PRODPlataforma BaaS soberana europeaAbrir panel →

Rendimiento · 9 lectura mínima

Postgres max_connections sin un agrupador

Affane Daylami · Fondateur · 6 de junio de 2026

volver al blog

Sin agruparse frente a su servidor, max_connections debería cubrir todas las conexiones de cliente abiertas al mismo tiempo, no la cantidad de solicitudes que Postgres puede procesar de manera eficiente en paralelo. Confundir estos dos números es la causa más común de max_connections configurados incorrectamente: demasiado bajo para absorber la carga o demasiado alto para la memoria realmente disponible.

Este texto en inglés se generó automáticamente a partir del original en francés y aún no ha sido revisado.
Esta página fue traducida automáticamente. La versión en inglés es autorizada.

Este artículo brinda la fórmula publicada por la wiki de PostgreSQL para calcular la concurrencia ideal de su hardware (la fórmula de tamaño del grupo de conexiones más citada en el ecosistema), explica por qué cada conexión cuesta más que un subproceso de aplicación y luego detalla el procedimiento para configurar max_connections sin adivinar. Nuestra metodología de referencia documenta el protocolo de medición utilizado para cualquier afirmación de rendimiento en este blog.

Lo esencial

  • Sin agrupación, max_connections debería cubrir todas las conexiones de clientes simultáneas, no solo aquellas que Postgres puede procesar eficientemente en paralelo.
  • Fórmula de referencia de la wiki de PostgreSQL: concurrencia activa ideal = (núcleos físicos × 2) + discos eficientes. Un punto de partida que debe ser validado mediante mediciones, no un límite estricto.
  • max_connections es un parámetro de contexto postmaster: cambiarlo requiere un reinicio completo del servidor, no una simple recarga.
  • Cada conexión de Postgres es un proceso de sistema separado, no un hilo liviano: esto es lo que hace que la sobrecarga sea real tan pronto como aumenta el número de conexiones.
  • Verificado en el código: en sus clústeres de Postgres dedicados, Aurabase varía max_connections de 50 (nivel gratuito) a 400 (nivel empresarial) según el tamaño del clúster.
#
Diagnóstico

Por qué una conexión Postgres cuesta más que un hilo de aplicación

Postgres no utiliza un grupo de subprocesos ligero para sus conexiones. Cada conexión de cliente desencadena un proceso de sistema completo.

El proceso postmaster crea uno nuevo ("fork") para cada intento de conexión, dedicado a esta sesión única hasta que se cierra. La documentación oficial del proyecto describe precisamente este mecanismo en su capítulo sobre fundamentos arquitectónicos (postgresql.org/docs/current/connect-estab.html, sección “Semántica de conexión”, consultado el 24 de agosto de 2026).

Esta elección tiene una verdadera ventaja: la caída de una conexión no afecta a las demás, ya que cada proceso queda aislado del resto del servidor. También tiene un costo directo: cada conexión adicional agrega un proceso completo del sistema operativo para programar, con su propio espacio de memoria y su propia sobrecarga de cambio de contexto para el kernel.

Qué cambia en la práctica

Una aplicación que abre 500 conexiones directas a Postgres sin agrupación obliga al servidor a gestionar 500 procesos del sistema simultáneos, incluso si la gran mayoría de ellos permanecen inactivos entre dos solicitudes.

#
Costo de la memoria

Lo que realmente consume una conexión: memoria compartida y work_mem

Dos mecanismos distintos afectan la memoria y confundirlos casi siempre conduce a un diagnóstico erróneo.

El primero está arreglado. Al inicio, Postgres reserva estructuras de memoria compartida (bloqueos, tabla de procesos) dimensionadas según el valor de max_connections, independientemente de si estas conexiones se abren posteriormente o no. La documentación oficial para la configuración señala explícitamente: aumentarla puede requerir más memoria compartida del sistema de la que permite la configuración predeterminada de su sistema operativo (postgresql.org/docs/current/runtime-config-connection.html, consultado el 24 de agosto de 2026).

El segundo es variable y mucho más peligroso a escala: work_mem no se asigna una vez por conexión, sino una vez por operación de clasificación o hash en el plan de consulta. La documentación oficial es explícita en este punto: una consulta compleja puede lanzar varias de estas operaciones en paralelo, y varias sesiones pueden hacer lo mismo simultáneamente, de modo que la memoria realmente utilizada puede valer varias veces work_mem (postgresql.org/docs/current/runtime-config-resource.html, consultado el 24 de agosto de 2026).

El peor caso real para recordar

No es solo max_connections × work_mem lo que amenaza la memoria de un servidor. Es max_connections × work_mem × número de operaciones simultáneas por consulta. Es este producto el que explica un servidor que intercambia, o que se queda sin memoria tras un aumento de max_connections considerado inofensivo.

#
Fórmula

La fórmula de tamaño del wiki de PostgreSQL

La wiki oficial del proyecto PostgreSQL documenta una fórmula de referencia para calcular cuántas conexiones activas su hardware puede procesar eficientemente en paralelo, no cuántas conexiones se abren en total (wiki.postgresql.org/wiki/Number_Of_Database_Connections, consultado el 24 de agosto de 2026).

la formula

concurrencia activa ideal = (núcleos físicos × 2) + discos eficientes. El número de núcleos excluye el hyperthreading. La cantidad de discos efectivos sigue siendo cercana a 1 en el almacenamiento SSD moderno, donde la noción de un disco físico separado (“eje”) pierde gran parte de su significado original.

En un servidor con 8 núcleos físicos y almacenamiento SSD, la fórmula da (8 × 2) + 1 = 17 conexiones activas antes de que el rendimiento comience a degradarse. Esta cifra suele sorprender: parece ínfima en comparación con los cientos de conexiones que abre una aplicación en la práctica. Éste es precisamente el tema del siguiente párrafo.

El número calculado por la fórmula mide la simultaneidad que la CPU y el disco pueden absorber, no la cantidad de conexiones de cliente que su aplicación necesita abrir. Una flota de 20 procesos de aplicación, cada uno con su propio grupo de 10 conexiones, abre 200 conexiones simultáneas a Postgres incluso si sólo 17 de ellas están trabajando activamente en un momento dado. Sin un pooler, max_connections debe cubrir los 200, no los 17. Es esta brecha la que empuja a la mayoría de las arquitecturas a agregar un pooler en modo de transacción, incluso si eso significa elegir cuál (consulte nuestra comparación de PgBouncer, Supavisor y PgCat).

#
Procedimiento

Cómo cambiar max_connections (y por qué es necesario reiniciar)

max_connections no se intercambia en caliente. Este es un parámetro de contexto postmaster: Postgres lo lee una vez, al inicio, para dimensionar su memoria compartida. Una recarga de configuración (pg_reload_conf() o SIGHUP) no es suficiente, debe reiniciar el servidor.

Primero verifique el valor actual y su contexto, para confirmar que será necesario reiniciar:

psqlsql
SHOW max_connections;

SELECT name, setting, context
FROM pg_settings
WHERE name = 'max_connections';

-- context='postmaster' confirma que es necesario reiniciar

Luego aplique el nuevo valor, luego reinicie:

psqlsql
ALTER SYSTEM SET max_connections = '300';

-- Escrito en postgresql.auto.conf.
-- No tiene efecto hasta que se reinicie Postgres.
terminalbash
# con sistemad
sudo systemctl restart postgresql

# Sin systemd, directamente con pg_ctl
pg_ctl restart -D $PGDATA -m fast
Un margen que muchos olvidan

max_connections incluye por defecto superuser_reserved_connections (3 por defecto): estas conexiones están reservadas para un superusuario en caso de saturación, nunca están disponibles para su aplicación, incluso si aún no se ha alcanzado el contador global.

#
Comprobado en código

Cómo Aurabase presupuesta max_connections en sus clústeres de Postgres

Dimensionar max_connections no es solo un ejercicio teórico. Así es como Aurabase lo presupuesta en sus clústeres de Postgres administrados:

100
POSTGRES POR DEFECTO
max_connections antes de cualquier ajuste
50→400
RODAMIENTOS AURABASE DEDICADOS
Gratis para las empresas, por el cluster CNPG.
3
SUPERUSUARIO RESERVADO
superuser_reserved_connections, valor predeterminado de Postgres

Clústeres dedicados: un clúster de Postgres por proyecto

En este nivel (vea nuestra comparación base dedicada vs compartida), cada proyecto recibe su propio clúster CloudNativePG y su propio presupuesto max_connections, dimensionado con el tamaño de la instancia:

gratis (dedicado)conexiones_max 501 instancia · 500 m vCPU · 512 Mi
profesional (predeterminado)conexiones_max 2002 instancias · 1 vCPU · 2Gi
equipoconexiones_max 3003 instancias · 2 vCPU · 3Gi
negocioconexiones_max 4003 instancias · 2 vCPU · 4Gi

Clústeres compartidos: varios proyectos de una organización, un presupuesto compartido

En este segundo camino, todos los proyectos de la misma organización se conectan a través de un pooler CNPG (PgBouncer, modo transaction) frente a un primario compartido:

gratisconexiones_max 50max_client_conn 100conexiones_max_usuario 20
profesionalconexiones_max 100max_client_conn 200conexiones_max_usuario 60
equipoconexiones_max 200max_client_conn 400conexiones_max_usuario 150

Todos los proyectos de una organización se conectan a través de una función de aplicación compartida. Por lo tanto, max_user_connections por sí solo limita el total de conexiones de servidor que esta función puede abrir en todo el clúster: esta es la verdadera protección global del clúster, no max_client_conn, que solo limita las conexiones de clientes al propio pooler.

Sin embargo, este agrupador solo atiende el tráfico de aplicaciones SDK. PostgREST, por su parte, permanece conectado directamente al primario (servicio-rw): la agrupación en modo de transacción rompería su mecanismo de recarga de esquema, que escucha un canal LISTEN dedicado llamado pgrst. Por lo tanto, sus propias conexiones (2 por réplica en el nivel compartido, 10 por réplica en el nivel dedicado) cuentan directamente en el presupuesto max_connections del principal, fuera de cualquier agrupador, exactamente el tipo de conexión "olvidada" que debe incluir el paso 1 del procedimiento siguiente.

Cifras actualmente en proceso de calibración, asumidas como tales

El código documenta explícitamente estos presupuestos de pool compartido como valores iniciales que se calibrarán en condiciones reales, midiendo pg_stat_activity bajo carga, no como cifras fijas de un punto de referencia publicado. Esta es la misma disciplina que se describe en nuestra metodología de referencia : medir antes de ajustar, no adivinar y luego esperar. Estos clústeres se ejecutan en PostgreSQL 16, una elección documentada en nuestra comparación Postgres 16 vs 17 vs 18.

#
Método

El procedimiento de 5 pasos para dimensionar max_connections sin agrupar

Este procedimiento no depende de ninguna herramienta en particular: se aplica a cualquier servidor Postgres, administrado o autohospedado.

  1. Cuente sus conexiones de clientes reales. Número de procesos de aplicaciones multiplicados por el tamaño de su grupo interno, además de herramientas de administración, replicación y monitoreo. Es este número, no la fórmula, el que establece el límite máximo de conexiones.
  2. Calcule la concurrencia ideal de su hardware con la fórmula de la wiki de PostgreSQL: (núcleos físicos × 2) + discos eficientes. Esta figura indica cuántas de estas conexiones pueden funcionar realmente en paralelo sin degradar el rendimiento.
  3. Establezca max_connections por encima de la necesidad real para el paso 1, con margen para superuser_reserved_connections y para cualquier herramienta de administración que abra sus propias conexiones fuera de la aplicación.
  4. Aplique el cambio con ALTER SYSTEM SET, luego reinicie el servidor. Este es un parámetro de postmaster: una simple recarga no es suficiente, como se detalló anteriormente.
  5. Supervisar pg_stat_activity a lo largo del tiempo. Si el número de conexiones inactivas excede en gran medida el número de conexiones activas, esto no es un problema de max_connections: es la señal de que necesita un agrupador frente al servidor, no un número mayor.

La solicitud de seguimiento del paso 5, utilizable directamente:

psqlsql
SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state
ORDER BY count(*) DESC;
#
Señal de advertencia

Cuando la fórmula ya no es suficiente: las señales de que necesitas un pooler

Tres señales regresan sistemáticamente cuando max_connections por sí solo ya no es suficiente, sea cual sea su valor.

  1. El error FATAL: sorry, too many clients already aparece durante la carga máxima, mientras que la mayoría de las conexiones mostradas por pg_stat_activity están en estado inactivo.
  2. La aplicación se ejecuta en un entorno sin servidor o con trabajadores efímeros (funciones de borde, trabajos cortos), que abren y cierran conexiones mucho más rápido de lo que el modelo de proceso por conexión de Postgres fue diseñado para acomodar.
  3. La fórmula y el procedimiento anteriores ya se han aplicado y la necesidad real de conexiones de clientes continúa excediendo la memoria disponible que se puede asignar sin poner en peligro work_mem o Shared_buffers.

En estos tres casos, la respuesta correcta casi siempre es un pooler ubicado entre la aplicación y Postgres, no un max_connections superior. Nuestra comparación PgBouncer, Supavisor y PgCat detalla las tres opciones, y nuestra guía para el modo de transacción explica el compromiso más común una vez que el pooler está implementado. Para conocer todos los ajustes de Postgres más allá de las conexiones, consulte nuestra lista de verificación de ajuste de Postgres de producción .

#
Preguntas frecuentes

Preguntas frecuentes

¿Cuáles son las max_connections predeterminadas de PostgreSQL?+
100, con 3 conexiones reservadas para el superusuario por defecto (superuser_reserved_connections). Este valor predeterminado es adecuado para muchas aplicaciones que pasan a través de un agrupador, pero rápidamente se vuelve insuficiente sin el agrupamiento tan pronto como una flota de procesos de aplicaciones abre cada uno su propio lote de conexiones.
¿Podemos cambiar max_connections sin reiniciar PostgreSQL?+
No. max_connections es un parámetro de contexto de postmaster: Postgres lo lee una vez al inicio para dimensionar su memoria compartida. ALTER SYSTEM SET escribe el nuevo valor en postgresql.auto.conf, pero solo lo aplica un reinicio completo del servidor; una recarga o un SIGHUP no son suficientes.
¿Cuánta memoria consume una conexión PostgreSQL inactiva?+
No existe un número oficial único: depende de work_mem,shared_buffers y extensiones cargadas por sesión. Sin embargo, lo que está documentado es que work_mem se asigna por operación de clasificación o hash en una consulta, no por conexión: por lo tanto, una única consulta compleja puede consumir work_mem varias veces en una única conexión activa.
¿Deberíamos siempre preferir un pooler como PgBouncer a un max_connections más alto?+
En la mayoría de los casos, sí, tan pronto como el número de conexiones de clientes reales supere con creces la concurrencia ideal calculada por la fórmula wiki de PostgreSQL. Un agrupador en modo de transacción agrupa una pequeña cantidad de conexiones físicas entre una cantidad mucho mayor de conexiones lógicas en el lado de la aplicación. Vea nuestra comparación de PgBouncer, Supavisor y PgCat para elegir cuál.
¿Qué mide exactamente la fórmula (núcleos × 2) + discos eficientes?+
Estima la simultaneidad activa ideal: la cantidad de solicitudes que la CPU y el disco de un servidor determinado pueden procesar en paralelo sin degradar el rendimiento, no la cantidad total de conexiones para abrir en max_connections. Este es un punto de partida que debe validarse mediante medición, documentado en la wiki oficial del proyecto PostgreSQL, no un límite estricto.
¿Cómo sé si mi servidor Postgres está cerca de su límite de conexiones?+
Consulte pg_stat_activity y compare la cantidad de conexiones en estado activo con aquellas en estado inactivo. Una gran cantidad de conexiones inactivas cerca del límite de max_connections, sin ninguna solicitud activa detrás, casi siempre indica una necesidad de agrupar en lugar de una necesidad de aumentar aún más max_connections.

¿LISTO PARA IMPLEMENTAR?

Tu backend en cinco minutos.

No se requiere tarjeta de crédito · 500 MB gratis · 50,000 MAU