A nightly import, a few hundred million rows through COPY, then reporting queries in the morning. That is the only workload I care about, so that is how I read the PostgreSQL 16 release notes: with one pipeline in mind and everything else skipped.

Three items survived the filter.

COPY got faster, noticeably when several loads run at once. Our import is exactly this shape, parallel COPY streams into partitioned tables. I will take the free speed. But the old lesson stays: if your import still does row-by-row INSERT from PHP, no Postgres release will save you. Batch into COPY first, then talk about versions.

pg_stat_io. One view with I/O by backend type: how much reading and writing comes from queries, from autovacuum, from the checkpointer. Until now we assembled this picture from indirect signals and guesswork. First morning on the test upgrade it showed that autovacuum, not the import, produces most of the write traffic on one table. We suspected this for months. Now it is a number. For me this view alone pays for the upgrade.

Logical replication grew up. A standby can now be a source, and big transactions are applied in parallel on the subscriber. If a search index or analytics is fed from replication, the lag behind a fat import transaction was the classic problem. Worth retesting.

The method behind this is boring. Never read a database changelog abstractly. Benchmarks in the announcement are someone else’s workload. Take your slowest pipeline, upgrade a test environment, run it, open the new statistics views. Two evenings.

I have read release notes cover to cover before. I remembered none of it a week later.