FATAL: sorry, too many clients already

PostgreSQL 'Too Many Clients Already' — Fix the Connection Limit

Postgres hit its max_connections cap and won't accept new clients. Raise the limit, kill idle sessions, and fix the app that's leaking connections.

Quick answer

Your Postgres server has hit max_connections and is refusing new clients. You need to disconnect idle sessions, raise the limit, and figure out why connections aren't being returned. This is rarely a Postgres bug — it's almost always an app or pooler issue.

What's actually happening

Postgres has a hard ceiling on simultaneous client connections. The default is 100. Every backend connection is a real OS process (not a thread), and each one eats a few hundred KB of memory plus has its own working memory. When you hit the cap, the server flatly refuses new logins with FATAL: sorry, too many clients already and that's it — no graceful degradation, no queue.

You'll see this most often in three situations. First, an application leaks connections — usually a Django/FastAPI/Express app with a connection pool that doesn't return connections on exceptions. Second, a midnight cron job or reporting script opens 50 connections in a burst and never closes them. Third, someone bumped a connection pool's max_size in dev without thinking about prod. We saw this exact thing at a client last year when their Celery workers went from 4 to 32 replicas overnight — every worker wanted 20 connections, and 640 requests hit a 100-connection Postgres.

Step-by-step fix

Step 1: Confirm you're actually hitting the limit

Open a terminal and check the current connection count. If you can't connect as a normal user, connect as postgres via local socket (the superuser slot is usually reserved).

psql -U postgres -c "SELECT count(*) FROM pg_stat_activity;"
psql -U postgres -c "SHOW max_connections;"

If count(*) is at or near max_connections, you've confirmed it. Don't guess — measure.

Step 2: See who's hogging connections

This query groups connections by state and user. Idle connections are the usual suspects.

SELECT usename, state, count(*)
FROM pg_stat_activity
GROUP BY usename, state
ORDER BY count DESC;

You'll usually see a wall of idle — meaning clients connected but aren't doing anything. That's the app not returning connections.

Step 3: Kill idle connections

Don't just kill everything — kill idles that have been sitting for a while. Anything idle for more than 10 minutes with no transaction in flight is safe to terminate.

SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle'
  AND state_change < now() - interval '10 minutes'
  AND pid <> pg_backend_pid();

After running that, you should see pg_stat_activity drop by dozens. New connections should start succeeding immediately. If they don't, verify with SELECT count(*) FROM pg_stat_activity; again.

Step 4: Raise max_connections (temporarily)

This buys you breathing room, not a fix. Set it in postgresql.conf:

max_connections = 200

Then reload — a full restart isn't required for this parameter on PostgreSQL 9.5+:

pg_ctl reload -D /var/lib/postgresql/data

Or from inside psql: SELECT pg_reload_conf();. After reload, SHOW max_connections; should return the new value. Verify by connecting a second time in a new terminal.

Be careful here. Each connection is a process. Going from 100 to 500 on a 2 GB RAM box is a great way to trigger the OOM killer and take down Postgres entirely. Rule of thumb: keep memory for connections under 25% of total RAM.

Step 5: Put PgBouncer in front

This is the real fix for most production setups. PgBouncer in transaction pooling mode lets 1000 app threads share 20 actual Postgres connections. Install it, then a minimal pgbouncer.ini:

[databases]
mydb = host=127.0.0.1 port=5432 dbname=mydb

[pgbouncer]
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 20
reserve_pool_size = 5

Point your app at PgBouncer's port (6432 by default) instead of 5432. Restart PgBouncer, then connect through it. You should see the same throughput with way fewer real backends — check pg_stat_activity and the count should be flat.

If the main fix doesn't hold

Find the leaking application

If connections climb back to the limit within an hour, you have a leak. This query shows the source IP and app name:

SELECT client_addr, application_name, count(*)
FROM pg_stat_activity
GROUP BY client_addr, application_name
ORDER BY count DESC;

If one IP is responsible for 80 connections, that's your culprit. Common causes: SQLAlchemy sessions not closed in a finally block, Node's pg pool missing pool.end(), or a Spring Boot HikariCP with maximumPoolSize set to something absurd like 100.

Set idle timeouts as a safety net

These two settings automatically kill connections that are sitting idle. They don't fix the leak, but they stop it from taking down your database at 3 AM.

idle_in_transaction_session_timeout = '5min'
idle_session_timeout = '30min'

idle_session_timeout requires PostgreSQL 14 or later. Reload the config and verify with SHOW idle_session_timeout;.

Check for stuck transactions

If you see idle in transaction states in pg_stat_activity, you've got an app that opened a transaction and forgot to commit. That's worse than a plain idle connection because it holds locks. Kill these first:

SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle in transaction'
  AND state_change < now() - interval '5 minutes';

Prevention

Don't just raise max_connections and walk away — that's how you end up with a 4 GB Postgres eating 30 GB of swap. Put PgBouncer (or pgpool-II) in front of Postgres from day one on anything with more than a handful of app instances. Set idle_session_timeout to 30 minutes so runaway clients get reaped automatically. And monitor pg_stat_activity — a simple alert when count(*) > 0.8 * max_connections gives you a warning before users start seeing errors. The connection limit error is almost never Postgres's fault. It's a signal that something upstream is holding connections it shouldn't.

Related Errors in Database Errors
0X00000998 Fix 0X00000998: Can't Add User to Accounts Database 0X8004D083 XACT_E_TRANSACTIONCLOSED (0x8004D083) Fix: Log Discarded Error 0X00001A91 Fix RM_NOT_ACTIVE (0X00001A91) on Windows Server Cannot open database requested by the login. Login failed Fix 'Cannot open database requested by the login. Login failed' in SQL Server

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.