The migration, PRD by PRD
The trail of changes since the upstream fork: the milestone azure-migration issues in order, each paired with the code it produced. How Mike went from hosted-Supabase SaaS to a single-tenant Azure deployment.
Parent docs
docs/Postgres/001-database-platform-and-sku.md docs/infra/001-network-topology.md docs/infra/003-secrets-and-identity.md docs/infra/004-bicep-and-manual-provisioning.md
What to build
Provision Azure Database for PostgreSQL Flexible Server with private-only network access. No public IP, no firewall rules — reachable exclusively through the private endpoint created alongside it.
Bicep module infra/modules/postgres.bicep:
- Flexible Server, Postgres 16, SKU driven by
pgSkuparameter (Standard_B1msBurstable for dev,Standard_B2sfor prod initial). publicNetworkAccess: 'Disabled'.- Storage:
pgStorageGbGiB, autogrow off initially. - Backup retention:
pgBackupRetentionDays(7 dev / 35 prod). - Admin user:
mikeadmin, password generated by deploy and stored as Key Vault secretpostgres-admin-password(this secret slot is removed in015-managed-identity-db-auth.md). - Private Endpoint in
subnet-pe; DNS zone group linked toprivatelink.postgres.database.azure.com(zone created in001). - Built-in PgBouncer enabled; backends connect on port 6432. Migration runner connects on port 5432 direct (DDL incompatibility with transaction-mode pooling).
pgcryptoextension noted as required; enabled in the initial migration (slice 004).
Runbook steps 4–5 in docs/infra/004-bicep-and-manual-provisioning.md must stay in sync with the module.
Data migration decision: This is a fresh-start Azure deployment. No Supabase data export/import is in scope for this slice. If production data needs carrying over, that is a separate operational runbook handled after the full auth cutover (slice 013) when Entra OIDs are known and user-ID translation can be done.
Acceptance criteria
- [ ] Flexible Server provisioned;
az postgres flexible-server showconfirmspublicNetworkAccess: Disabled. - [ ] Private endpoint exists in
subnet-pe; private DNS A record resolves to the private IP from within the VNet. - [ ]
postgres-admin-passwordsecret populated in Key Vault; server reachable viapsql -h <private-fqdn> -p 5432 -U mikeadminfrom a container inside the VNet. - [ ] PgBouncer reachable on port 6432 from within the VNet.
- [ ] No public FQDN resolves to the server from outside the VNet.
Blocked by
001-bicep-infra-foundation.md(VNet, subnets, private DNS zone, Key Vault must exist)
User stories addressed
- Database is not reachable from the public internet.
- Dev and prod use different SKUs from the same template.
- Server can be stopped in dev to avoid idle charges.