PostgreSQL error: sorry, too many clients already
FATAL: sorry, too many clients already
Every connection slot on the server is taken, so PostgreSQL refuses the new one. The server is otherwise healthy — it is simply full. A close variant of the same problem is the message about "remaining connection slots are reserved": the last few slots are held back for superusers so an administrator can still get in and fix things.
What this error means
PostgreSQL accepts at most max_connections concurrent connections (default: 100), and reserves a handful of those (superuser_reserved_connections, default: 3) for superusers. When a regular client asks for a connection beyond the non-reserved limit, it gets this FATAL at connect time — the connection is refused, nothing else on the server is affected.
Each connection is a dedicated server process with its own memory, so the limit exists for a reason: PostgreSQL does not handle thousands of direct connections gracefully. That's why the durable fix is almost never "raise the number".
Common causes
- No connection pooler in front of the database, with many application instances each opening its own pool. Ten services × 20 connections each = 200 before any traffic spike.
- Connection leaks: code paths that open connections and never return them to the pool.
- Sessions stuck in
idle in transactionholding slots (and locks, and vacuum progress) indefinitely. - Serverless / autoscaling workers, each opening fresh connections per invocation.
- A slowdown elsewhere: if queries suddenly take 10× longer, connections pile up as callers time out and retry. The error is the symptom; the slow query is the disease.
How to diagnose it
Connect as a superuser (this is what the reserved slots are for) and look at who holds the slots:
SHOW max_connections;
SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state ORDER BY count(*) DESC;
SELECT usename, application_name, count(*)
FROM pg_stat_activity
GROUP BY 1, 2 ORDER BY count(*) DESC;
-- Sessioni in transazione da più tempo (candidati leak):
SELECT pid, usename, state, now() - xact_start AS xact_age, left(query, 60)
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
ORDER BY xact_start
LIMIT 10;
Lots of idle connections point at oversized or leaking application pools; old idle in transaction sessions point at application code that opened a transaction and wandered off.
How to fix it
- Put a pooler in front (PgBouncer in transaction mode is the standard answer): thousands of client connections multiplex onto a few dozen server connections. This is the fix that scales; check first that your workload doesn't rely on session state (session-level
SET, advisory locks, prepared statements across transactions) that transaction pooling doesn't preserve. - Fix the leaks: bound every pool (max size, max lifetime, idle timeout) and make sure connections are returned in
finally-style cleanup. - Cap the damage server-side:
ALTER ROLE app_user CONNECTION LIMIT 50; ALTER SYSTEM SET idle_in_transaction_session_timeout = '5min'; SELECT pg_reload_conf(); - Raise
max_connectionsonly deliberately (requires a restart): each slot is a process with real memory cost, and hundreds of active backends usually perform worse than a pooled few dozen.
idle in transaction sessions don't just eat slots: they hold back vacuum for the whole database.
