PostgreSQL
Conexiones, sesiones y pooling
Ciclo de vida de conexiones y sesiones, estado persistente, límites de concurrencia y uso de pools como PgBouncer o pools de aplicación.
- Última actualización
- Actualizada
- Nivel
- Aplicación
PostgreSQL
Ciclo de vida de conexiones y sesiones, estado persistente, límites de concurrencia y uso de pools como PgBouncer o pools de aplicación.
Una conexión PostgreSQL es una sesión con memoria, transacciones, prepared statements, settings y recursos del servidor. El pool reutiliza sesiones; no las vuelve stateless.
Cada conexión directa suele corresponder a un backend process. Mantiene:
search_path, timezone y settings.Abrir una conexión por query es costoso; abrir demasiadas agota memoria y scheduler.
requests de aplicación
→ pool limitado
→ conexiones PostgreSQLEl pool reduce handshakes y controla concurrencia. No debe dimensionarse como “una conexión por request máximo”.
En múltiples replicas de la app:
pool por instancia × número de instancias + jobs + admin + monitoring
≤ capacidad segura de PostgreSQLUn autoscaling puede multiplicar conexiones inesperadamente.
Vive dentro de cada proceso. Simple y conoce transacciones del cliente.
Centraliza conexiones. Modos:
Transaction pooling rompe supuestos sobre estado de sesión entre transacciones.
const client = await pool.connect();
try {
await client.query('BEGIN');
// todas las queries con client
await client.query('COMMIT');
} catch (error) {
await client.query('ROLLBACK');
throw error;
} finally {
client.release();
}No uses pool.query entre BEGIN y COMMIT: puede elegir conexiones distintas.
Antes de devolver una conexión, no debe quedar:
Usa SET LOCAL dentro de transacciones. Algunos pools pueden ejecutar reset, pero no dependas de una limpieza parcial desconocida.
Distingue:
statement_timeout.lock_timeout.idle_in_transaction_session_timeout.Una request puede pasar más tiempo esperando pool que ejecutando SQL. Mide ambos.
Cuando el pool está lleno, la cola debe ser limitada. Una cola ilimitada convierte una base lenta en uso creciente de memoria y timeouts tardíos.
Patrón:
pool saturado
→ rechazar/limitar trabajo
→ proteger baseRetries indiscriminados agravan el incidente.
Empieza con un número pequeño y mide throughput, CPU, waits y latencia. Más conexiones pueden reducir rendimiento por context switching y contención.
Para workloads CPU-bound, decenas de conexiones activas pueden ser suficientes aunque existan miles de usuarios.
Conexiones idle consumen slots y memoria, pero no equivalen a idle in transaction.
idle: sesión disponible sin transacción.idle in transaction: transacción abierta, problemática.Configura idle timeout del pool para adaptarse a proxies/serverless, sin crear churn excesivo.
Muchas instancias efímeras pueden crear connection storms. Usa:
No abras una nueva conexión por invocation si existe un mecanismo de reutilización seguro.
No confíes entre transacciones en:
SET persistente.Verifica compatibilidad específica de driver y PgBouncer para prepared statements modernos.
SELECT 1 verifica que una conexión responde, no que el sistema está listo para carga.
Readiness puede considerar:
No ejecutes checks agresivos desde cada instancia cada segundo.
Cerrar el proceso abruptamente puede dejar queries ejecutándose hasta detectar desconexión y produce resultados inciertos cerca del commit.
Mide:
pg_stat_activity states.Configura application_name por servicio/worker.
max_connections.SET tenant persistente.application_name.Prepared statements y plan cache equilibra reutilización de planificación con sensibilidad a parámetros.