Odoo Running Slow? 7 Performance Optimization Fixes That Deliver Results
5 min read
5 min read
25+
Certified Odoo experts at BiztechCS
19+
Years delivering enterprise software optimization and performance engagements
93%
Of enterprises say system downtime now costs over $300K per hour [6]
7
Proven performance optimization fixes covered in this guide
Here’s the thing about Odoo performance problems — they’re almost always predictable. The platform can handle large transaction volumes, but it needs the right Odoo configuration, adequate infrastructure, database maintenance, and query tuning to hold up under real production load. Most Odoo performance degradation isn’t a platform limitation. It’s a configuration and maintenance failure.
Odoo performance optimization services fix the actual root cause — whether that’s database indexing, hardware sizing, worker configuration, report query issues, or module bloat. The goal isn’t to ask your users to work around slow screens. This guide walks through seven proven fixes, how to pinpoint what’s actually causing the slowness, and what you should expect when engaging odoo performance optimization services.
Is your Odoo system slowing down under growing user load?
Database growth without maintenance. Odoo stores all its transactional data in a PostgreSQL database. As your transaction volume grows, heavily-read tables like sales order lines, stock moves, and account move lines balloon to millions of rows. Skip regular database maintenance and the query planner starts working from stale statistics — it misses indexes, scans entire tables, and turns operations that took milliseconds into ones that take seconds.
Incorrect worker and process configuration. Odoo’s multi-process mode handles concurrent requests through a pool of worker processes. Size that pool too small — which is extremely common when deployments grow beyond their original user count — and requests stack up behind each other. A 40-user deployment running with just 6 workers means users are constantly waiting for a worker to free up. It doesn’t look like a specific problem; it just makes everything feel slow.
Insufficient server memory. Odoo loads all its module files and configuration into memory at startup. When there isn’t enough RAM for the worker count you’re running, the OS reaches for swap. Swap is orders of magnitude slower than RAM — and once you’re swapping, the slowness hits everything, not just one screen.
Unoptimized custom reports and views. Custom reports and views built during implementation often weren’t tested against real production data volumes. A report that ran in 2 seconds on 100,000 records can take 45 seconds on 3 million — because the query does a full table scan instead of using an index. Custom fields added to list views that join large tables create the same issue.
Installed modules that are not in use. Odoo loads every installed module at startup — even the ones nobody touches. Modules installed for an eval or an abandoned pilot still consume memory and slow startup. Some add database triggers or scheduled actions that fire on every transaction.
Session store and file store management. Odoo stores session data and uploaded files on the filesystem. When the file store grows into millions of files in a single directory, filesystem performance takes a hit. Session data that never gets cleaned up adds overhead to every request.
Schedule daily VACUUM ANALYZE[2] operations on the most-used Odoo tables: account_move, account_move_line, stock_move, stock_move_line, sale_order, sale_order_line, purchase_order, purchase_order_line, mrp_production. These operations reclaim dead tuples from updates and deletes, refresh query planner statistics, and restore index efficiency.
For tables with specific slow queries, pull the query plan using EXPLAIN ANALYZE in PostgreSQL. It’ll tell you whether the query is using indexes or doing sequential scans. Add indexes on any columns used in WHERE clauses on large tables that are missing them — the most common gaps in Odoo are on custom fields added post-go-live that appear in filters and search views.
For mature Odoo instances with two or more years of transaction data, this one fix often produces the most dramatic improvement of anything on this list.
Your worker count at go-live was sized for your user count at go-live — not today’s. Reconfigure based on your current concurrent load. The recommended formula for sizing Odoo workers in multi-process deployments is (2 × CPU cores) + 1 for CPU-bound workloads[3], with adjustments for your specific mix. A deployment with 40 concurrent users on an 8-core server should be running at least 16 Odoo workers.
Set limit_memory_hard and limit_memory_soft so that available server memory divided by worker count stays above 2 GB per worker for complex implementations. If the math doesn’t work out, you need more RAM before you increase the worker count — adding workers without enough memory just pushes you into swap, which cancels out the gain.
Get this Odoo configuration change right, and the general “everything feels slow” complaints from multi-user teams usually disappear.
Odoo opens a dedicated PostgreSQL connection for each worker process. Run enough Odoo workers and that connection overhead becomes its own bottleneck. PgBouncer[4] sits between Odoo and PostgreSQL, maintaining a smaller pool of persistent connections and multiplexing worker connections through them — so PostgreSQL isn’t constantly handling new connection setup and teardown.
For deployments with 20+ workers, adding PgBouncer in transaction pooling mode reduces connection overhead and improves query throughput. You’ll point Odoo’s db_host, db_port, and db_password to PgBouncer rather than directly at PostgreSQL.
If Nginx isn’t configured to cache static files, Odoo re-serves JavaScript bundles, CSS, and images on every request. That’s unnecessary work. Set up Nginx to serve the /web/static/ path from the Odoo file store with a long cache lifetime (365 days) and the right Cache-Control headers.
Make sure proxy_mode = True is set in your Odoo configuration[1] so that Nginx takes over static serving. You’ll see reduced server-side load for any session with a lot of UI interactions, and faster page load times across the board.
Not sure which fix your Odoo system actually needs?
Don’t skip staging here. Uninstalling modules from a live production Odoo instance can trigger failures if there are schema dependencies you weren’t aware of. Run the uninstall sequence in a test environment first, then apply it to production.
Fewer installed modules means faster startup, a smaller memory footprint, and fewer background triggers firing on every transaction.
Enable log_response_time in the Odoo server log and collect it during a slow period. Identify your five slowest operations by URL path — then determine whether each is a report query, a list view load, or an action open. For slow reports, pull the underlying PostgreSQL query plan with EXPLAIN ANALYZE and add indexes wherever full table scans are hitting large tables.
For slow list views, look at the columns. Every many2one field in a list view adds a join to the query. A list view with 8–12 many2one columns on a large table will be slow no matter how good your indexing is. Cut it down to the essential fields, or build a database view that pre-computes the joins.
Over time, the Odoo file store accumulates orphaned attachment files — files that are stored on disk but no longer referenced by any database record. Odoo has a built-in filestore cleanup tool in the database manager. Run it in a maintenance window with a fresh backup in hand.
While you’re at it, purge the session directory. Session files accumulate continuously and aren’t automatically cleaned up in all Odoo configurations. A session directory sitting at 500,000+ files adds filesystem lookup overhead to every single request. A scheduled task to remove session files older than 7 days keeps it manageable.
Before anyone touches your Odoo configuration or infrastructure, collect this data first. Going in without it is guesswork.
Server resource utilization. CPU usage during slow operations, RAM and swap usage at peak load, disk I/O during slow database operations. High swap tells you the system is memory-constrained. High CPU on PostgreSQL processes points to query inefficiency. High disk I/O usually means missing indexes or a maintenance backlog.
Odoo slow log. Turn on INFO-level Odoo logging and capture the server log during a slow period. Response times are logged per request — you want to identify the exact URL paths where the slowness is concentrated.
PostgreSQL slow query log. Enable the PostgreSQL slow query log with a 1-second threshold. Collect it for 30 minutes during a busy period. This tells you exactly which SQL queries are causing database load, which is what you need before you can add indexes or rewrite views.
Module and user count. Document how many modules are installed, how many active users you have, and what your peak concurrent user count is. This establishes the baseline for Odoo workers and memory reconfiguration.
If a partner recommends adding RAM before they’ve looked at your slow log and query plans, they’re selling hardware, not optimization.
This work also requires access to production data — or a production mirror with full data for testing. Fixes validated only against a dev instance with minimal records won’t behave the same way in production.
Want a diagnostic-first Odoo performance engagement — no predetermined fix list?
1
Odoo performance degrades over time mainly for three reasons: database growth without regular maintenance, Odoo workers sized for your original user count rather than today’s load, and custom views or reports that weren’t tested against real production data volumes. These aren’t platform limitations — they’re maintenance and Odoo configuration gaps. Regular VACUUM ANALYZE, correct worker sizing, and periodic query plan reviews keep Odoo running well as your data and user load grow.
2
The seven most effective fixes are: PostgreSQL database maintenance and index optimization, worker count and memory limit tuning, PostgreSQL connection pooling with PgBouncer, Nginx caching for static assets, unused module removal, report and view query optimization, and file store cleanup and session purging. Of these, database maintenance and worker configuration produce the largest performance improvements for most mature Odoo instances.
3
A diagnostic engagement takes one to two days to collect and analyze performance data. Fix implementation depends on the specific issues found — database maintenance and worker reconfiguration take hours, custom query optimization for complex reports may take days per report. A full odoo performance optimization services engagement from diagnostic to post-fix baseline typically takes one to three weeks.
4
Most fixes involve minimal downtime. PostgreSQL VACUUM ANALYZE runs online without blocking reads or writes. Worker reconfiguration needs an Odoo service restart — typically a few minutes. You can add database indexes online in PostgreSQL using CONCURRENTLY without locking the table. File store cleanup and session purging need a short maintenance window. Report and view query changes deploy as module updates, which require a brief Odoo restart.
5
Yes. BiztechCS delivers odoo performance optimization services for businesses experiencing slow Odoo performance — covering database diagnostics, query plan analysis, worker and memory configuration, Nginx setup, custom report optimization, and infrastructure recommendations. Engagements begin with a diagnostic phase to identify root causes before fixes are scoped. BiztechCS is an Odoo Ready Partner with 25+ certified experts and 19+ years of enterprise software delivery.
Development
ERP
Odoo
Odoo Partner
UK ERP
348
By Uttam Jain
Development
ERP
Odoo
Odoo Partner
UK ERP
374
By Uttam Jain
Development
ERP
Odoo
Odoo Partner
UK ERP
374
By Uttam Jain