Optimizing Odoo Performance with Caching Techniques

March 10, 2026 by
Optimizing Odoo Performance with Caching Techniques
Alfin Isnain Hariawan
| No comments yet

Odoo is a powerful ERP system used by thousands of companies to manage their operations. However, as the amount of data grows and the number of users increases, performance can become a serious concern. Slow loading views, heavy database queries, and repeated computations can significantly impact the user experience.

One effective strategy to improve Odoo performance is caching. By storing frequently accessed data in memory, caching reduces the need for repetitive database queries and expensive computations.

In this article, we will explore how caching works in Odoo and how developers can use it to optimize system performance.


Why Caching Matters in Odoo

Every time Odoo processes a request, it often performs several database queries. In systems with large datasets, these queries can become expensive and slow.

Common situations where performance issues appear include:

  • Large datasets with thousands or millions of records
  • Heavy compute fields
  • Frequently accessed configuration data
  • Complex domain searches
  • Reports that require multiple joins

Caching helps solve this by storing frequently used results so that Odoo can retrieve them directly from memory instead of querying the database repeatedly.

The result is:

  • Faster response time
  • Reduced database load
  • Improved scalability


Types of Caching in Odoo

Odoo already provides several built-in caching mechanisms that developers can use.


1. ORM Prefetching

Odoo’s ORM automatically performs prefetching, which is a form of caching.

When you access a field in a recordset, Odoo automatically loads other fields of that recordset to reduce future queries.

Example:

partners = self.env['res.partner'].search([])
for partner in partners:
print(partner.name)

Instead of executing a query for each partner, Odoo fetches the required data in batches.

Best Practice

Always work with recordsets instead of repeatedly searching inside loops.

Bad example:

for partner_id in partner_ids:
partner = self.env['res.partner'].search([('id', '=', partner_id)])

Better approach:

partners = self.env['res.partner'].browse(partner_ids)

This significantly reduces database queries.


2. Using tools.ormcache

Odoo provides a powerful decorator called ormcache that allows developers to cache function results.

Example:

from odoo import tools

class Product(models.Model):
_inherit = 'product.product'

@tools.ormcache('product_id')
def get_product_name(self, product_id):
product = self.browse(product_id)
return product.name

With this decorator, the function result is cached based on the input parameter.

This means that if the same product ID is requested again, Odoo will return the cached result instead of querying the database.

When to Use ormcache

Use it for:

  • Configuration values
  • Frequently accessed data
  • Data that rarely changes

Avoid using it for:

  • Frequently updated records
  • User-specific data


3. Environment Cache (env.cache)

Odoo internally maintains a cache at the environment level. This cache stores record values to avoid repeated database access.

Example:

self.env.cache.invalidate()

Developers can clear this cache when necessary, especially after performing direct SQL operations.

However, it is important to use cache invalidation carefully to avoid unnecessary performance penalties.


4. Computed Field Caching

Computed fields can cause performance issues if they are recalculated too often.

Example of a heavy compute field:

total_amount = fields.Float(
compute="_compute_total"
)

If the compute method performs complex calculations or database queries, performance can degrade quickly.

Solution:

Use stored computed fields.

total_amount = fields.Float(
compute="_compute_total",
store=True
)

This ensures the value is stored in the database and only recomputed when dependencies change.


5. Reducing Repeated Queries

A common performance mistake in Odoo development is performing searches inside loops.

Example of a bad pattern:

for order in orders:
partner = self.env['res.partner'].search([('id', '=', order.partner_id.id)])

This generates a query for every iteration.

Better solution:

partners = orders.mapped('partner_id')

This leverages Odoo’s ORM caching and prefetching capabilities.


6. Caching Configuration Parameters

System parameters are frequently accessed in Odoo.

Instead of querying them repeatedly, cache them.

Example:

@tools.ormcache()
def get_setting(self):
return self.env['ir.config_parameter'].sudo().get_param('my_module.setting')

This prevents repeated database queries for the same configuration value.

When Caching Can Be Dangerous

While caching improves performance, it must be used carefully.

Potential risks include:

  • Stale data if cache is not invalidated properly
  • Memory consumption if too many values are cached
  • Incorrect results when data changes frequently

Therefore, caching should only be applied to stable and frequently accessed data.

Real Performance Improvement Example

In a real production system with large datasets, a report was taking 12 seconds to load because it executed the same query multiple times.

After applying:

  • ormcache
  • better recordset usage
  • removing queries inside loops

The report execution time dropped to less than 2 seconds.

This demonstrates how powerful caching can be when used correctly.


Conclusion

Caching is one of the most effective ways to improve Odoo performance. By reducing unnecessary database queries and expensive computations, developers can significantly speed up the system and improve scalability.

Key techniques include:

  • Leveraging ORM prefetching
  • Using tools.ormcache
  • Storing computed fields
  • Avoiding queries inside loops
  • Caching configuration values

When applied properly, these techniques can transform a slow Odoo system into a highly responsive and scalable platform.

Optimizing Odoo Performance with Caching Techniques
Alfin Isnain Hariawan March 10, 2026
Share this post
Archive
Sign in to leave a comment