Question: Connections and sessions
Why is opening a Postgres connection so slow?
Answered in the first paragraph. Last updated .
Because the server forks a new process for every client. The documentation describes the model plainly: a supervisor waits for connections and starts a separate backend for each one. That backend then authenticates you, loads the catalog information it needs, and builds its private memory before it can answer anything. On an idle server the whole sequence is a few milliseconds. Under load it is the first thing to degrade.
What the milliseconds are spent on
Process creation is only the first item. Authentication can dominate it, and does whenever it involves anything off the machine: a directory service, an identity provider, or a certificate exchange each add a round trip that has nothing to do with the database. Name resolution on the client side belongs in the same bucket and is invisible from the server entirely.
Then the new backend has to warm up. It reads catalog entries for the objects your first statements touch and caches them privately, which is why the first query on a fresh connection is reliably slower than the second and why a schema with very many tables makes connecting measurably worse.
From PostgreSQL 18 you can stop guessing at the split. The connection logging switch stopped being a simple on or off and can now report how long the individual setup stages took, which turns an argument about whether authentication is slow into a number in the log.
Why this becomes an incident rather than an annoyance
Connection setup competes for the same cores as the queries already running. When the server is saturated, connecting gets slower, application timeouts fire, clients retry, and every retry costs another fork. That is a connection storm, and it is the failure mode where a database that was merely busy becomes unreachable.
The structural answer is to stop opening connections on the request path. A pool keeps a small number of long-lived backends and hands them out, so the fork and the warm-up happen at startup rather than per request. It also makes the cost of your worst authentication configuration a one-time cost instead of a per-call one. Connection pooling and PgBouncer covers the modes and which one an application’s transaction patterns can survive.
One warning about tuning in the wrong direction: if connections are slow because the server is saturated, allowing more of them makes both problems worse. How many connections Postgres can handle is the arithmetic for choosing that ceiling.