🎯 Objective of this chapter
By the end of this chapter:
PgBouncer will bespecifically configured for Odoo
You will avoid typical production errors
You will have a stable base for advanced tuning
👉 We are not looking for 'maximum performance' yet.
We are looking forstability + predictability.
🧱 Key principle: PgBouncer is not configured 'generically'.
Most guides fail here.
PgBouncer:
is not configured the same wayfor all apps
it depends on the connection pattern
it depends on transactions
Odoo has a very particular pattern📁 Main file.
📁 Main file
Everything we touch is in:
/etc/pgbouncer/pgbouncer.ini
🗂️ [databases] section
Recommended example:
[databases] odoo = host=127.0.0.1 port=5432 dbname=odoo
Best practices
Useone alias per database
Do not use * = in production
Keep the dbname explicit
⚙️ [pgbouncer] section – Base configuration
🔌 Ports and listening
listen_addr = 0.0.0.0 listen_port = 6432
Use 0.0.0.0 only if Odoo is on another host
If everything is on the same server:
listen_addr = 127.0.0.1
🔐 Authentication (recommended)
auth_type = scram-sha-256 auth_file = /etc/pgbouncer/userlist.txt
👉 SCRAM is more secure and stable than md5.
🔄 Pool mode (CRITICAL)
pool_mode = transaction
Why transaction and not session?
Odoo frequently opens transactions.
session keeps the connection busy.
transaction frees the connection when finished.
❌ session = guaranteed starvation.
✅ transaction = efficient reuse.
📊 Pool sizes (initial safe values)
max_client_conn = 500 default_pool_size = 20 reserve_pool_size = 5
What each one means
max_client_conn
Maximum connectionsfrom Odoo to PgBouncer
default_pool_size
Real connections to PostgreSQL per database
reserve_pool_size
Extra connections for brief spikes
👉 These valuesare not final, they are safe to start.
⏱️ Important timeouts
server_idle_timeout = 60 query_timeout = 0
server_idle_timeout:
closes idle connections
frees resources
query_timeout = 0:
do not break long Odoo queries.
Odoo manages its own timeouts.
🧠 Handling problematic transactions
idle_transaction_timeout = 60
Avoid:
hanging transactions.
workers blocking pools
🧾 Logging (highly recommended)
log_connections = yes log_disconnections = yes log_pooler_errors = yes
In production:
helps detect saturation
allows real debugging
🧪 Recommended full configuration (base)
[databases] odoo = host=127.0.0.1 port=5432 dbname=odoo [pgbouncer] listen_addr = 127.0.0.1 listen_port = 6432 auth_type = scram-sha-256 auth_file = /etc/pgbouncer/userlist.txt pool_mode = transaction max_client_conn = 500 default_pool_size = 20 reserve_pool_size = 5 server_idle_timeout = 60 idle_transaction_timeout = 60 query_timeout = 0 log_connections = yes log_disconnections = yes log_pooler_errors = yes
🔁 Apply changes
sudo systemctl reload pgbouncer
(Or use restart if you changed auth or ports)
👀 Check that everything is okay
Connect to PgBouncer:
psql -p 6432 -U odoo pgbouncer
And run:
SHOW POOLS; SHOW STATS;
What you should see:
active pools
few real connections
clients coming in and out
❌ Common errors at this stage
pool_mode = session
pools too small
aggressive timeouts
not looking at metrics
copying generic configs from the internet
📌 Conclusion
With this configuration:
Odoo stops saturating PostgreSQL
PgBouncer acts as a buffer
The system becomes stable
👉 It is still not optimal, but it is alreadycorrect.
Next chapter ->