53300

PostgreSQL 'too many clients' error: real fixes that work

PostgreSQL hits its max_connections limit and rejects new connections. Here's what actually causes it and the quick fixes I use on client servers.

You're mid-migration or maybe just trying to run a quick query, and bam—FATAL: sorry, too many clients already. Error code 53300. I've seen this kill production apps at 2 AM more times than I can count. Last month, a client's POS system ground to a halt because their inventory app kept opening connections and never closing them. The fix wasn't as simple as bumping a number.

Here's the thing: this error means PostgreSQL's max_connections setting is hit. But why it's hit matters more than the error itself. Let's go through the three most common causes, starting with the one that's easiest to fix.

Cause 1: max_connections is just too low for your workload

This is the most common scenario. You've got a small server, default settings, and suddenly you have a few apps plus some monitoring tools all connecting. Default max_connections is 100. That sounds like a lot, but each connection takes about 5-10 MB of RAM. And if you're running multiple apps—say, a web app, a cron job, and a BI tool—you can blow through 100 fast.

The fix: raise max_connections (but not blindly)

First, check your current setting:

SHOW max_connections;

If it's 100 and you're hitting the limit, you can raise it. But here's the catch: every connection eats memory. On a server with 4 GB RAM, going to 500 connections might swap your system to death. I always calculate it roughly: each connection uses about 2-5 MB (depends on your work_mem and other settings). So if you have 8 GB RAM, 200-300 connections is usually safe.

Edit postgresql.conf (usually in /etc/postgresql/16/main/ on Debian, or /var/lib/pgsql/16/data/ on RHEL):

max_connections = 200

Then restart PostgreSQL (or reload if you set it via ALTER SYSTEM):

sudo systemctl restart postgresql

But honestly, if you're hitting 100 with normal traffic, you might have a connection leak. Don't just crank it up—you'll hide the problem. The real fix is often Cause 2.

Cause 2: Application connection leaks (the silent killer)

This is the one that makes me angry. You've got an app that opens a connection, runs a query, and forgets to close it. Over time, connections pile up. I had a client whose Node.js app had a pool size of 50, but because they never called pool.end() in error paths, after a few days every connection was stuck. The server wasn't overloaded—it just had 100 zombie connections.

How to spot a leak

Run this query to see who's connected and for how long:

SELECT pid, usename, application_name, client_addr, state, now() - state_change AS idle_time
FROM pg_stat_activity
WHERE state = 'idle'
ORDER BY idle_time DESC;

If you see dozens of idle connections that have been idle for hours, you've got a leak. Especially if they're from the same application_name.

The fix: find and fix the leak

First, kill the zombies to get back online:

SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle' AND now() - state_change > INTERVAL '5 minutes';

Then go fix your code. In most languages, use a connection pool with a timeout. For example, in Python with psycopg2:

from psycopg2 import pool

conn_pool = pool.SimpleConnectionPool(1, 20, dbname='mydb')
# Always return the connection
conn = conn_pool.getconn()
try:
    cur = conn.cursor()
    cur.execute('SELECT 1')
finally:
    conn_pool.putconn(conn)

The key is the finally block. If you're using an ORM like SQLAlchemy, set pool_pre_ping=True and a reasonable pool_recycle.

Also, check for long-running transactions. A transaction that never commits holds a connection. Use SELECT * FROM pg_stat_activity WHERE xact_start IS NOT NULL to find them.

Cause 3: Too many connections from a single client or middleware

Sometimes it's not a leak—it's just that your app or a tool like a reporting dashboard opens way too many connections. I saw a Tableau server that opened 50 connections per user. With 10 users, that's 500 connections. The database wasn't the problem; the client was.

The fix: use a connection pooler like PgBouncer

The real solution for high connection counts is to put a pooler in front of PostgreSQL. PgBouncer is the go-to. It multiplexes thousands of client connections into a small pool (say, 20) that actually hits the database. Your app thinks it's talking to Postgres directly, but PgBouncer is sitting in the middle.

Install it (on Ubuntu):

sudo apt install pgbouncer

Configure /etc/pgbouncer/pgbouncer.ini:

[databases]
mydb = host=127.0.0.1 port=5432

[pgbouncer]
listen_addr = 127.0.0.1
listen_port = 6432
default_pool_size = 20
max_client_conn = 1000

Then point your app to port 6432 instead of 5432. This is the cleanest way to handle 500+ connections without killing your database server.

Alternatively, if you can't install PgBouncer, you can lower idle_in_transaction_session_timeout in PostgreSQL to force connections to die if they sit idle too long. But that's a band-aid.

Quick-reference summary

CauseSymptomFix
max_connections too lowError even with low traffic, SHOW max_connections under 200Increase max_connections in postgresql.conf, restart
Connection leakMany idle connections in pg_stat_activityTerminate idle, fix app code to close connections
Too many clients per appHigh connection count from one sourceInstall PgBouncer, set pool size

If you're getting this error repeatedly, don't just google and copy a setting. Look at your actual connection usage first. The query I gave above will tell you everything you need. And if you're on a managed service like RDS, you can't change max_connections directly—you'll need to use a pooler or reduce your app's connections.

One last thing: always set connection_limit in your connection strings if your app framework supports it. Things like psycopg2 let you cap the pool. It's one less thing to panic about later.

Related Errors in Database Errors
0X80190029 Fix STATUS_NO_TXF_METADATA (0X80190029) on SQL Server 0X00000884 0X00000884: Service Database Locked — The Real Fix 0XC0000212 STATUS_TRANSACTION_NO_MATCH (0XC0000212) – Quick Fix for Transport Token Mismatch 1452 Foreign Key Constraint Violation Error — Quick Fix

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.