PostgreSQL Major Upgrades on RDS & Aurora: A Field Guide
Major version upgrades on Amazon RDS for PostgreSQL and Aurora PostgreSQL are the rare database operation that AWS deliberately keeps manual. There is a good reason: each major release can carry breaking changes, and AWS wants a human to sign off before the database switches formats. For Houston teams running energy trading, logistics, and healthcare systems, an upgrade that goes sideways during business hours is a non-starter. The fix is process, not luck. With a release-cadence tracker, a two-week pre-flight checklist, and Blue/Green Deployments for the risky jumps, a major upgrade becomes a routine maintenance event.
Know the Release Cadence Before You Commit
AWS announces new PostgreSQL engine versions — and, just as important, the end-of-support dates for old ones — on the RDS for PostgreSQL release notes page. AWS also publishes guidance on how new open source database engine versions land on Aurora and RDS, so you can plan upgrades around your own release calendar instead of reacting to a deprecation notice.
Check what your region actually offers before you plan anything:
aws rds describe-db-engine-versions \
--engine postgres \
--query "DBEngineVersions[].EngineVersion" \
--output text | tr '\t' '\n' | sort -V
The rule of thumb: never run more than one major version behind current, and schedule the jump while your current version still has a comfortable support window. That keeps the upgrade on your terms, not AWS’s.
Run the Pre-Flight Checks Two Weeks Out
Major upgrades are where extension compatibility bites. PostgreSQL core handles the migration; your extensions have to be ready for it. Start by listing what you actually use:
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE installed_version IS NOT NULL
ORDER BY name;
Then confirm every one of those has a version compatible with your target major release — pg_cron, PostGIS, pgvector, and friends all lag core from time to time. Next, build a fresh parameter group for the target version rather than reusing the old one; defaults change between majors, and stale settings cause mysterious regressions.
Disk space is the silent killer. RDS materializes the new data directory during the upgrade, so watch FreeStorageSpace in CloudWatch and keep headroom. Finally, rehearse: restore a recent snapshot into a staging instance, run the upgrade there, and execute your application test suite plus a pgbench smoke test before you touch production. Right before the window, take a manual final snapshot:
aws rds create-db-snapshot \
--db-instance-identifier orders-prod \
--db-snapshot-identifier orders-prod-pre-upgrade
aws rds describe-pending-maintenance-actions \
--filters "Name=db-instance-id,Values=orders-prod"
That second command shows the prechecks RDS runs for you — resolve anything flagged there before the window opens.
Execute the Upgrade
For an RDS for PostgreSQL instance, the upgrade is a modify call. Use the exact minor version AWS lists for your region (the 18.x below is a placeholder), and think hard about --apply-immediately versus letting it ride the maintenance window:
aws rds modify-db-instance \
--db-instance-identifier orders-prod \
--engine-version 18.x \
--allow-major-version-upgrade \
--apply-immediately
For an Aurora PostgreSQL cluster, the same idea targets the cluster:
aws rds modify-db-cluster \
--db-cluster-identifier orders-prod \
--engine-version 18.x \
--allow-major-version-upgrade \
--apply-immediately
Know what you are signing up for. On a Multi-AZ DB instance, RDS upgrades the primary and standby together, and the database can be unavailable for several minutes. Read replicas of a Multi-AZ DB instance are upgraded alongside the primary. The trap is Aurora Multi-AZ DB clusters: their read replicas drop into a terminated replication state, and you must delete and recreate them after the upgrade — build that into your runbook, not your post-mortem. The RDS for PostgreSQL upgrade documentation spells out the details for both deployment types.
Cut Downtime with Blue/Green Deployments
If a several-minute outage is too much — and for Houston’s 24/7 operations it often is — use RDS Blue/Green Deployments. Blue/Green builds a logically replicated staging environment, you run the major upgrade there, validate everything against production data, and then switch over with seconds of downtime. It is the single highest-leverage tool AWS has added for upgrade work, and it turns the scariest maintenance event into a reversible one.
Verify, Monitor, and Keep an Exit Plan
After the upgrade completes, verification is not optional. Confirm the version, check that extensions came along, and look for errors in the logs:
SELECT version();
SELECT extname, extversion FROM pg_extension ORDER BY extname;
SELECT pid, state, wait_event_type, wait_event
FROM pg_stat_activity
WHERE state = 'active';
Then re-run EXPLAIN on your top ten queries. Planner behavior changes between majors, and a query that used to be fast can pick a new plan. Watch CloudWatch for free space, connections, and replica lag during the burn-in window, and keep your rollback path warm: RDS does not auto-rollback, so the final snapshot — or the still-running blue environment — is your exit.
Treat the upgrade like a well-control exercise: know the pressure (the support timeline), test the equipment (staging), and keep the kill switch within reach. Do that, and Houston’s most demanding workloads get new PostgreSQL features without anyone noticing the maintenance window.
