A few hundred connections, mostly idle, and the whole server gets slower. That was Postgres for as long as I remember it: a process per connection, and past some count the snapshot bookkeeping starts to eat everything.

PostgreSQL 14 is released today. I had the RC on a test box for a week, so a few notes from a backend seat. The headline for me is that this internal work got a serious rewrite. On our connection-heavy profile, many workers, short queries, lots of idle time, the difference is visible without squinting. Idle connections finally cost close to what people always assumed they cost.

Does this retire pgbouncer? No. A pooler still turns thousands of client connections into tens of server ones, still smooths spikes, still saves you when a deploy doubles the worker count. Version 14 makes the penalty for imperfect pooling smaller. It does not make pooling optional. With PHP moving to long-lived workers the topic stops being theoretical: every worker is a standing connection now.

Also in the release: vacuum keeps getting better at not falling behind on write-heavy tables, and libpq got pipeline mode, several queries in flight without waiting for each round trip. PHP drivers will need time to expose that one. The foundation is there.

The usual caution. Release notes describe someone else’s benchmark. “Better under high concurrency” means nothing for your system until you look at your own waits, your own throughput, your own vacuum lag. Upgrade a replica, replay something close to real traffic, then decide what the new version gave you. Sometimes the honest answer is “two percent”, and that is still a fine reason. Just know your number.

Ours was more than two percent. I will not say how much, because I do not fully trust my test box either.