FATAL: sorry, too many clients already — every slot allowed by the server's
max_connections is taken, usually by connections an application opened and
never closed. Find who holds them in pg_stat_activity, make the code dispose each
connection (await using), and size the pools so all your apps together stay under
the limit.
Its sister message, remaining connection slots are reserved for roles with the SUPERUSER
attribute, is the same situation seen by an ordinary role: the last few slots are kept
for superusers, so an administrator can still log in and look.
The error
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: sorry, too many clients already
From Npgsql 10.0.3, as a superuser and as an ordinary role:
Unhandled exception. Npgsql.PostgresException (0x80004005): 53300: sorry, too many clients already
Unhandled exception. Npgsql.PostgresException (0x80004005): 53300: remaining connection slots are reserved for roles with the SUPERUSER attribute
Why it happens
max_connections is fixed when the server starts, and each open connection holds
one slot until it is closed. The test server ran with max_connections=5 and the
default superuser_reserved_connections of 3. A loop that opened connections with
Pooling=false and kept them got two as the ordinary role
shopapp before the reserved-slots message, and five as postgres
before the sixth failed.
With pooling on, which is Npgsql's default, a leak shows up in the client first. With
Maximum Pool Size=2 the third open waited and then threw
The connection pool has been exhausted, either raise 'Max Pool Size' (currently 2) or
'Timeout' (currently 3 seconds) in your connection string. The server error appears
when several apps or instances each keep a pool, whose default maximum is 100, and their sum
passes the server's limit.
The fix
First see who holds the slots, from a superuser session:
SELECT usename, application_name, client_addr, state, count(*)
FROM pg_stat_activity
WHERE backend_type = 'client backend'
GROUP BY 1, 2, 3, 4;
usename | application_name | client_addr | state | count
----------+------------------+-------------+--------+-------
postgres | psql | | active | 1
shopapp | OrderWorker | 172.17.0.1 | idle | 2
(2 rows)
Idle connections from one application are the classic leak. Set
Application Name=OrderWorker in each app's connection string and this view names
the culprit. Then dispose every connection, so it goes back to the pool after each use:
await using var conn = new NpgsqlConnection(cs);
await conn.OpenAsync();
await using var cmd = new NpgsqlCommand("SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'client backend'", conn);
Console.WriteLine($"query {i}: {await cmd.ExecuteScalarAsync()} client connection(s) on the server");
query 1: 1 client connection(s) on the server
query 2: 1 client connection(s) on the server
query 3: 1 client connection(s) on the server
query 4: 1 client connection(s) on the server
query 5: 1 client connection(s) on the server
query 6: 1 client connection(s) on the server
query 7: 1 client connection(s) on the server
query 8: 1 client connection(s) on the server
query 9: 1 client connection(s) on the server
query 10: 1 client connection(s) on the server
Ten queries in a loop used one server connection. Raise the limit only after that, and mind
where it is set: ALTER SYSTEM SET max_connections = 20 plus a restart still left
SHOW max_connections at 5, because pg_settings reported the source as
command line, the container's -c max_connections=5, which beats
postgresql.auto.conf. Change the -c value in your
docker run or Compose file instead.
How it was reproduced
A postgres:18 container (PostgreSQL 18.4) on Docker 29.9.2 under Windows 11,
started with -c max_connections=5, plus a login role shopapp. A .NET
10 console app (SDK 10.0.403, Npgsql 10.0.3) opened connections in a loop and kept them;
another mode held them for 60 seconds while psql 18.4 connected from inside the container. The
names fix7-pgmax, shopapp and OrderWorker are this test's own, and the container was removed
afterwards.
Frequently asked
- How do I fix FATAL: sorry, too many clients already in PostgreSQL?
- Find who holds the connections with SELECT usename, application_name, state, count(*) FROM pg_stat_activity GROUP BY 1, 2, 3. Fix the application that leaks them by disposing every connection, keep each app's Maximum Pool Size small enough that all apps together fit, and only then raise max_connections, which needs a server restart.
- What does remaining connection slots are reserved for roles with the SUPERUSER attribute mean?
- The server has only its reserved slots left, superuser_reserved_connections, 3 by default, and they are kept for superusers. An ordinary role gets this message where a superuser would still connect. It is the same shortage as too many clients already, so the fix is the same.
- How do I see the max_connections setting and where it comes from?
- Run SHOW max_connections, or SELECT setting, source FROM pg_settings WHERE name = 'max_connections'. A source of command line means it was passed with -c, for example in docker run, and ALTER SYSTEM will not override it.
More decoded errors in the Fixes category. The same
pg_stat_activity view finds the session that blocks
DROP DATABASE
when it is being accessed by other users.