🧠 Why This Chapter is Key
Many Performance Issues in Odooare not understooduntil you understand one thing:
Odoo does not reuse connections to PostgreSQL like most modern web applications.
And that has direct consequences on:
memory consumption
scalability
latency
system stability
🔌 The Odoo Connection Model (Simplified)
Odoo works with:
aPython server
multipleworkers
anORMthat interacts with PostgreSQL
Each worker:
maintainsits own connectionto PostgreSQL
opens transactions frequently
holds the connection for the duration of the transaction
👉 There is no real internal pooling.
⚙️ Odoo Workers and Connections
Basic Rule:
1 worker = 1 active connection to PostgreSQL (at minimum)
Typical Example:
workers = 12
Result:
12 base connections
plus connections for cron jobs
plus connections for long polling
plus connections during load peaks
You can easily end up with:
30, 50, or more active connections
even with few concurrent users
🔄 What happens during a request
When a user performs an action in Odoo:
The request reaches a worker
The ORM starts a transaction
Multiple queries are executed
The connection remains occupied
The transaction closes (sometimes late)
Meanwhile:
that connectioncannot be used by another request
PostgreSQL keeps reserved resources
🧨 The problem of long transactions
Odoo has many operations that generate:
long transactions
multiple chained queries
implicit locks
Examples:
invoice validation
inventory movements
stock recalculation
complex reports
👉 A long transaction = connection blocked longer.
❌ Why PostgreSQL struggles with this model
PostgreSQL:
createsa process per connection
allocates memory per connection
does not scale well with hundreds of connections
When Odoo opens many connections:
it increases RAM usage
it increases context switching
it lowers overall performance
Typical result:
PostgreSQL slow with low CPU and high RAM.
📉 The domino effect in production
Without connection control:
the workers start to wait
users perceive latency
timeouts appear
admins restart services
the problem returns
👉 Restart Odooonly frees connections, does not solve the cause.
🔍 How to see the problem live
In PostgreSQL you can see it like this:
SELECT count(*) FROM pg_stat_activity;
Or more detailed:
SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state;
It usually appears:
many idle connections
several idle in transaction
That isOdoo holding connections.
🧩 Why Odoo can't "fix this on its own"
Odoo's ORM:
is not designed for external pooling
assumes direct connection
depends on the worker's lifecycle
That's why:
increasing workers worsens the problem
increasing max_connections aggravates it
more hardware only delays the collapse
🚀 The correct solution: decouple connections
What Odoo needs is:
to openmany logical connections
but maintainfew real connectionsto PostgreSQL
Thatcannot be done within Odoo.
👉 It is done with aconnection pooler.
🔗 This is where PgBouncer comes in
PgBouncer:
is placed between Odoo and PostgreSQL
receives thousands of connections from Odoo
maintains few real connections
reuses connections efficiently
👉 In the next chapter, we will see it in detail:
Qué es PgBouncer y cómo funciona
🔗 Related links
📌 Conclusion
Odoo is not slow by design.
It isdemanding with PostgreSQL.
If you do not understand how it manages connections:
you will optimize poorly
you will scale poorly
you will restart too much
The solution is not to touch Odoo.
It isto put the missing piece in the architecture.
Next chapter ->