PSA: postgres 14 deprecation is july 1. I migrated 2.1 tb without downtime last week. here's what almost broke.
posting because i googled "supabase postgres 14 to 17 migration" two weeks ago and the only result was the changelog entry. now i've done it on a real database, here's the field report.
why this is urgent
july 1, 2026: any project still on pg14 gets auto-upgraded. if your project uses an extension that doesn't exist on pg17, supabase pauses the project (no traffic served) until you remove the extension. this is in the changelog but easy to miss.
i checked our project: pg14, ~2.1 tb, 4 extensions, some of which were on the "deprecated in pg17" list. ticking clock.
the prep work
- ran select * from pg_extension to inventory extensions. cross-referenced against the supabase extension support matrix (it's in the docs but not on the changelog). found one deprecated extension (plpython3u in our case, used by exactly one stored function from 2 years ago). removed the function, dropped the extension.
- inventoried queries that depended on pg14-specific syntax. there are a few subtle ones. our worst offender: a select ... from json_to_recordset(...) that worked on pg14's looser type inference but errored on pg17 because the jsonb column had nulls in a field declared int. fixed by adding coalesce.
- ran vacuum analyze on every hot table the day before. pg17 collects stats differently and you want a baseline.
- checked for unsupported wire-protocol differences. our orm (drizzle) was fine. our reporting tool (metabase, oldish version) was not — it was using a prepared statement style that pg17 deprecated. updated metabase first.
the actual migration
used supabase's in-place upgrade flow from the dashboard. project settings → infrastructure → upgrade postgres version.
zero downtime in the sense of "your project keeps serving traffic." about 90 seconds of degraded performance during the cutover where replication catches up. our supavisor buffered everything and clients didn't notice.
total wall clock: 47 minutes. mostly waiting.
what almost broke
- a materialized view that referenced a function we'd dropped during the extension cleanup. the upgrade tried to refresh it and choked. recovered after we drop-cascaded the mv.
- our nightly pg_dump backup script was pinned to pg14's pg_dump binary. first dump after upgrade was incompatible. updated the script to use the version-matching binary.
- extensions.pgcrypto had a subtle behavior change in random byte generation. one of our token generators was producing slightly different distributions. not a security problem in our case but i was glad i tested.
what i wish i'd done first
- a real staging branch. branching 2.0 went GA the same week so i could have spun up a fresh branch on pg17, run all our queries against it, and seen the issues before touching prod. i did this on my second project this week and it was night-and-day calmer.
- run the migration on a low-traffic day. we did it on tuesday afternoon because that's when our traffic dips. saturday would have been even better.
should you wait
no. the deprecation is a hard deadline and the "if you use a deprecated extension we pause your project" line is not a bluff. start the prep this week. you don't want to be the person doing this at 11pm on june 30.
happy to share the extension-inventory query and the metabase config diff if useful.