PostgreSQL gives every client connection its own server process, and max_connections caps how many may exist at once. The default is 100. When all slots are in use, the next connection attempt fails with this message and your site shows a database error until a slot frees up.
FATAL: sorry, too many clients already
FATAL: remaining connection slots are reserved for non-replication superuser connections
The second message means the normal slots are gone and only the reserved ones remain. Both mean the same thing for your application. For the MySQL equivalent, see too many connections.
Step 1: see who is using the slots
Connect as a superuser. The reserved slots exist so you can still get in:
SHOW max_connections;
SELECT count(*) FROM pg_stat_activity;
SELECT usename, datname, state, count(*)
FROM pg_stat_activity
GROUP BY usename, datname, state
ORDER BY count(*) DESC;
The state column tells the story:
- Many
idle: an application or pool is holding connections open and not using them. The most common cause. - Many
idle in transaction: code opened a transaction and never committed or rolled back, which is worse because it also holds locks and blocks vacuum. - Many
active: the database is genuinely busy, probably with slow queries stacking up.
Find the oldest offenders:
SELECT pid, usename, application_name, state,
now() - state_change AS in_state, left(query, 80) AS query
FROM pg_stat_activity
WHERE state <> 'active'
ORDER BY in_state DESC
LIMIT 20;
Step 2: free slots right now
To get breathing room during an incident, end idle sessions:
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state IN ('idle', 'idle in transaction')
AND state_change < now() - interval '10 minutes'
AND pid <> pg_backend_pid();
This disconnects clients. A well-behaved pool reconnects, but a careless one may throw errors, so be selective.
Step 3: add automatic limits
These prevent a leak from taking the server down again:
ALTER SYSTEM SET idle_in_transaction_session_timeout = '60s';
ALTER SYSTEM SET idle_session_timeout = '15min'; -- PostgreSQL 14 and newer
SELECT pg_reload_conf();
You can also cap a single role so one service cannot starve the others:
ALTER ROLE reporting CONNECTION LIMIT 10;
Step 4: fix the real cause in the application
Add up how many connections your clients can open. Each web worker, queue worker and cron job can have its own pool. With 10 app servers and a pool size of 20, you request 200 connections against a limit of 100.
- Pool too large. Match the total (servers times workers times pool size) to what the database can serve. A database does not usually run faster with hundreds of connections; many more than a few per CPU core often just queue.
- Leaks. Connections opened per request and never closed, or exceptions that skip the cleanup. Use context managers or
finallyblocks, and check your framework's pool "checked out" metrics. - Serverless or short-lived workers that open a new connection per invocation. Put a pooler in front.
- Long-running queries that keep connections busy. Fix them or add indexes.
Step 5: use a connection pooler
PgBouncer sits between your app and PostgreSQL and multiplexes many client connections onto a small number of server connections. A minimal pgbouncer.ini:
[databases]
appdb = host=127.0.0.1 port=5432 dbname=appdb
[pgbouncer]
listen_port = 6432
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 20
In transaction mode, session features such as prepared statements, SET, advisory locks and LISTEN need care. Check the PgBouncer documentation for how your driver should be configured. Point the application at port 6432.
Step 6: raise max_connections last
If you truly need more slots:
ALTER SYSTEM SET max_connections = 200;
This change requires a full restart of PostgreSQL, so plan a maintenance window. Each connection costs memory (including work_mem per sort or hash operation), so more connections mean you must reduce other settings or add RAM. On a standby, max_connections must be at least as large as on the primary. The reserved slots are controlled by superuser_reserved_connections, default 3; newer versions also have reserved_connections, so read the documentation for your version.
Verify
Watch the count over a busy period:
SELECT count(*) FILTER (WHERE state = 'idle') AS idle,
count(*) FILTER (WHERE state = 'idle in transaction') AS idle_tx,
count(*) AS total
FROM pg_stat_activity;
Alert before you hit the ceiling, say at 80 percent. Check the front end with the Website Health Check and use an Uptime Monitor with a keyword check on a database-backed page to catch the error page. A scheduled job that opens connections can be tracked with cron monitoring.
Next steps
- If connections fail for another reason, see connection refused on 5432.
- Locks causing pile-ups? Read deadlock detected.
- Authentication trouble instead: password authentication failed.
- Check network reachability with the Port Checker.
FAQ
What is the default max_connections in PostgreSQL?
- Managed services often set it based on instance size, so check yours with
SHOW max_connections;.
Does idle in transaction matter more than idle?
Yes. An idle-in-transaction session keeps locks and prevents cleanup of old row versions, so one forgotten transaction can cause bloat and blocking, not just a lost slot.
Do I need a restart to change max_connections?
Yes. Most other settings here reload with pg_reload_conf(), but max_connections needs a restart.
Is PgBouncer required?
Not always. Fix leaks and right-size pools first. A pooler becomes valuable once many app instances or short-lived processes connect.
Get notified when this fix updates
Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.
This page is general information written by our editorial team and updated when documentation changes. Servers and providers differ, so test changes safely first. See our editorial policy and disclaimer.