ArmorDB Logo
ArmorDB
Fix Postgresql Too Many Clients Already Error
How to Fix PostgreSQL `too many clients already` Errors
Back to Blog
Quick Fixes
May 19, 2026
8 min read

How to Fix PostgreSQL `too many clients already` Errors

A short fix guide for connection-limit errors, idle sessions, and when to add PgBouncer instead of raising max_connections.

AE
ArmorDB EngineeringArmorDB engineering
PostgreSQLConnectionsPgBouncer

When PostgreSQL says too many clients already, it is refusing new connections because the server has reached its configured connection limit. That usually means one of three things: the application is opening too many connections, a worker pool grew faster than expected, or idle sessions were left hanging around long enough to crowd out new work. The fix is usually not to touch the database first. It is to find the connection source, reduce pressure at the app layer, and only then decide whether a higher limit is justified.

The fastest way to think about this error is to separate symptoms from capacity. max_connections is a hard ceiling on concurrent connections, and PostgreSQL sizes some resources directly from it. That means increasing it is not free. A managed platform can make the limit easier to understand, but it still pays to treat connection count as a design choice, not a default you only notice during an outage.

What the error usually means

The message is rarely about a single bad query. It usually means the database has more active or idle client sessions than it can safely accept. In practice, the problem comes from a bursty release, a misconfigured app pool, too many workers, or a leak that keeps connections open after work is done.

PostgreSQL also keeps a small number of slots reserved for superusers and roles with reserved-connection privileges. That is deliberate. It lets administrators still get in during saturation instead of locking out the very people who need to fix the issue.

How to spot the source quickly

Use the database itself to answer two questions: how many connections are open, and which service owns them. The exact query can vary, but the pattern is the same.

show max_connections;
select count(*) from pg_stat_activity;
select usename, application_name, state, count(*)
from pg_stat_activity
group by 1, 2, 3
order by 4 desc;

That last query usually tells the story. If one service owns most of the sessions, its pool is probably too large. If you see many rows in idle or idle in transaction, the application is holding connections longer than it should. If the spike appears only during deploys or traffic bursts, the pool size may be harmless in isolation but too large once several services are running together.

SymptomLikely causeFirst check
Error appears during deploysNew replicas or workers multiplied poolsCount connections by application_name
Error comes and goes during spikesBursty traffic or serverless fan-outLook for many short-lived sessions
Many sessions sit idleThe app leaves connections openSearch for idle and idle in transaction
Admin can still connectReserved slots are doing their jobUse the admin role, not the app role

The fastest fix sequence

Start with the least risky change. If a deployment just rolled out, scale the app back, restart the leaking worker, or reduce the per-process database pool before you touch the database settings. If a background job is the source, stop that job until you know why it is holding connections.

If the app is healthy but the traffic pattern is not, put PgBouncer in front of PostgreSQL. PgBouncer is built for exactly this kind of pressure. In transaction pooling mode, a server connection is released back to the pool after each transaction, which lets many clients share fewer database connections. That is usually the right fit for web requests and short-lived work.

ArmorDB includes PgBouncer by default, and the connection guide shows how to use it cleanly: /docs/connect and /docs/pgbouncer. If your app has separate web, worker, and admin paths, pool them differently instead of giving every process the same large limit.

Only raise max_connections when you understand the tradeoff. PostgreSQL says this setting can only be changed at server start, and increasing it raises memory usage for the server. If the database is already near its practical limit, a larger number can hide the symptom while making recovery harder.

When raising the limit is actually the right move

There are cases where a higher limit is justified. A shared database that serves many small internal apps, a legacy workload that cannot be pooled immediately, or a temporary migration window may need more headroom. Even then, the right move is usually to raise the limit carefully after checking memory, not to turn it into the new default forever.

OptionGood whenTradeoff
Reduce app pool sizesA few services are over-connectingRequires deploy changes and coordination
Add PgBouncerRequests are short and burstySession-heavy features need review
Raise max_connectionsYou have clear headroom and a real needMore shared memory and a bigger blast radius

A practical rule of thumb

If you are seeing this error once and the app has a clear bug, fix the bug. If you are seeing it whenever traffic rises, fix the connection model. If you are seeing it because the project has grown past the old defaults, add pooling first and sizing second. That order keeps the system simpler and avoids paying for a larger database just to make a connection leak less visible.

The main mistake to avoid is using max_connections as the first response to every spike. A bigger ceiling can buy time, but it does not solve pool misconfiguration, leaked sessions, or poor worker math. The stable pattern is conservative app pools, short transactions, and a pooler between unpredictable clients and PostgreSQL.

Sources / further reading

  • PostgreSQL documentation on connection settings, including max_connections, reserved_connections, and superuser_reserved_connections
  • PostgreSQL documentation on pg_stat_activity and the cumulative statistics views
  • PgBouncer documentation on pool_mode and server connection reuse
  • ArmorDB docs for connection setup and PgBouncer

Takeaway

too many clients already is a capacity signal, not just an error string. Find which service owns the connections, shrink the largest pools, add PgBouncer when the workload is bursty, and only raise max_connections when you know why the extra headroom is needed.

Topic

Quick Fixes

Updated

May 19, 2026

Read time

8 min read

About the author

ArmorDB Engineering writes about PostgreSQL operations, security, and infrastructure decisions for teams building production apps on ArmorDB.