PostgreSQL 19: REPACK, WAIT, and a planner you can finally argue with
PostgreSQL 19 merges VACUUM FULL and CLUSTER into REPACK, adds a WAIT command for catching a standby up, and ships two extensions that pin planner decisions. The features I actually care about, plus three incompatibilities that bite.
PostgreSQL 19’s documentation is still rolling (the release notes still show the date as pending), but the overview has settled. A few entries that will genuinely change day-to-day operations:
REPACK: VACUUM FULL and CLUSTER in one command
Reclaiming disk space meant VACUUM FULL; rewriting a table in index order meant CLUSTER. Both take an exclusive lock. 19 merges them into a single REPACK, and adds a CONCURRENTLY option that reorganises without blocking reads or writes.
The point is not the shorter syntax. It is that reorganising a large table moves from requires downtime to schedule it whenever. Rewriting a few-hundred-gigabyte table used to mean announcing a maintenance window.
WAIT: read your own writes on a replica
Primary/replica setups have always had an awkward edge: write to the primary, immediately read a replica, and the row may not be there. The new WAIT command blocks until a standby has replayed changes up to a chosen point — read-your-writes, on the standby.
That beats “sleep 200ms and retry” by a wide margin, and it is cheaper than routing every read to the primary.
The planner can be pinned
Two new extensions: pg_plan_advice stabilises and controls the query planner’s decisions, and pg_stash_advice applies that advice automatically based on the query.
Plan drift is an old wound — the same SQL runs fine yesterday, statistics update overnight, and today it picks a catastrophic plan. The previous answers were third-party extensions like pg_hint_plan or rewriting the SQL. Now the core ships an official mechanism.
Replication and vacuuming
- Logical replication now replicates sequence values, and can be enabled without a server restart when
wal_levelisreplica - Autovacuum can use parallel workers to vacuum a table’s indexes, with a new scoring system deciding which tables most need it
- The number of I/O worker processes scales automatically, and foreign-key checks are faster
The “no restart” part matters more than it sounds. Enabling logical replication used to mean changing wal_level and restarting — on a busy primary, that is a scheduled event.
Three incompatibilities that bite
Know these before upgrading:
- RADIUS support removed. The stated reason is blunt: it only supported RADIUS over UDP, which is “unfixably insecure”. If your auth chain uses RADIUS, plan a replacement.
standard_conforming_stringsis forced on in the server. Dumps produced by pre-19pg_dump/pg_dumpallwithstandard_conforming_strings = offwill not load correctly into 19 and later. Dump with 19+ tooling.- Carriage returns and line feeds are disallowed in database, role, and tablespace names.
pg_upgradechecks for this.
Two smaller ones: a new password_expiration_warning_threshold (default seven days), and a warning after successful MD5 password authentication, disableable via md5_password_warnings. MD5 passwords were marked deprecated back in 18.
Where I land
Of the four headline items, REPACK ... CONCURRENTLY and WAIT change how you operate. The planner-advice extensions are a receipt for something people had been bolting on for years.
The real risk is in the compatibility list. RADIUS was removed because it is insecure — and PostgreSQL has consistently been more willing than most projects to delete a feature for correctness. If RADIUS sits anywhere in your auth path, this upgrade is not a “someday” item.

Comments
…