For about fifteen years, the standard answer to “this table is bloated, what do I actually do about it” has been one of the out-of-tree options: pg_repack (the extension), pg_squeeze (Antonin Houska’s predecessor work), or a hand-rolled CREATE TABLE AS and swap. PG19 changes that. The new built-in REPACK command absorbs the work VACUUM FULL and CLUSTER already did, and a CONCURRENTLY flag — built on top of the logical-decoding machinery pg_squeeze originally pioneered — does it without holding an access-exclusive lock.

depesz has done the work:

The first walks through the non-concurrent form, which is essentially “what you already do with VACUUM FULL, with one new piece of syntax.” Read it for completeness.

The second is the operationally interesting one. Hubert built a 200-million-row table, deleted 80% of the rows, and ran REPACK ... CONCURRENTLY while a workload ticked inserts every half-second from a second session. Inserts went from a 1.5 ms average baseline to 5.5 ms average and a 63 ms max during the rebuild, then settled to ~9.5 ms afterward. A real, measurable, tolerable cost… and the data point you do not get by reading the patch thread.

A few caveats the patches have already exposed: REPACK CONCURRENTLY consumes a replication slot for the duration; there is a still-in-flight fix for the deferrable-PK fallback case; and a pgsql-hackers thread on compressed-TOAST corruption under specific paths is unresolved. Beta 1 will be the moment to start exercising this in earnest. Not before.

Out-of-tree pg_repack is not obsolete tomorrow. It is on a clock.