PostgreSQL: server closed the connection unexpectedly
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The TCP connection ended without a proper protocol goodbye. Two very different families of causes produce this identical client message: something killed the server side (crash, restart, out-of-memory), or a network middlebox silently dropped an idle connection. One check separates them: the server log at that timestamp.
What this error means
Read the server log for the moment of the disconnect:
server process (PID ...) was terminated by signal 9: Killed→ the Linux OOM killer shot a backend (confirm indmesg). PostgreSQL then restarts and briefly disconnects everyone.terminating connection due to administrator command→ someone (or systemd, or a failover) intentionally stopped things.- Crash-restart lines (
all server processes terminated; reinitializing) → a backend crashed; look just above for the reason. - Nothing at all in the log → the server never knew: a NAT gateway, load balancer or firewall dropped the idle flow. Load-balancer idle timeouts of a few minutes are typical culprits.
Common causes
- OOM kills — often driven by memory settings:
work_memapplies per sort/hash node per query, so a few memory-hungry queries across many connections can multiply far past physical RAM. - Restarts and failovers (planned or otherwise) mid-connection.
- Idle connections cut by middleboxes, surfacing as this error on the next use of a pooled connection.
- Occasionally, a genuine server bug crashing a backend on a specific query — check the log and the release notes for your minor version.
How to diagnose it
- Server log at the timestamp — decides between the families, as above.
- OOM suspected:
dmesg | grep -i oomand review memory settings against available RAM. - Log silent: measure how long the connection had been idle before failing; compare against LB/NAT idle timeouts in the path.
How to fix it
- OOM → right-size memory (
work_memespecially, given its multiplicative nature), bound connection counts with a pooler, and follow the documentation's guidance on Linux memory overcommit for dedicated database hosts. - Middlebox → enable TCP keepalives more aggressive than the idle timeout (server:
tcp_keepalives_idle; client:keepalives_idlein the connection string) and/or set the pool's max connection lifetime below the middlebox timeout. - Crashes → update to the latest minor version; if reproducible on current versions, that is a bug report.
🔍
The connect-time cousin: Connection refused — when the connection never gets established at all.
