On this page
  1. What does the error actually mean?
  2. What are the quick fixes?
  3. What is the permanent fix?
  4. Where AI coding assistants get this wrong
  5. Checklist
  6. FAQ
    1. How many connections does my app actually need?
    2. Is raising max_connections a good fix?
  7. Related topics
  8. Sources
tutorial

How to Fix 'Too Many Connections' in Postgres

'Too many connections' means your app exhausted Postgres's connection limit. Learn the real causes, the quick fixes, and the permanent ones.

Quick answer

  • The error means your app holds more Postgres connections than max_connections allows.
  • Quick fixes: restart the app (drops leaked connections) and find what’s opening per-request connections.
  • Permanent fix: a proper connection pool sized to your limit, or PgBouncer in transaction mode for many instances.

What does the error actually mean?

Postgres has a hard cap on concurrent connections — max_connections defaults to 100 (managed databases often set 100-400). When a request tries to open one more, Postgres rejects it: ‘FATAL: remaining connection slots are reserved for non-replication superuser connections’. The app’s requests start failing even though the database is healthy. The cause is almost always connection mismanagement in the app: a new connection per request, connections never closed, or pools sized without accounting for how many app instances exist.

What are the quick fixes?

Three immediate moves. First, restart the app — leaked connections drop with the process, which usually restores service while you find the root cause. Second, check active connections to see who’s holding them: SELECT count(*), usename, application_name FROM pg_stat_activity GROUP BY 1, 2. Third, if the database itself allows it, raising max_connections buys time — but it’s a band-aid: each connection consumes memory, and a raising it past the server’s resources makes things worse.

# Who is holding connections? Run as a superuser.
psql -c "SELECT count(*), usename, application_name \
  FROM pg_stat_activity GROUP BY 1, 2 ORDER BY 1 DESC;"

# Kill idle connections from a specific app (emergency only)
psql -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity \
  WHERE application_name = 'myapp' AND state = 'idle';"

What is the permanent fix?

Give the app a real connection pool — your framework’s pool (SQLAlchemy, Prisma, node-postgres) with a size that fits the budget: pool size per instance times the number of instances must stay under max_connections with headroom. If you run many instances or serverless functions, put PgBouncer in front of Postgres in transaction mode, which lets thousands of app connections share a few dozen real database connections. Then monitor pg_stat_activity and pool wait times so the next exhaustion is visible before it’s an outage.

Where this bites vibecoders

The most common ‘works locally, dies in production’ story: the AI-generated app opens a fresh connection per request (or never closes them), the demo works, and the first real traffic spike exhausts Postgres’s limit. The assistant rarely generates pooling because it doesn’t see the production concurrency. The fix is usually a few lines — reuse one engine, size the pool — plus understanding that each instance’s pool counts separately.

Where AI coding assistants get this wrong

  • Creating a new database connection inside every request handler.
  • Never closing connections, leaking them until the limit is hit.
  • Setting a huge pool size, transferring the exhaustion from the app to the database.
  • Ignoring the count of app instances when sizing pools, so 10 instances x 50 connections blows the limit.

Checklist

  • Restart the app and check pg_stat_activity to see who holds connections.
  • Use the framework’s pool, sized per instance to fit max_connections.
  • For many instances or serverless, add PgBouncer in transaction mode.
  • Monitor connection usage so the next exhaustion is visible early.

FAQ

How many connections does my app actually need?

Enough to serve peak concurrency, and rarely more than a few dozen per instance. Each Postgres connection costs memory and CPU, so more isn’t better — a pool of 10-20 per instance serves most web apps, and a proxy handles the rest.

Is raising max_connections a good fix?

Only as a stopgap. Every connection consumes server memory, so raising the limit past what the machine can hold causes crashes and slow queries. The durable fix is pooling: fewer, reused connections instead of more of them.

Sources

Share: