PostgreSQL: server closed the connection unexpectedly
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
La connessione TCP è terminata senza un proper protocol goodbye. Due famiglie di cause molto diverse producono questo identico messaggio al client: qualcosa ha ucciso il lato server (crash, riavvio, out-of-memory), oppure un middlebox di rete ha silenziosamente scartato una connessione idle. Un controllo le separa: il log del server a quel timestamp.
Cosa significa questo errore
Leggi il log del server nel momento della disconnessione:
server process (PID ...) was terminated by signal 9: Killed→ l'OOM killer di Linux ha abbattuto un backend (confermalo indmesg). PostgreSQL poi si riavvia e disconnette brevemente tutti.terminating connection due to administrator command→ qualcuno (o systemd, o un failover) ha fermato intenzionalmente le cose.- Righe di crash-restart (
all server processes terminated; reinitializing) → un backend è crashato; guarda appena sopra per il motivo. - Nulla del tutto nel log → il server non ha mai saputo: un NAT gateway, un load balancer o un firewall ha scartato il flusso idle. Gli idle timeout dei load balancer di pochi minuti sono i colpevoli tipici.
Cause comuni
- Kill per OOM — spesso guidati dalle impostazioni di memoria:
work_memsi applica per nodo di sort/hash per query, quindi qualche query affamata di memoria su molte connessioni può moltiplicarsi ben oltre la RAM fisica. - Riavvii e failover (pianificati o meno) a metà connessione.
- Connessioni idle tagliate dai middlebox, che emergono come questo errore al prossimo uso di una connessione dal pool.
- Occasionalmente, un genuino bug del server che fa crashare un backend su una query specifica — controlla il log e le release notes della tua minor version.
Come diagnosticarlo
- Log del server al timestamp — decide tra le famiglie, come sopra.
- OOM sospetto:
dmesg | grep -i oome rivedi le impostazioni di memoria rispetto alla RAM disponibile. - Log silenzioso: misura da quanto tempo la connessione era idle prima di fallire; confronta con gli idle timeout di LB/NAT sul percorso.
Come risolverlo
- OOM → dimensiona correttamente la memoria (
work_memin particolare, data la sua natura moltiplicativa), limita il numero di connessioni con un pooler, e segui le indicazioni della documentazione sull'overcommit di memoria di Linux per host database dedicati. - Middlebox → abilita i TCP keepalive più aggressivi dell'idle timeout (server:
tcp_keepalives_idle; client:keepalives_idlenella stringa di connessione) e/o imposta la durata massima delle connessioni del pool sotto il timeout del middlebox. - Crash → aggiorna all'ultima minor version; se riproducibile sulle versioni attuali, è una segnalazione di bug.
🔍
Il cugino al momento della connessione: Connection refused — quando la connessione non viene mai stabilita.
