Introduction
PostgreSQL 11 has reached its end of life, and Azure recommends upgrading to PostgreSQL 13 or later for enhanced security, improved performance, and long-term support. Unlike minor upgrades, Azure Database for PostgreSQL (Flexible Server) does not support in-place major version upgrades. This makes the upgrade process slightly non-trivial—especially when the server is provisioned using Terraform, and some environments use VNet integration.
In this blog, we’ll walk through:
- How Azure PostgreSQL upgrades work
- Why does Terraform recreate the server
- Multiple migration strategies
- The exact steps I followed to upgrade PostgreSQL 11 → 13 safely
Existing Setup
My environment had the following characteristics:
- Azure Database for PostgreSQL – Flexible Server
- PostgreSQL version: 11
- SKU: Burstable B1ms (1 vCore, 2 GiB RAM)
- Storage: 32 GiB
- Region: Central US
- Provisioned using Terraform
- Mixed environments: Some with public access, some with VNet integration
- Firewall rules restricted to specific IPs
Terraform snippet (simplified):
Important Reality: No In-Place Major Version Upgrade
This is the most critical thing to understand: Azure PostgreSQL Flexible Server does NOT support in-place major version upgrades.
That means:
- You cannot upgrade PostgreSQL 11 → 13 on the same server
- Changing version = "13" in Terraform:
- Deletes the existing PostgreSQL 11 server
- Creates a brand-new PostgreSQL 13 server
- All data is lost unless you migrate or restore it manually
Terraform makes this very clear: forces replacement. This is not really an upgrade — it’s a rebuild and a migration.
Why This Upgrade Looks Simple — and Why It Isn’t
At first glance, the upgrade appears trivial: version = "13"But behind this single line:
- Azure treats PostgreSQL major versions as immutable
- Terraform maps this to a ForceNew operation
- Automated backups are tied to the old server lifecycle
- Configuration and data do not carry over
What Actually Happens (Timeline)
Understanding the timeline helps avoid surprises:T-0: PostgreSQL 11 running
- Applications connected
- Data live
- Automated backups available
T-1: Terraform version updated
- version = "11" → version = "13"
- Plan shows forces replacement
T-2: Terraform apply
- PostgreSQL 11 server is deleted
- Databases and backups disappear
T-3: PostgreSQL 13 server created
- Empty server
- Default parameters
- No firewall rules
- No databases
T-4: Manual restore
- Data restored
- Configuration reapplied
- Applications reconnect
Available Upgrade Approaches
1. Azure Database Migration Service (DMS)
2. Backup & Restore (pg_dump / pgAdmin)
3. Temporary Public Access
Step 1: Take a Backup
I used pgAdmin 4 with a custom format backup.Why Custom format?
- Includes schema + data
- Best compatibility across versions
- Works cleanly with pg_restore
pg_dump `
-h myserver.postgres.database.azure.com `
-U pgsqladmin@myserver `
-d master_data_service `
-Fc `
--sslmode=require `
-f master_data_service_v11.dump
Step 2: Upgrade PostgreSQL Version via Terraform
In Terraform, change the code: version = "13"Important: This destroys the PostgreSQL 11 server and creates a new PostgreSQL 13 server with the same name.
Run:
terraform plan
terraform apply
This immediately destroys the PostgreSQL 11 server and creates a new PostgreSQL 13 server with the same name.
Step 3: Restore the Database to PostgreSQL 13
pg_restore `
-h myserver.postgres.database.azure.com `
-U pgsqladmin@myserver `
-d postgres `
--create `
-Fc `
--sslmode=require `
master_data_service_v11.dump
This:
- Recreated the database
- Restored schema and data
- Worked cleanly from v11 → v13
Step 4: Server Parameters & Configuration
Azure applies default server parameters when a new PostgreSQL server is created.
Key learning:
- Server parameters are NOT automatically migrated
- If you changed parameters manually in the portal, you must reapply them
Step 5: VNet-Integrated Environments
For servers with VNet integration:
- No public endpoint exists
- Local pgAdmin / pg_dump won’t connect
Available options:
- Use Azure DMS inside the VNet
- Use a VM or jumpbox
- Temporarily enable public access
We temporarily enabled public access with strict /32 firewall rules and disabled it immediately after migration.
/32 firewall rules and disabled it immediately after migration.Step 6: Validate & Cutover
After restoring:
- Verified tables, row counts, and extensions
- Tested application connectivity
- Updated connection strings where required
- Disabled public access again for private environments
Cost Considerations
- PostgreSQL B1ms server: ~$25/month
- Temporary overlap or migration time: a few dollars
- Azure DMS (Standard): Often free for migration scenarios
- Overall upgrade cost: minimal
Key Takeaways
- Azure PostgreSQL major upgrades are not in-place
- Terraform recreates the server when version changes
- Always backup before upgrading
- Server parameters must be reapplied
- For VNet setups, plan connectivity carefully
- PostgreSQL supports direct jump from 11 → 13
Final Thoughts
Upgrading PostgreSQL on Azure requires careful planning, but with the right approach, it can be a predictable and safe process.If you’re using Terraform:
- Treat major version upgrades as rebuild + restore
- Automate as much as possible
- Test in lower environments first

No comments:
Post a Comment