Problema y alcance
Una plataforma de pedidos que utiliza PostgreSQL ejecuta 100 instancias de API sin estado y 20 workers en segundo plano. La base de datos tiene max_connections configurado en 500. Las migraciones, la respuesta a incidentes y las herramientas operativas requieren una reserva de 50, lo que deja un presupuesto para toda la aplicación de 450 conexiones. El tráfico pico es de 6.000 solicitudes por segundo, aproximadamente el 70% de las solicitudes acceden a la base de datos y los rastreos de la aplicación muestran que una operación de base de datos retiene una conexión durante 40 milisegundos en promedio. El objetivo p99 de extremo a extremo para las solicitudes de API es de 800 milisegundos.
Actualmente, cada proceso tiene un pool de 10, por lo que el despliegue puede crear teóricamente 100 × 10 + 20 × 10 = 1,200 sesiones de base de datos. La adquisición de conexiones comienza a agotar el tiempo de espera en el pico de tráfico. A veces, el uso de CPU de la base de datos es de solo el 55%; en otras ocasiones, las esperas de bloqueo y la latencia de las consultas también aumentan. Diseñe una asignación inicial del pool, una política de tiempos de espera y el ciclo de vida de las conexiones. Explique cómo distinguir entre un pool local subdimensionado, una fuga de conexiones, una transacción larga, un escalado de réplicas que excede el presupuesto y una sobrecarga interna en la base de datos.
El número de instancias, el rendimiento, el tiempo de retención de 40 milisegundos y el límite de 500 conexiones son suposiciones de entrevista, no afirmaciones de rendimiento universales para PostgreSQL, HikariCP o PgBouncer. La guía actual de entrevistas de backend aún evalúa el rendimiento, la confiabilidad y las consideraciones operativas en el diseño de sistemas, y en 2026 se publicó una pregunta dedicada al diseño de pools de conexiones de bases de datos. La habilidad fundamental es gestionar la concurrencia de la base de datos y la propiedad de los recursos a través de las réplicas de la aplicación, por lo que la categoría es backend.
Qué evalúa el entrevistador
La primera señal es tratar al pool como un control de admisión de concurrencia, en lugar de asumir que más conexiones producen un mayor rendimiento. El parámetro max_connections de PostgreSQL es para toda la base de datos, y aumentarlo incrementa la asignación de recursos. Un número configurado de forma independiente en una instancia debe multiplicarse por las réplicas de la API, los workers, las tareas programadas y las réplicas temporales durante un despliegue progresivo (rolling release).
La segunda señal es usar la Ley de Little para una comprobación de orden de magnitud sin presentar un promedio como una respuesta de capacidad definitiva. La tasa promedio de llegada a la base de datos es de 6,000 × 70% = 4,200 operaciones por segundo. La ocupación promedio de conexiones es de aproximadamente 4,200 × 0.04 = 168. Esto describe únicamente la concurrencia promedio en estado estacionario. Las ráfagas, el tiempo de retención p99, las esperas de bloqueo, los reintentos de transacciones y el desbalanceo de carga entre réplicas aún requieren mediciones y pruebas de carga.
La tercera señal es localizar la cola con evidencia de ambos lados. La aplicación debe exponer los recuentos de conexiones activas, inactivas y pendientes, la latencia y los tiempos de espera de adquisición, y el tiempo de retención de las conexiones. La base de datos debe exponer el estado de pg_stat_activity, wait_event, las consultas activas, las transacciones inactivas y el origen de las conexiones. Aumentar el pool porque "la adquisición de conexión agotó el tiempo de espera" puede simplemente trasladar la cola de la aplicación a la base de datos.
Por último, la respuesta debe definir límites de falla. Un diseño sólido cubre los plazos de las solicitudes (deadlines), fugas de conexiones, transacciones largas, despliegues progresivos, autoescalado, reinicios de la base de datos, conexiones obsoletas y la diferencia entre el pooling de sesión y de transacción en PgBouncer. También identifica las características con ámbito de sesión que podrían no ser seguras con el pooling de transacciones.
Preguntas aclaratorias antes de responder
- ¿El límite de 500 aplica a un único primario o a un clúster más grande? Las réplicas de lectura, los destinos de conmutación por error (failover) y el acceso
operativo pueden tener presupuestos diferentes. Calcule los pools por separado para las bases de datos que realmente atienden cada carga de trabajo.
- ¿Cuál es el número máximo de réplicas? ¿Son 100 instancias de API el valor normal o el máximo de autoescalado? Un despliegue progresivo puede
ejecutar temporalmente réplicas antiguas y nuevas juntas. Una configuración basada únicamente en réplicas en estado estacionario puede exceder el presupuesto durante un despliegue o un incidente.
- ¿Cuál es la distribución del tiempo de retención de las conexiones? Un promedio de 40 milisegundos no muestra el p95, el p99, las llamadas
de red dentro de transacciones ni las esperas de bloqueo. La cola larga controla la formación de colas y los tiempos de espera, por lo que debe segmentarse por ruta, tarea y etiqueta de transacción.
- ¿El trabajo en segundo plano puede ponerse en cola o limitar la concurrencia? Los trabajos por lotes largos no deben competir libremente con solicitudes
de API cortas. Los pools separados son útiles, pero cada pool sigue compartiendo el mismo presupuesto global de 450.
- ¿Qué reintentos ocurren tras un tiempo de espera agotado? Los reintentos inmediatos sin retroceso exponencial (backoff) aumentan la tasa de llegada precisamente cuando
la base de datos se ralentiza. El tiempo de espera de adquisición debe encajar dentro del plazo de la solicitud y funcionar con control de admisión, retroceso o una respuesta de falla definida.
- ¿Qué características con ámbito de sesión utiliza la aplicación? Las tablas temporales,
LISTEN, los bloqueos consultivos de sesión (session advisory locks),
el estado de SET entre transacciones y el comportamiento de las sentencias preparadas (prepared statements) afectan si el pooling de transacciones de PgBouncer es seguro.
- ¿Dónde se ejecutaría el proxy de conexiones? Una sola instancia de PgBouncer crea un límite de capacidad y disponibilidad.
Los sidecars por nodo, un nivel de proxy dedicado y un proxy administrado tienen diferentes modos de falla.
Estructura de respuesta de 30 segundos
"Comenzaría con un presupuesto global. Reservar 50 de 500 conexiones deja 450 para las aplicaciones; el límite actual por proceso se expande a 1.200. La concurrencia promedio de 168 es solo una comprobación de escala. Una asignación inicial podría dar a cada instancia de API 2 y a cada worker 4, sumando 280 con 170 de margen, para luego ajustarlo bajo carga máxima. El tiempo de espera de adquisición debe encajar dentro del plazo de solicitud de 800 milisegundos. Compararía el recuento de pendientes del pool, la latencia de adquisición y el tiempo de retención con pg_stat_activity y los eventos de espera. Si el pool forma colas mientras la base de datos tiene margen disponible, inspeccionaría el sesgo, las fugas y los límites locales. Si las consultas o los bloqueos ya se están degradando, no agrandaría el pool. El autoescalado debe recalcular el presupuesto, y el pooling de transacciones de PgBouncer requiere una auditoría del estado de sesión".
Análisis detallado paso a paso
Establecer un presupuesto global de conexiones
Escriba el presupuesto como una invariante explícita:
application_connection_cap
= max_connections
- operations_reserve
= 500 - 50
= 450La suma de todos los límites de pool para API, workers, migraciones, administración y despliegues progresivos debe mantenerse en o por debajo de 450. Si otras aplicaciones usan la misma base de datos, reste también sus presupuestos. La reserva operativa no es rendimiento libre para el tráfico normal. Preserva la capacidad de conectarse, observar y reparar la base de datos durante un incidente.
La comprobación de concurrencia promedio es:
database_arrival_rate = 6,000 × 70% = 4,200 operations/second
average_in_flight = 4,200 × 0.04 seconds = 168Esto demuestra rápidamente que 1.200 conexiones no están justificadas por la carga de trabajo promedio y que 20 conexiones totales son probablemente muy pocas. No produce el tamaño final del pool porque los promedios ocultan ráfagas, tiempo de retención p99, reintentos de transacciones y retroalimentación de colas. El número final debe combinar los SLO del servicio, la concurrencia activa sostenible de la base de datos y pruebas de carga.
Proponer una asignación inicial que pueda probarse
Un punto de partida conservador es de 2 conexiones por instancia de API y 4 por worker:
API cap = 100 × 2 = 200
worker cap = 20 × 4 = 80
allocated = 280
app headroom = 450 - 280 = 170La asignación de 4 para workers es solo un límite aislado inicial, no un valor que se deduzca directamente de 'trabajos más largos'. Los valores reales deben basarse en la distribución del tiempo de retención, la tasa de llegada y el límite de concurrencia de cada carga de trabajo. Doscientos ochenta es un candidato que respeta el presupuesto global y puede someterse a pruebas de carga; los 170 restantes no deben asignarse automáticamente. Si las réplicas de API crecen a 200, mantener 2 por réplica consume 400, y los 80 de los workers empujan el total por encima de 450. El escalado debe reducir el límite por instancia, acotar el número máximo de réplicas o usar un proxy para aplicar un presupuesto de conexiones de servidor más centralizado.
No configure un minimumIdle grande simplemente para que cada proceso siempre tenga conexiones de reserva. Las sesiones inactivas aún consumen el límite global. Un pool puede crecer bajo demanda hasta un máximo estricto. La conveniencia de retener un número mínimo de conexiones inactivas debe justificarse mediante el costo medido de establecimiento de conexiones y la latencia en ráfagas.
Establecer tiempos de espera de adquisición y vida útil de las conexiones
El tiempo de espera de adquisición debe ser menor que el plazo restante de la solicitud. Con un objetivo p99 de 800 milisegundos, un hilo no puede esperar 30 segundos por una conexión. Una primera prueba podría otorgar a la adquisición entre 100 y 200 milisegundos y ajustarlo a partir de la distribución de colas medida. Ese rango es una decisión de diseño para el escenario, no una recomendación universal de biblioteca. Tras agotarse el tiempo de espera, devuelva un error de sobrecarga reconocible y aplique control de admisión ascendente (upstream) o retroceso con variación aleatoria (jitter). No reintente inmediatamente sin un límite.
La vida útil máxima de la conexión debe ser más corta que cualquier límite de vida impuesto por la base de datos, el proxy o la red, y debe incluir fluctuación aleatoria para que muchas conexiones no expiren juntas. El keepalive es para conexiones inactivas que deben permanecer válidas y debe ejecutarse con mayor frecuencia que la vida útil máxima. Probar cada conexión antes de cada préstamo agrega un viaje de ida y vuelta (round trip) y requiere medición. Más importante aún, gestione correctamente la primera operación fallida tras un reinicio o conmutación por error de la base de datos y reintente únicamente operaciones de negocio idempotentes.
Determinar si el pool de la aplicación es el cuello de botella
Cada pool debe exponer al menos estas métricas con etiquetas de servicio, instancia y carga de trabajo:
- configurado máximo, activas, inactivas y pendientes;
- latencia de adquisición p50, p95 y p99 y recuento de tiempos de espera agotados;
- tiempo de retención de conexión etiquetado por ruta, tarea o transacción;
- tasas de creación, cierre, validación fallida y recreación de conexiones;
- el límite teórico total: máximo del pool configurado multiplicado por el recuento actual de réplicas.
Interprete combinaciones, no valores aislados. Un recuento de pendientes y una latencia de adquisición crecientes con conexiones activas fijadas en el límite máximo, mientras la base de datos aún tiene margen de conexiones activas sostenibles y CPU, pueden indicar un pool local pequeño, tráfico sesgado o unas pocas operaciones que retienen conexiones demasiado tiempo. Si los préstamos activos nunca disminuyen después de que terminan las solicitudes, o los rastreos de pila permanecen en el código de la aplicación, es posible que una conexión no se esté liberando. Un aumento repentino en la creación y cierre de conexiones puede indicar una discrepancia en los tiempos de vida, un tiempo de espera agotado en el proxy o un problema de red.
Use ámbitos de conexión estructurados para que las rutas de éxito, error, cancelación y retorno temprano liberen la conexión. Los umbrales de detección de fugas pueden ayudar a localizar una ruta, pero no reemplazan las distribuciones de tiempo de retención ni la revisión de código. Un umbral demasiado corto etiquetará transacciones largas legítimas como fugas.
Usar evidencia de PostgreSQL para aislar la sobrecarga de la base de datos
PostgreSQL expone una fila de pg_stat_activity por cada proceso del servidor. Agrúpela por application_name, dirección de cliente, estado y evento de espera. Comience con:
SELECT application_name, state, wait_event_type, wait_event, count(*)
FROM pg_stat_activity
WHERE datname = current_database()
GROUP BY application_name, state, wait_event_type, wait_event
ORDER BY count(*) DESC;Luego busque las sesiones que permanecen inactivas dentro de una transacción:
SELECT pid, application_name, xact_start, state_change, wait_event_type, wait_event
FROM pg_stat_activity
WHERE state = 'idle in transaction'
ORDER BY xact_start;Si las sesiones activas, la latencia de consultas, las esperas de bloqueo o las operaciones de E/S empeoran a medida que aumenta el recuento de conexiones, el cuello de botella está en las consultas, transacciones o recursos de la base de datos. Agrandar el pool incrementa la contención. Si la base de datos está cerca de las 500 sesiones pero muchas son sesiones inactivas de la aplicación, los pools inactivos por instancia han consumido el presupuesto; redúzcalos o introduzca multiplexación. Si idle in transaction persiste, repare los límites de las transacciones porque esas sesiones consumen una conexión y pueden retener bloqueos o impedir el progreso del vacuum.
El total de sesiones no equivale a ejecución paralela. Las sesiones inactivas y las sesiones en espera de bloqueos requieren diferentes explicaciones. Una CPU al 55% no demuestra capacidad disponible en la base de datos: la contención de bloqueos, la latencia de almacenamiento, una partición caliente o una ruta de ejecución serial pueden bloquear el trabajo con un uso agregado de CPU bajo.
Aislar cargas de trabajo y contemplar el escalado
Cuando las solicitudes de API cortas y los workers largos comparten un solo pool, unos pocos trabajos por lotes pueden causar bloqueo de cabeza de línea (head-of-line blocking). Asígneles pools separados y colas de concurrencia separadas, como la división 200/80 en este escenario. El aislamiento protege la latencia; no crea un presupuesto mayor. Debe permitirse que el pool de workers se reduzca cuando esté inactivo, y los trabajos en sí necesitan un límite de concurrencia.
El autoescalador debe conocer el presupuesto de la base de datos. La restricción estricta más simple es:
max_replicas × pool_size_per_replica + other_pool_caps <= 450Incluya el margen adicional (surge) de maxSurge en despliegues progresivos. Si el recuento de réplicas varía ampliamente, un límite fijo por instancia desperdicia capacidad con pocas réplicas y excede el presupuesto con muchas. Use un pool fijo pequeño más encolamiento de solicitudes, o use PgBouncer para multiplexar muchas sesiones de cliente en un número controlado de conexiones de servidor. De cualquier manera, continúe limitando la concurrencia activa dentro de la base de datos.
Decidir si usar PgBouncer
El pooling de sesión de PgBouncer retiene la misma conexión de servidor hasta que finaliza la sesión del cliente. Es altamente compatible con el comportamiento de sesión de PostgreSQL, pero proporciona menor multiplexación. El pooling de transacciones asigna una conexión de servidor únicamente durante la duración de una transacción. Puede evitar que clientes inactivos retengan conexiones de servidor, pero elimina la suposición de que la siguiente transacción utilizará la misma sesión de servidor.
Antes de utilizar pooling de transacciones, audite el uso de SET/RESET entre transacciones, LISTEN, bloqueos consultivos de sesión, tablas temporales y otros estados de sesión. Si la aplicación necesita esas semánticas, mantenga el pooling de sesión, asigne a rutas seleccionadas un pool directo independiente o mueva el estado dentro de una transacción. Un menor recuento de conexiones por sí solo no garantiza el éxito. Pruebe el encolamiento en el proxy, las fallas del proxy, la autenticación, la recreación de conexiones y la conmutación por error de la base de datos.
Cerrar el ciclo de capacidad con pruebas de fallos
Comience con carga escalonada, incremente hacia 6.000 solicitudes por segundo y luego agregue ráfagas y autoescalado. En cada paso registre el p95/p99 de extremo a extremo, la latencia de adquisición, el recuento de pendientes, el tiempo de retención, las sesiones activas en la base de datos, las esperas de bloqueo, la latencia de consultas, la CPU y la E/S. Compare varias asignaciones candidatas alrededor de la división inicial 200/80 y encuentre el punto donde el rendimiento deja de crecer o la latencia y las colas de la base de datos comienzan a empeorar.
Las pruebas adversarias deben incluir una ruta inyectada que no libere la conexión, varias transacciones que retengan conexiones durante segundos, contención de bloqueos, réplicas antiguas y nuevas ejecutándose durante un despliegue progresivo, un reinicio de la base de datos, un proxy desconectando conexiones de servidor existentes y una ráfaga de acumulación de trabajo pendiente (backlog) en los workers. Aprobar no significa "cero errores". Bajo el presupuesto global de conexiones, el sistema debe fallar rápidamente (fail fast) o descartar carga (load shedding), las métricas deben identificar la cola y la recuperación no debe generar una tormenta de conexiones.
Ejemplo de respuesta de alta calidad
"Dividiría las 500 conexiones de la base de datos en presupuestos antes de elegir un número por instancia. Reservar 50 para operaciones deja 450 para las aplicaciones. Los 120 procesos actuales con 10 cada uno producen un límite teórico de 1.200, por lo que los despliegues progresivos y las ráfagas pueden exceder el límite de la base de datos.
El enunciado indica 4.200 operaciones de base de datos por segundo y un tiempo promedio de retención de 40 milisegundos. La Ley de Little arroja cerca de 168 operaciones concurrentes promedio. Usaría eso únicamente como una comprobación de escala, no como capacidad p99. Una asignación inicial podría dar 2 conexiones a cada una de las 100 réplicas de API y 4 a cada uno de los 20 workers, totalizando 280 y dejando 170 conexiones de margen para la aplicación. Realizaría pruebas de carga con candidatos cercanos a 280 con la distribución real del tiempo de retención, ráfagas y contención de bloqueos. El máximo de autoescalado y las réplicas en despliegues progresivos pertenecen a la fórmula; de lo contrario, 200 réplicas de API más los pools de workers excederían 450.
El tiempo de espera de adquisición debe encajar dentro del plazo de solicitud de 800 milisegundos. Comenzaría probando de 100 a 200 milisegundos. En el lado de la aplicación monitorearía activas, inactivas, pendientes, latencia de adquisición, recuento de tiempos de espera agotados, tiempo de retención y recreación de conexiones. En PostgreSQL agruparía pg_stat_activity por nombre de aplicación e inspeccionaría activas, inactivas, idle-in-transaction y eventos de espera. Si el pool forma colas mientras la base de datos tiene margen sostenible, inspeccionaría el sesgo entre réplicas, el límite local y las conexiones no liberadas. Si las consultas, los bloqueos o la E/S ya se están degradando, un pool más grande solo incrementará la concurrencia en la base de datos. Si la mayoría de las sesiones cerca de max_connections están inactivas, reduzca los pools inactivos por instancia o multiplexelos mediante un proxy.
Aislaría las API cortas y los workers largos con pools y límites de concurrencia independientes, manteniendo su suma por debajo de
- Si se necesita PgBouncer, elegiría el modo deliberadamente: el pooling de sesión preserva mayor compatibilidad;
el pooling de transacciones multiplexa de forma más agresiva pero requiere una auditoría de LISTEN, bloqueos consultivos de sesión, tablas temporales y SET entre transacciones. Por último, validaría el p99, las colas, las conexiones totales y la recuperación mediante carga escalonada, ráfagas, una fuga inyectada, transacciones largas, contención de bloqueos, despliegue progresivo, reinicio de la base de datos y desconexiones del proxy".
Errores comunes
- Asignar 20 conexiones a cada instancia → el total de sesiones se vuelve incontrolable cuando cambia el número de réplicas →
defina primero el presupuesto global de la base de datos y divídalo entre todos los pools y el número máximo de réplicas.
- Configurar exactamente 168 conexiones a partir del promedio → se ignoran ráfagas, tiempo de retención p99, esperas de bloqueo y granularidad de asignación →
utilice la Ley de Little como comprobación de escala y luego decida con distribuciones y pruebas de carga.
- Aumentar el pool cada vez que la adquisición agota el tiempo de espera → la formación de colas en la aplicación puede trasladarse a bloqueos, E/S o colas de CPU
en la base de datos → inspeccione las conexiones pendientes del pool y las sesiones activas, eventos de espera y latencia de consultas de la base de datos en conjunto.
- Mirar solo el uso de CPU de la base de datos → los bloqueos, la latencia de almacenamiento y los puntos calientes pueden bloquear conexiones con bajo uso de CPU →
interprete las sesiones por estado y evento de espera.
- Ignorar las conexiones inactivas → los pools inactivos en muchas réplicas pueden agotar
max_connectionsprimero →
monitoree el límite del pool multiplicado por el número de réplicas y controle el mínimo inactivo.
- Tratar idle-in-transaction como inactividad ordinaria → la transacción puede retener bloqueos, mantener una instantánea antigua e impedir
la limpieza de vacuum → ubique el inicio de la transacción y los límites de código, y aplique tiempos de espera adecuados.
- Poner todas las cargas de trabajo en un solo pool → los workers largos ocupan conexiones requeridas por las API cortas →
aísle pools y colas por perfil de latencia sin exceder el presupuesto global.
- Adoptar PgBouncer y usar pooling de transacciones por defecto → el estado de sesión puede desaparecer entre transacciones o terminar en
otra conexión de servidor → audite la compatibilidad antes de seleccionar un modo de pooling.
- Reintentar todos los errores de conexión de inmediato → la recuperación de la base de datos se enfrenta a una tormenta de conexiones y a una mayor tasa de llegada →
limite los reintentos, agregue retroceso con variación aleatoria y reintente únicamente operaciones idempotentes.
- Probar únicamente el estado estacionario → los despliegues progresivos, el escalado, las transacciones largas y los reinicios de la base de datos revelan fallas de presupuesto
y ciclo de vida → inclúyalos en la matriz de aceptación.
Preguntas de seguimiento
Pregunta de seguimiento 1: ¿Por qué más conexiones pueden ralentizar el sistema?
La CPU, la memoria caché, los bloqueos y el ancho de banda de almacenamiento de la base de datos son finitos. Más allá de la concurrencia activa sostenible, más conexiones aumentan el cambio de contexto, la contención de caché y las esperas de bloqueo. Cada consulta se vuelve más lenta, lo que prolonga el tiempo de retención de la conexión y crea una retroalimentación positiva. Un pool pequeño proporciona un encolamiento acotado en la aplicación, lo cual suele ser más fácil de controlar que permitir que cada solicitud ingrese a la base de datos. Sin embargo, el pool no debe ser tan pequeño que deje sin uso la capacidad sostenible de la base de datos.
Pregunta de seguimiento 2: ¿Qué cambia si la API escala a 200 instancias?
Mantener 2 conexiones por instancia crearía 400 conexiones de API; los 80 de los workers empujarían el total por encima de 450. Reduzca cada pool de API a 1 y reasigne el presupuesto de los workers, limite el número máximo de réplicas y el incremento en despliegues progresivos, o multiplexe los clientes con PgBouncer. Utilice pruebas de encolamiento ante ráfagas y de concurrencia sostenible de la base de datos para tomar la decisión. Un autoescalador no puede limitarse a mirar la CPU e ignorar la capacidad de la base de datos downstream.
Pregunta de seguimiento 3: ¿Cómo se demuestra una fuga en lugar de una consulta genuinamente lenta?
Una fuga suele manifestarse como préstamos activos que solo aumentan, solicitudes pendientes persistentes y una solicitud que ya ha finalizado mientras su sesión de base de datos puede estar inactiva. Asocie cada préstamo con ruta, tarea y traza de pila muestreada; compare el tiempo de retención con la vida útil de la solicitud; e inspeccione las rutas de excepción, cancelación y retorno temprano. Si la sesión de PostgreSQL permanece activa o espera en un bloqueo, explique la consulta y la transacción antes de catalogarla como fuga.
Pregunta de seguimiento 4: ¿Se puede aplicar directamente la fórmula de tamaño de pool de HikariCP?
(core_count × 2) + effective_spindle_count es una heurística inicial en la documentación de HikariCP, que indica explícitamente realizar pruebas de carga a su alrededor. Los SSD, la tasa de aciertos de caché, el tipo de consulta y una base de datos remota modifican el resultado. Más importante aún, cuando muchas réplicas de la aplicación comparten una sola base de datos, cualquier candidato a nivel de base de datos aún debe dividirse entre ellas. La fórmula no puede reemplazar el presupuesto global de 450 ni la evidencia real de los SLO.
Pregunta de seguimiento 5: ¿Las sentencias preparadas nunca son compatibles con el pooling de transacciones de PgBouncer?
No haga una afirmación absoluta para todas las versiones y configuraciones. Valide la matriz de características de PgBouncer frente a la versión desplegada, el soporte de sentencias preparadas a nivel de protocolo y los ajustes del controlador (driver). El pooling de transacciones aún no garantiza que dos transacciones usen la misma sesión de servidor. Enumere la semántica de sesión real de la que depende la aplicación, verifíquela en pruebas de integración y luego elija pooling de transacciones, pooling de sesión o un pool directo para cada ruta.
Pregunta de seguimiento 6: La latencia de adquisición se redujo tras aumentar el pool, pero el p99 de extremo a extremo aumentó. ¿Por qué?
La cola se trasladó del pool de la aplicación a la base de datos. Al ingresar más consultas simultáneamente, la contención de bloqueos, la E/S o la cola de CPU aumentan el tiempo de ejecución de las consultas. Una mejor métrica de adquisición no implica una mejor latencia para el usuario. Compare el p99 de extremo a extremo, la duración de las consultas en la base de datos, los eventos de espera y el rendimiento, y elija el punto de concurrencia con la menor latencia total y un margen estable.