PgBouncer es excelente para controlar conexiones y suavizar picos. Pero hay un momento en el que ya no te salva: cuando el problema real no es cuántas conexiones tienes, sino qué están haciendo esas conexiones (o cuánto tardan en terminar).
Este post te ayuda a reconocer ese punto y a elegir el siguiente paso correcto.
1) Si tu cuello es la query, PgBouncer no te va a “acelerar” la DB
Señales típicas
p95/p99 altos incluso con cl_waiting bajo o cero
Postgres con CPU/I/O altos y pocas conexiones
“todo se vuelve lento” aunque aumentes pool
Qué hacer
activar/usar pg_stat_statements y atacar top queries
revisar índices (especialmente en tablas grandes de ventas, stock, contabilidad)
optimizar dominios/búsquedas en Odoo, campos computed, search_read gigantes
revisar reportes PDF (frecuentemente son el “pico escondido”)
Idea clave: PgBouncer te ordena la fila; no cocina más rápido.
2) Si hay locks o transacciones largas, PgBouncer puede empeorar la percepción
En pool_mode=transaction, una transacción larga “secuestra” una conexión server hasta que termina. Si además hay locks, el pool se llena de transacciones esperando.
Señales típicas
cl_waiting sube, maxwait sube
en Postgres: wait_event_type = Lock, transacciones con xact_start muy viejo
lentitud “en oleadas” (sobre todo en horarios de crons)
Qué hacer
cortar transacciones: batching en crons (lotes pequeños)
evitar I/O externo dentro de transacciones (APIs/requests)
lock_timeout, statement_timeout, idle_in_transaction_session_timeout
ordenar locks (misma secuencia de updates en todos lados)
3) Si tu DB está limitada por I/O, PgBouncer no compensa discos lentos
Señales típicas
I/O wait alto, latencia de disco alta
DB “se arrastra” aunque bajes concurrencia
picos en horas de reportes/contabilidad/stock
Qué hacer
mejorar almacenamiento (IOPS/latencia)
ajustar autovacuum y vigilar bloat
cache y “working set” en RAM (buffers)
separar workloads (reportes pesados vs OLTP)
4) Si el problema es RAM/swap en Odoo, PgBouncer es irrelevante
PgBouncer no evita que Odoo se coma la RAM con workers, reportes y módulos pesados.
Señales típicas
swap distinto de cero en horas pico
latencia impredecible, timeouts raros
Odoo “revive” al reiniciar
Qué hacer
bajar/ajustar workers y límites de memoria
revisar generación de PDFs y trabajos masivos
separar workers vs crons (si tu operación lo permite)
dimensionar RAM real por worker (y medir RSS)
5) Si tu problema es “demasiados crons”, PgBouncer solo te muestra la cola
Crons paralelos y masivos pueden saturar DB por contención y transacciones largas.
Señales típicas
degradación fuerte en ventanas horarias (madrugada/cierre)
backlog de crons, solapes, jobs “eternos”
Qué hacer
bajar max_cron_threads (al inicio 1–2)
reescribir crons a lotes
escalonar horarios y aislar crons pesados
mover integraciones a colas externas (job queue) si ya es “modo fábrica”
6) Si tienes requerimientos de sesión (LISTEN/NOTIFY, prepared statements), PgBouncer “transaction” no alcanza
Señales típicas
tiempo real inestable (bus), comportamiento raro con notificaciones
problemas con drivers que dependen de sesión (dependiendo del stack)
Qué hacer
mantener transaction pooling para el ORM normal
y para lo “session-bound”: conexión directa o pool dedicado session
dividir pools por tipo de tráfico
7) Si ya escalaste Odoo y aún así estás al límite, necesitas arquitectura, no solo pooling
PgBouncer no sustituye:
escalado horizontal de Odoo (múltiples nodos)
cachés (Redis/HTTP cache) para reducir lecturas repetidas
read replicas (cuando el patrón lo permite)
separación de workloads (reporting vs transaccional)
refactor de procesos pesados y colas
Señales típicas
ya ajustaste pools y workers, y el límite se mueve poco
la carga crece y el “margen” operativo desaparece
Qué hacer
multi-nodo Odoo + balanceo
cachear donde duele (catálogos, páginas, endpoints repetidos)
separar reporting/ETL (replica o pipeline)
gobernar “trabajo pesado” con colas y rate limits
8) Checklist rápido: “¿PgBouncer es el cuello o solo el mensajero?”
SHOW POOLS;
¿cl_waiting sube? (hay cola)
Postgres
¿locks? ¿xact largas? ¿I/O wait alto?
Odoo
¿swap? ¿crons solapados? ¿p99 explota por PDFs?
Si el pool está bien pero el sistema va lento → no es PgBouncer.
Cierre
PgBouncer es necesario en muchos escenarios, pero no es “la solución final”. Es el control de tráfico. Cuando el problema real es queries, locks, I/O, RAM o diseño de jobs, necesitas atacar esas capas.