The point that defines whether PgBouncer saves you or breaks you
PgBouncer can be the difference between a stable Odoo and a nightmare of timeouts. But it all starts with a decision that many overlook:
pool_mode defines when PgBouncer returns a real connection to the pool.
If you choose poorly, you not only improve nothing:you can worsen the system.
🧠 What does pool_mode actually do
PgBouncer receives many “client” connections (Odoo) and manages a smaller number of “server” connections (PostgreSQL).
pool_mode defineshow longa real PostgreSQL connection is “reserved” for a client.
If you reserve it for too long → you run out of pool.
If you release it quickly → you reuse connections and PostgreSQL breathes.
1) pool_mode = session
How it works
Insession, PgBouncer assigns a real connection to a client and keeps itfor the entire session.
In practice:
Odoo opens a connection
PgBouncer assigns a connection to PostgreSQL
that connection remains “occupied” for that client
even if the client is idle
Por qué suele fallar en Odoo
Odoo does not behave like an app that opens/closes perfect sessions. In production, it mixes:
short requests
users who leave tabs open
long polling (depending on your stack)
crons
workers with irregular loads
Typical result with session:
the pool “freezes”
clients start to wait for a connection
they appearintermittent timeouts
PostgreSQL may not be at 100%, but Odoo feels dead
Translation:with session, PgBouncer can become a “bottleneck” if your connections are held.
2) pool_mode = transaction (recomendado para Odoo)
How it works
In modetransaction, PgBouncer assigns a real connectiononly while the transaction lasts.
When the transaction ends:
the real connection returns to the pool
another client immediately reuses it
Por qué encaja con Odoo
Odoo works based on:
frequent transactions
ORM operations that open/close transactions per request/action
This makes transaction the natural mode for:
maximizing reuse
maintaining few real connections
stabilizing latency
avoiding pools hijacked by idle clients
✅ Base recommendation:
pool_mode = transaction
🚨 ¿Hay riesgos usando transaction?
Yes, but they are controllable.
In transaction, there is an important rule:
you should not rely on persistent session state in PostgreSQL(certain SET, temporary tables, session-level prepared statements, etc.)
In standard Odoo, it usually works well.
If you have very specific modules or unusual integrations, it is advisable to validate with tests.
🔥 Cómo se ve el fallo en la vida real
When the session is poorly chosen:
users report slowness "at times"
some screens load, others die
restarting Odoo "fixes" it
it comes back after a while
Cuando transaction está bien aplicado:
the system becomes predictable
latency drops in spikes
PostgreSQL stops inflating in RAM
the "firefighter mode" is reduced
✅ Recomendación práctica (para empezar bien)
If you are implementing PgBouncer for Odoo and want stability:
Use pool_mode = transaction
Adjust pools with real numbers (next chapter)
Monitor with SHOW POOLS; and SHOW STATS;
🔗 Enlaces internos
📌 Conclusión
If you take away only one idea from this chapter:
For Odoo, transaction is almost always the correct mode.
session may seem "safe", but in production is where starvation and timeouts arise.