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 conexión TCP terminó sin una despedida de protocolo adecuada. Dos familias de causas muy distintas producen este mensaje de cliente idéntico: algo mató el lado del servidor (crash, reinicio, out-of-memory), o un middlebox de red descartó silenciosamente una conexión inactiva. Una comprobación las separa: el log del servidor en ese timestamp.
Qué significa este error
Lee el log del servidor en el momento de la desconexión:
server process (PID ...) was terminated by signal 9: Killed→ el OOM killer de Linux disparó a un backend (confírmalo endmesg). PostgreSQL entonces reinicia y desconecta brevemente a todos.terminating connection due to administrator command→ alguien (o systemd, o un failover) detuvo las cosas intencionadamente.- Líneas de crash-restart (
all server processes terminated; reinitializing) → un backend crasheó; mira justo arriba por la razón. - Nada en absoluto en el log → el servidor nunca lo supo: un gateway NAT, un balanceador de carga o un firewall descartó el flujo inactivo. Los idle timeouts de balanceadores de carga de unos pocos minutos son culpables típicos.
Causas comunes
- Muertes por OOM — a menudo impulsadas por los ajustes de memoria:
work_memaplica por nodo de sort/hash por consulta, así que unas pocas consultas ávidas de memoria a través de muchas conexiones pueden multiplicarse mucho más allá de la RAM física. - Reinicios y failovers (planificados o no) a mitad de conexión.
- Conexiones inactivas cortadas por middleboxes, manifestándose como este error en el siguiente uso de una conexión del pool.
- Ocasionalmente, un bug genuino del servidor crasheando un backend en una consulta concreta — comprueba el log y las release notes de tu versión menor.
Cómo diagnosticarlo
- Log del servidor en el timestamp — decide entre las familias, como arriba.
- OOM sospechado:
dmesg | grep -i oomy revisa los ajustes de memoria contra la RAM disponible. - Log en silencio: mide cuánto tiempo había estado inactiva la conexión antes de fallar; compáralo con los idle timeouts de LB/NAT en la ruta.
Cómo solucionarlo
- OOM → dimensiona bien la memoria (
work_memespecialmente, dada su naturaleza multiplicativa), acota el número de conexiones con un pooler, y sigue las indicaciones de la documentación sobre el overcommit de memoria de Linux para hosts de base de datos dedicados. - Middlebox → habilita keepalives TCP más agresivos que el idle timeout (servidor:
tcp_keepalives_idle; cliente:keepalives_idleen la cadena de conexión) y/o configura la vida máxima de conexión del pool por debajo del timeout del middlebox. - Crashes → actualiza a la última versión menor; si es reproducible en versiones actuales, eso es un reporte de bug.
🔍
El primo del momento de conexión: Connection refused — cuando la conexión nunca llega a establecerse.
