PostgreSQL: "too many clients", pg_hba refusals and a database that will not start
PostgreSQL is explicit about why it refuses a connection. The message names the rule or the limit, and the log is authoritative.
What you see
Applications report a connection error naming one of these messages, or the service will not start after a crash or a disk-full event.
What is actually wrong
The client limit, a missing or mismatched pg_hba.conf rule, or write-ahead log damage after an unclean shutdown.
Codes and articles
Fixes (3)
Add pooling rather than raising the limit
"sorry, too many clients already".
See the limit and what is connected.
sudo -u postgres psql -c 'SHOW max_connections'sudo -u postgres psql -c "SELECT state, count(*) FROM pg_stat_activity GROUP BY state"
Look for connections idle in transaction — these hold locks and are far worse than idle ones.
sudo -u postgres psql -c "SELECT pid, usename, state, now()-state_change AS age, LEFT(query,60) FROM pg_stat_activity WHERE state <> 'idle' ORDER BY age DESC LIMIT 20""Idle in transaction" for minutes means the application opened a transaction and went away. It blocks vacuum and holds locks, and no amount of extra connections fixes the underlying bug.
Terminate a stuck session only when you understand what it was doing.
sudo -u postgres psql -c "SELECT pg_terminate_backend(12345)"Install a connection pooler rather than raising max_connections. PostgreSQL uses a process per connection and does not scale the way a threaded server does.
sudo apt install pgbouncerRaising max_connections to several hundred costs memory per connection and increases contention. PgBouncer in transaction mode lets hundreds of application connections share a few dozen real ones, which is the standard answer.
Set an idle transaction timeout so this cannot recur silently.
sudo -u postgres psql -c "ALTER SYSTEM SET idle_in_transaction_session_timeout = '60s'"sudo -u postgres psql -c 'SELECT pg_reload_conf()'
sudo -u postgres psql -c "SELECT state,count(*) FROM pg_stat_activity GROUP BY state"Write the right pg_hba rule
"no pg_hba.conf entry for host" or an authentication failure.
Find the file in use — there may be more than one installation.
sudo -u postgres psql -c 'SHOW hba_file'sudo -u postgres psql -c 'SHOW config_file'
Read the current rules. They are evaluated top to bottom and the first match wins, so a broad reject above your rule silences it.
sudo grep -vE '^\s*#|^\s*$' $(sudo -u postgres psql -Atc 'SHOW hba_file')First match wins is the part that catches people. Adding a correct rule at the bottom of the file does nothing if a earlier line already matched that host and method.
Add a specific rule with the narrowest address range that works.
echo 'host appdb appuser 10.0.0.0/24 scram-sha-256' | sudo tee -a /etc/postgresql/16/main/pg_hba.confReload rather than restart — pg_hba is re-read without dropping connections.
sudo -u postgres psql -c 'SELECT pg_reload_conf()'Check the server is listening on the address at all — listen_addresses defaults to localhost.
sudo -u postgres psql -c 'SHOW listen_addresses'sudo ss -tlnp | grep 5432
sudo -u postgres psql -c 'SELECT line_number,type,database,user_name,address,auth_method,error FROM pg_hba_file_rules'Recover a cluster that will not start
The service fails to start after a crash, a disk-full event or a power loss.
Read the log. PostgreSQL states the reason clearly and the right action depends entirely on which reason it is.
sudo journalctl -u postgresql@16-main -n 60 --no-pagersudo tail -60 /var/log/postgresql/postgresql-16-main.log
If the disk is full, free space before anything else — PostgreSQL cannot recover while it cannot write.
df -hsudo du -sh /var/lib/postgresql/16/main/pg_wal
Take a full filesystem-level copy of the data directory before any repair attempt.
sudo systemctl stop postgresqlsudo tar -C /var/lib/postgresql/16 -czf /root/pgdata-backup.tar.gz main
Everything below can make things worse. With this copy, a failed repair costs an hour; without it, it can cost the database.
Do not run pg_resetwal as a first response. It discards transactions and produces a cluster that starts but may be inconsistent — it is a last resort for a database with no backup, and the correct next step afterwards is to dump and reload into a fresh cluster.
This command appears in a lot of quick answers and it is genuinely dangerous. It makes a broken cluster start, which looks like success and can hide silent corruption for weeks.
Restore from backup if one exists — that is faster and safer than any repair.
sudo -u postgres pg_restore --list /backups/latest.dump | headIf pg_resetwal is genuinely the only option, dump everything immediately afterwards and reload into a new cluster.
sudo -u postgres pg_dumpall > /root/emergency-dump.sql
sudo systemctl status postgresql --no-pagersudo -u postgres psql -c 'SELECT count(*) FROM pg_database'
Related faults
Where this stops. This write-up was written and checked by hand. It says what each step changes, how to confirm it worked and how to reverse it, and anything destructive is flagged before you reach it. If it does not match what your machine is doing, search the Support Centre for the exact code or message — and when something needs a person, get in touch.