Connections, sessions, and transactions
Every connection is a server process. Read pg_stat_activity to see who holds them and why, and contain clients that leak.
A connection is a process
When a client connects, PostgreSQL forks a backend process for it. That process holds memory for sorting, hashing, and caching, whether the client is busy or not. max_connections is therefore a capacity limit. A small host with a large limit does not get more throughput, it gets swapping. The last superuser_reserved_connections slots are kept for superusers, so when ordinary roles are refused an administrator can still connect and investigate. That is why, during a "too many clients" incident, your psql as postgres still works.
Read before you kill
pg_stat_activity has one row per backend. Group it by usename, application_name, and state, and look at xact_start to see how long each transaction has been open:
SELECT usename, state, count(*), min(xact_start) AS oldest
FROM pg_stat_activity WHERE backend_type = 'client backend'
GROUP BY 1, 2 ORDER BY 3 DESC;
idle means connected and doing nothing, which is cheap but still occupies a slot. idle in transaction means a transaction is open and the server is waiting for the client to send the next statement or a COMMIT. Such a session keeps its slot, holds any row locks it took, and pins an old snapshot that stops VACUUM from cleaning up. Dozens of them from one role usually mean a code path that forgets to commit or to return connections to a pool.
Contain the client, then fix it
pg_terminate_backend(pid) ends a session at once. It frees slots, but a leaking client opens new sessions just as fast. Containment means the server enforces limits on the client:
ALTER ROLE reconciler CONNECTION LIMIT 5caps how many sessions that role may hold. When it hits the cap, only that client gets errors.ALTER ROLE reconciler SET idle_in_transaction_session_timeout = '30s'makes the server end that role's sessions that sit in an open transaction for too long.- A connection pooler in front of many application servers keeps the number of real backends small and steady.
Raising max_connections is the last resort. It needs a restart, costs memory on every connection, and a leak fills whatever number you pick. Containment buys time. The real fix is in the client, so file the bug with the evidence from pg_stat_activity.
Key terms
- Backend
- The server process PostgreSQL starts for each client connection.
- Idle in transaction
- A session that began a transaction and is waiting for the client. It holds its slot, its snapshot, and any locks.
- Reserved connections
- Slots only superusers may use, so an administrator can still log in when ordinary roles cannot.
- Connection pooler
- A proxy such as PgBouncer that shares a few server connections among many clients.
Read further
- PostgreSQL Documentation, version 17, Chapter "Server Configuration", sections "Connections and Authentication" and "Client Connection Defaults" (Free online (PostgreSQL Licence))
max_connections, superuser_reserved_connections, and the timeouts that end idle or stuck sessions. - PostgreSQL Documentation, version 17, Chapter "Monitoring Database Activity", the pg_stat_activity view (Free online (PostgreSQL Licence))
The state column, xact_start and state_change, and how to group sessions to find the client that holds them. - PostgreSQL Documentation, version 17, SQL command reference, ALTER ROLE (Free online (PostgreSQL Licence))
CONNECTION LIMIT and per-role settings such as idle_in_transaction_session_timeout.