A slow Odoo system does not always need a larger server. Delayed searches, reports that take minutes to load and transactions that stall can result from inefficient queries, custom code, database maintenance issues or limited server resources.
Effective Odoo database optimization starts with identifying which part of the system is slow. Adding indexes or increasing memory without that information can cost money without solving the underlying problem.
This guide explains how to investigate database performance, identify common bottlenecks and choose an appropriate fix.
Diagnose Where the Slowdown Occurs
1. Confirm Whether the Database Is the Problem
Before changing PostgreSQL settings, establish where the delay occurs.
For example:
If opening one list view is slow, the domain, sorting, number of displayed records or custom fields may be responsible.
If several unrelated operations are slow, investigate shared server resources, database load and network latency.
If a particular report is slow, inspect its queries, aggregations and custom computation.
If the delay occurs during a scheduled job, examine the job's workload and execution history.
The Odoo application, PostgreSQL database, custom modules and hosting environment all affect performance. A database-focused fix will not solve every application-level bottleneck.
2. Profile Slow Operations Before Optimizing
The first step in Odoo database optimization is to measure the operation that users report as slow.
Odoo includes a profiler that can record SQL queries and execution traces. It helps developers see whether time is being spent running database queries, executing Python code or handling other parts of a request.
What to check:
Reproduce the slow action.
Enable profiling in a suitable test or diagnostic environment.
Inspect the SQL queries and execution traces.
Look for repeated queries, expensive operations and unnecessary data retrieval.
Compare performance before and after a targeted change.
The profiler has overhead, so use its results to locate likely bottlenecks and then measure the final change under representative conditions.
For production databases, consider access, workload and data sensitivity before enabling diagnostic tools.
Fix Query and Code Problems
3. Reduce Repeated ORM Queries
Custom Odoo code can generate far more database traffic than necessary.
Consider this example:
for partner in partners:
order_count = self.env['sale.order'].search_count([
('partner_id', '=', partner.id)
]) This performs a separate count operation for each partner. With a large recordset, repeated queries can become expensive.
Where appropriate, batch the operation using _read_group()
orders = self.env['sale.order']
counts = orders._read_group(
[('partner_id', 'in', partners.ids)],
['partner_id'],
['__count'],
)
count_by_partner = dict(counts)
for partner in partners:
partner.order_count = count_by_partner.get(partner, 0) This illustrates the batching approach, but the exact return structure and aggregation behaviour should be checked against the Odoo version and model. Also consider whether an existing relational field or a stored computed field would be more suitable.
Batching reduces repeated database round-trips. It does not guarantee that every operation becomes faster, so profile the actual workload. When repeated ORM calls, inefficient computed fields, or custom business logic contribute to slow requests, the solution may require changes to the underlying code. Our Odoo Development Services can help review custom modules, identify inefficient operations, and improve performance while keeping the code maintainable.
4. Add Indexes Where the Query Needs Them
Database indexes can improve searches when PostgreSQL can use them to locate matching rows without scanning an entire table.
For example, a custom Odoo field may be declared with an index:
reference_code = fields.Char(index=True)This may help when queries frequently filter on reference_code , but it is not a universal performance fix.
Before adding an index, investigate:
Which fields appear in slow query filters or sorting operations?
How many records match the query?
Does PostgreSQL already have a suitable index?
Will the index improve the actual query plan?
What additional write and storage costs will it introduce?
Indexes consume storage and add work to inserts, updates and deletes. Indexing every field can therefore make some workloads worse.
Check the query plan:
PostgreSQL's EXPLAIN shows the plan selected for a query. EXPLAIN ANALYZE executes the query and reports actual execution statistics.
Use these tools in a safe environment and with queries that are appropriate to run. EXPLAIN ANALYZE can execute the underlying statement, including data changes if used on a modifying query.
Compare estimated and actual row counts, scan methods and execution times. A sequential scan is not automatically a problem; PostgreSQL may correctly choose one when a query needs a large portion of a table.
5. Review Expensive Searches and Reports
Some slow Odoo screens are caused by the amount of data being requested rather than a database failure.
Common examples include:
List views loading too many records.
Domains that return far more rows than necessary.
Reports aggregating large datasets repeatedly.
Custom fields that trigger expensive calculations.
Sorting or filtering on fields without suitable query support.
Practical improvements:
Limit results where the user does not need every record at once.
Retrieve only the fields needed for the operation.
Apply filtering in the ORM domain where possible.
Use grouped queries for suitable reporting and aggregation tasks.
Review computed fields and their dependencies.
Avoid repeated searches inside loops.
These changes can improve Odoo database optimization efforts without requiring changes to PostgreSQL configuration. If slow screens or reports are tied to custom fields, complex calculations, or heavily modified workflows, reviewing the customization may be necessary. Our Odoo Customization Services can help assess existing functionality and make targeted changes to better support your business processes.
When investigating slow ORM operations, review how custom models and business logic retrieve and process records. If you need to understand how custom functionality is structured in Odoo, read our guide on building a custom Odoo module.
Check PostgreSQL and Infrastructure
6. Check PostgreSQL Maintenance and Statistics
PostgreSQL maintains statistics that help its query planner choose execution plans. If those statistics do not accurately reflect the data, the planner may make poor decisions.
Routine maintenance also helps PostgreSQL reclaim space occupied by obsolete row versions created by updates and deletes.
What to review:
Whether autovacuum is enabled and keeping up with database activity.
Whether important tables have current planner statistics.
Whether recent bulk changes have affected query performance.
Whether database logs show long-running queries, lock waits or resource pressure.
PostgreSQL normally handles routine vacuuming and statistics collection automatically. Do not assume that manually running maintenance commands will improve every slow database.
In particular, VACUUM FULL is not a routine first-line performance fix. It rewrites a table, can require additional disk space and takes an exclusive lock that blocks other access to that table. Use it only when there is a justified maintenance reason and a suitable operational plan.
7. Investigate Locks and Long-Running Transactions
A query can be slow because it is waiting for another transaction rather than spending time processing data.
This can occur when one transaction holds a lock that another operation needs. Long-running transactions can also delay maintenance and increase operational pressure.
When users report intermittent delays, check database activity and logs for:
Queries waiting on locks.
Transactions that remain open for a long time.
Repeated timeouts during busy periods.
Scheduled jobs that overlap with high-volume business operations.
Do not terminate database sessions blindly. Identify the transaction, understand its purpose and assess the impact before taking action.
8. Check Hosting Resources and Database Configuration
If profiling and query analysis do not explain the delay, examine the hosting environment.
Relevant factors include CPU availability, memory pressure, storage latency, database connections, Odoo worker configuration and the number of concurrent users.
Look for evidence before changing settings. For example, increasing the number of workers without sufficient CPU or database capacity may simply move the bottleneck elsewhere.
Likewise, increasing PostgreSQL memory settings without considering total system memory and concurrent operations can create resource problems.
For managed hosting or Odoo Online, access to infrastructure settings may be limited. In those environments, focus on application-level diagnostics and raise infrastructure concerns with the hosting provider where necessary.
Build a Repeatable Performance Checklist
A practical Odoo database optimization process should record the original problem and the result of each change.
Use this checklist:
Identify the slow screen, report, transaction or scheduled job.
Record the affected Odoo version and hosting environment.
Reproduce the problem with representative data.
Profile the operation and inspect expensive SQL queries.
Review ORM batching, domains and computed fields.
Inspect query plans before adding indexes.
Check PostgreSQL statistics, maintenance and lock activity.
Review server resources and concurrency.
Test one targeted change at a time.
Compare performance and confirm business behaviour remains correct.
Document the change and monitor the result.
This approach makes it easier to distinguish a real improvement from a temporary change in workload.
Conclusion
Optimizing a slow Odoo database starts with identifying what is causing the delay. Profile the affected operation, review SQL queries and ORM behavior, inspect indexes and PostgreSQL statistics, and check for locks or resource constraints before changing database settings.
Make one targeted change at a time, then measure the results under representative conditions. This helps confirm that performance has improved without introducing data integrity issues, unnecessary write overhead, or new bottlenecks. If slow performance persists across multiple workflows or involves complex custom modules, PostgreSQL configuration, or hosting resources, a broader technical review may be necessary. Discuss your Odoo performance challenges and identify a practical way forward.

