PostgreSQL has become the default open source database of the industry, and Flexible Server is Azure’s serious answer for running it managed: your VNet, your maintenance window, zone redundant HA, and the knobs a real Postgres workload needs. Here is the production configuration conversation.
Compute, Storage, and the Autogrow Safety Net
Three compute tiers: Burstable for dev and tiny workloads (credits run out under sustained load, never production), General Purpose for most OLTP, Memory Optimized when your working set or connection count demands it. Storage scales independently with autogrow, and storage tier IOPS scale with provisioned size, so a database that is small but hot sometimes needs a larger storage allocation purely for the IOPS. Turn autogrow on everywhere: Postgres filling its disk goes read only at best, and the incident is always at night.
resource "azurerm_postgresql_flexible_server" "this" {
name = "psql-orders-prod"
resource_group_name = azurerm_resource_group.data.name
location = "westeurope"
version = "16"
sku_name = "GP_Standard_D4ds_v5"
storage_mb = 262144
auto_grow_enabled = true
backup_retention_days = 35
geo_redundant_backup_enabled = true
delegated_subnet_id = azurerm_subnet.psql.id
private_dns_zone_id = azurerm_private_dns_zone.psql.id
public_network_access_enabled = false
zone = "1"
high_availability {
mode = "ZoneRedundant"
standby_availability_zone = "2"
}
authentication {
active_directory_auth_enabled = true
password_auth_enabled = false
tenant_id = data.azurerm_client_config.current.tenant_id
}
maintenance_window {
day_of_week = 0
start_hour = 2
start_minute = 0
}
}
Networking follows the series pattern with a twist: Flexible Server offers VNet integration via a delegated subnet (shown above) or private endpoints; new designs increasingly prefer private endpoints for consistency with everything else, and the delegated subnet model cannot be changed after creation, so decide deliberately. Entra only authentication kills password sprawl, applications connect with managed identity tokens.
HA, Failover Honesty, and Replicas
Zone redundant HA runs a synchronous standby in another zone: zero data loss on failover, and planned failovers (which you should rehearse) complete in well under a minute. The honesty part: synchronous replication costs write latency, roughly doubling the cost per plan compute, and unplanned failover still means a connection storm as everything reconnects, so applications need retry logic with backoff regardless. Read replicas are asynchronous, up to five, promotable, and the standard tools for read scaling and cross region DR; just remember async means the replica is behind by its lag metric, and reads there must tolerate it.
Connections deserve their own paragraph. Postgres connections are processes, expensive at scale, and a fleet of microservices each holding a pool exhausts max_connections fast. Enable the built in PgBouncer (port 6432, transaction pooling mode) and point services at it; a thousand client connections multiplex onto tens of server connections and the problem disappears for most workloads.
Tuning and Operations
Server parameters are exposed properly: shared_buffers and work_mem sized to the tier defaults are sane starts, but set log_min_duration_statement (500 ms is a good opener) and enable pg_stat_statements, then make query store style review a weekly habit: top statements by total time, fix the worst, repeat. Index bloat and autovacuum tuning matter on high churn tables, watch dead tuple counts and adjust per table autovacuum settings rather than global ones. Upgrade path: in place major version upgrades exist, but rehearse on a restored copy first, extensions are the usual snag. And backups: 35 day retention with geo redundant backup gives point in time restore plus a cross region story, and the monthly restore drill from the backup post applies here with full force, a database team that has never restored is a database team with a theoretical database.
Cheers
Osama
Leave a comment