Quick answer: Check your current connection count with SELECT count(*) FROM pg_stat_activity;, then either increase max_connections in postgresql.conf or hunt down the leaked connections that are hogging slots.
You're running a query and suddenly PostgreSQL slams the door: FATAL: sorry, too many clients already. Infuriating, I know. It means your server is at its hard limit for concurrent connections—the max_connections setting—and it's refusing new ones. Most of the time it's not that you truly need 500 connections; it's that some app left a bunch of idle connections hanging around. Or your connection pool is misconfigured. Or you genuinely have a busy app that needs more room. We'll sort it out.
Step 1: See How Many Connections Are Actually Open
Log into your PostgreSQL server and run this:
SELECT count(*) FROM pg_stat_activity;
That tells you the current total. If you're stuck and can't even connect, you can still connect as a superuser sometimes—PostgreSQL reserves a few slots for superusers. If that also fails, you'll need to restart or increase the limit from the OS level (we'll get there).
To see who's connected and what they're doing, try:
SELECT pid, usename, application_name, client_addr, state, query FROM pg_stat_activity;
Look for the usual suspects: a web app with a pool size of 100, a monitoring tool that refreshes every second, or a cron job that never closes its connection. The state column will show idle for connections that are just sitting there—those are prime candidates for leaks.
Step 2: Kill Idle Connections (If You're in a Jam)
If you need to free up slots right now, terminate idle sessions. Use this to kill every idle connection that's been hanging around for over 5 minutes:
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle' AND datname = 'your_db' AND pid <> pg_backend_pid();
Replace your_db with your actual database name. This is a blunt instrument—it'll kick out anyone who's not actively running a query. If a connection is mid-query, it won't be killed because state will be active. So it's safe enough.
But this is a band-aid. If the leak is real, they'll pile up again in no time.
Step 3: Find the Real Culprit
Run a query to group connections by application or user:
SELECT application_name, usename, count(*) FROM pg_stat_activity GROUP BY application_name, usename ORDER BY count(*) DESC;
If you see one app with 200 connections when it should have 20, that's your leak. Common causes:
- Connection pool size too large — A Java app with HikariCP set to 50, but you have three instances, that's 150 connections. Each app instance should have its own pool size that matches its needs.
- Connections not returned — Your code opens a connection and never closes it. Happens all the time with ORMs if you're not careful.
- Long-running transactions — A transaction left open holds a connection forever. Look for
state=idle in transaction.
If you spot an app that's leaking, fix the code. If it's a pool issue, tune the pool size. I've seen a Rails app with pool: 25 in database.yml suddenly spike to 200 because of a background job that opened a new connection for every task. Took me two days to find it—don't be like me.
Step 4: Increase max_connections (When You Really Need It)
If your app legitimately needs more connections, you can raise the limit. Edit postgresql.conf (usually /etc/postgresql/14/main/postgresql.conf on Debian/Ubuntu, or /var/lib/pgsql/14/data/postgresql.conf on RHEL/CentOS). Find the line:
#max_connections = 100
Uncomment and change it, say to 200:
max_connections = 200
Then restart PostgreSQL:
sudo systemctl restart postgresql
But here's the kicker: each connection consumes memory. You can't just jack it up to 1000 on a cheap VPS. Roughly, each connection takes about 2–5 MB of memory for things like work_mem and sort buffers. Check your available RAM first. If you have 4 GB, 200 connections might be fine. But 500 could be tight.
Also, if you raise max_connections, you may need to bump up shared_buffers and other memory settings—but that's a rabbit hole. Start with doubling the value and monitor performance.
Step 5: Adjust Connection Pooling (Better Long-Term Fix)
Instead of letting every app connect directly, put a pooler in front. PgBouncer is the classic choice. It can handle thousands of client connections while maintaining a small pool of real PostgreSQL connections, like 20–50. This is the real fix for a busy app—not cranking up max_connections to the sky.
Install and configure PgBouncer with a minimal config:
# pgbouncer.ini
[databases]
your_db = host=127.0.0.1 port=5432
[pgbouncer]
listen_port = 6432
listen_addr = 127.0.0.1
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 20
Then point your app to port 6432 instead of 5432. Your app sees a pool of 1000 connections, but PostgreSQL only handles 20. That's a game changer.
If the Main Fix Fails
Sometimes you can't even connect as a superuser because all slots are taken. Then you have to restart PostgreSQL from the command line:
sudo systemctl restart postgresql
Or if that's not possible, kill the postmaster process:
sudo pkill -9 postgres
Then start it again. This will drop all connections and give you breathing room. But it's a sledgehammer—do it only if you have no other choice.
Another quick hack: you can set a lower idle_in_transaction_session_timeout and statement_timeout in postgresql.conf to automatically close sessions that hang. That prevents future pile-ups.
idle_in_transaction_session_timeout = 60000 # 1 minute
statement_timeout = 30000 # 30 seconds
Prevention Tips
Set up monitoring so you see connection counts climbing before they hit the wall. Use pg_stat_activity queries in a cron job, or use a tool like Nagios or Datadog. Also, make it a habit to check for idle connections in your dev environment—if you see them, your code is leaking.
And please, don't just crank max_connections to 5000. It treats the symptom, not the disease. Use PgBouncer, fix your pool sizes, and keep your code honest about closing connections. Your PostgreSQL server will thank you.