Ir al contenido

Relación entre workers de Odoo y PgBouncer

25 de noviembre de 2025 por
Relación entre workers de Odoo y PgBouncer
John Wolf
| Todavía no hay comentarios

Cuando Odoo “se pone lento” bajo carga, casi nunca es “misterio”: suele ser concurrencia mal dimensionada entre:

  • Workers de Odoo (cuántas requests puedes atender en paralelo)

  • Conexiones cliente a PgBouncer (cuántas conexiones simultáneas recibe el pooler)

  • Conexiones servidor a PostgreSQL (cuántas conexiones reales abre PgBouncer hacia Postgres)

Entender esa cadena te permite escalar sin caer en “Connection Pool Is Full” o colas infinitas.


1) El mapa mental: 3 niveles de concurrencia

Nivel A — Odoo: workers y crons

En producción (Linux), Odoo recomienda el modo multi-proceso y da una regla de pulgar para workers:

workers ≈ (#CPU * 2) + 1. Odoo+1

Además, Odoo aclara que en multi-processing se levanta un worker dedicado para LiveChat/WebSocket en --gevent-port (y que el proxy debe redirigir /websocket/ a ese puerto). Odoo

Traducción: aunque configures workers = N, en la práctica hay más actividad paralela (web + cron + gevent).


Nivel B — Odoo: db_maxconn (pool de conexiones “cliente”)

Odoo usa un pool de conexiones a la DB y, cuando se queda corto, aparece el clásico:

psycopg2.pool.PoolError: The Connection Pool Is Full GitHub+1

En multi-proceso, el punto que más confunde es este: el “pool” no es global a todos los workers; cada proceso tiene su dinámica, y con crons/longpolling puedes saturarlo incluso con valores que “parecen” suficientes (hay varios casos reportados por la comunidad). GitHub+1


Nivel C — PgBouncer: max_client_conn y default_pool_size

PgBouncer separa claramente:

  • clientes (Odoo → PgBouncer)

  • servidores (PgBouncer → PostgreSQL)

Y organiza pools por par (usuario, base de datos); ahí es donde default_pool_size define el máximo de conexiones servidor por pool. PgBouncer+1

En transaction pooling (lo típico con Odoo), PgBouncer asigna una conexión servidor solo durante la transacción y luego la devuelve al pool. PgBouncer


2) La relación clave (en una frase)

Más workers de Odoo ⇒ más concurrencia potencial ⇒ más conexiones “cliente” hacia PgBouncer ⇒ más presión para abrir conexiones reales a PostgreSQL (hasta el límite de default_pool_size).

Si dimensionas mal cualquiera de estos escalones, aparece:

  • cola en PgBouncer (clientes esperando)

  • o saturación en Postgres (demasiadas conexiones activas)

  • o el “pool is full” del lado de Odoo


3) Qué parámetro controla qué (sin humo)

Odoo

  • workers: cuántas requests web simultáneas puedes ejecutar (aprox.) Odoo+1

  • max_cron_threads: cuántos crons corren en paralelo (DB-active muchas veces)

  • db_maxconn: “cuántas conexiones a DB puede tener disponibles el proceso” (si te quedas corto, explota) GitHub+1

PgBouncer

  • max_client_conn: cuántas conexiones cliente acepta en total (Odoo → PgBouncer)

  • default_pool_size: cuántas conexiones servidor máximo por pool (db/user) PgBouncer+1

  • transaction pooling: conexión servidor asignada solo durante la transacción PgBouncer


4) Cómo dimensionar PgBouncer a partir de workers de Odoo (paso a paso)

Paso 1 — Estima tu pico de “procesos DB-activos”

Punto de partida:

  • Web workers (N)

  • Cron threads (C)

  • Gevent/WebSocket (G ≈ 1 en multi-processing) Odoo

DB-activos potenciales ≈ N + C + G

Ojo: esto es “peor caso”. En la realidad, no todos están en DB al mismo tiempo, pero para sizing inicial es útil.


Paso 2 — Estima conexiones cliente hacia PgBouncer

Cada proceso puede pedir varias conexiones si su pool lo permite (db_maxconn). En picos (o cuando hay longpolling, crons pesados y tráfico web), el uso se acerca al límite y aparecen los PoolError cuando se queda corto. Odoo+1

Máximo teórico de clientes hacia PgBouncer:

max_client_conn_ideal ≥ (N + C + G) * db_maxconn + margen

  • El “margen” es para picos, conexiones admin, healthchecks, herramientas, etc.


Paso 3 — Dimensiona conexiones servidor a Postgres (lo que importa de verdad)

Acá manda default_pool_size, que es por (db, user). PgBouncer+1

En transaction pooling, default_pool_size se comporta como:

límite de transacciones concurrentes por db/user PgBouncer+1

Regla práctica:

  • default_pool_size debe ser lo bastante alto para que no haya cola en horas pico,

  • pero lo bastante bajo para no ahogar Postgres con demasiadas consultas simultáneas.


Paso 4 — Agrega “burst” controlado: reserve_pool_size

En vez de inflar default_pool_size, usa reserve_pool_size para picos cortos (10–20% del pool suele ser un inicio razonable). Esto te salva de picos sin dejar Postgres “a la intemperie”.


5) Ejemplo real (para entender la matemática)

Servidor con 8 CPU:

  • Odoo sugiere workers ≈ (8*2)+1 = 17 Odoo

  • max_cron_threads = 2

  • gevent worker = 1 Odoo

  • db_maxconn = 32


5.1 PgBouncer max_client_conn

Peor caso:

  • procesos DB-activos = 17 + 2 + 1 = 20

  • clientes potenciales = 20 * 32 = 640

Recomendación inicial: max_client_conn 1000–2000 (según tu entorno).


5.2 PgBouncer default_pool_size

Si tienes 1 db y 1 user (lo normal en Odoo), tienes 1 pool.

Un inicio “sano” suele estar entre 40 y 120 (depende de la potencia de Postgres y la calidad de queries). Luego ajustas mirando colas y latencia.


6) Señales de que lo dimensionaste mal

Te quedaste corto (cola en PgBouncer)

  • Usuarios lentos “en oleadas”

  • PgBouncer muestra clientes esperando (cl_waiting sube)

  • Postgres NO está al 100%

→ Sube default_pool_size o ajusta crons/queries.

Te pasaste (Postgres sufre)

  • CPU/IO altos sostenidos

  • más waits/locks

  • latencia por query sube

→ Baja default_pool_size y optimiza (índices/queries) antes de “darle más conexiones”.

Odoo explota con “The Connection Pool Is Full”

Indica que el pool de Odoo es insuficiente para el patrón real de concurrencia (web + cron + longpolling), algo reportado en escenarios con workers>0 y crons paralelos. GitHub+1


7) Recomendación final (el enfoque que más evita incidentes)

  1. Dimensiona workers con la regla de Odoo como punto de partida. Odoo

  2. Mantén db_maxconn moderado (32–64 suele ser un rango operativo común; sube solo con evidencia).

  3. Pon max_client_conn alto (capacidad) y controla el backend con default_pool_size (protección). PgBouncer+1

  4. Usa transaction pooling (Odoo-friendly) y mide colas. PgBouncer


Siguiente capítulo ->

Relación entre workers de Odoo y PgBouncer
John Wolf 25 de noviembre de 2025
Compartir
Etiquetas
Archivo
Iniciar sesión dejar un comentario