Computed fields in Odoo can seem like a straightforward concept at first – just some logic, a decorator, and voilà, the value is where it should be. But as the amount of data increases and more people depend on these values on a daily basis, this simplicity becomes a heavy factor. A single decision, such as whether to store a computed field or not, can silently impact the loading times, search results, and overall system performance.
This is a lesson many developers learn the hard way when things start slowing down or acting erratically. Stored computed fields and non-stored computed fields may look identical in code, but Odoo handles them in a completely different manner.
In this blog, we will discuss the differences between stored and non-stored computed fields, the impact of both on performance, and why it is important to make the right decision at the right time.
What Is a Computed Field in Odoo?
A computed field is a field whose value is calculated based on Python logic rather than being manually entered by a user. The value is dependent on one or more other fields, and Odoo automatically updates it based on these dependencies.
Example:
total_price = fields.Float(compute="_compute_total_price")
@api.depends('quantity', 'unit_price')
def _compute_total_price(self):
for record in self:
record.total_price = record.quantity * record.unit_price
At this stage, the field is non-stored by default. Odoo computes it every time the value is requested.
Non-Stored Computed Fields in Odoo
Non-stored computed fields are the norm in Odoo. When a field is declared with a compute function but without store=True, Odoo will not store the value of that field in the database. Rather, it will compute the value every time it is requested, no matter whether it is requested from a form view, list view, or from any backend process.
What this means is that Odoo will consider the value of the field as temporary knowledge. The value will only exist for the brief moment that it is needed and will be gone as soon as the need is over. This is particularly useful when the computation is simple and the value is dependent on constantly changing data. This is because nothing is written to the database, so write operations are still light and fast.
Non-stored computed fields are commonly used for:
- Display-only values in form views
- Fields that depend on context or user-specific logic
- Calculations that are quick and inexpensive
However, since these fields are not stored, Odoo cannot use them in search domains, filters, or group-by statements. In list views with a large number of records, the compute method could be invoked multiple times, which could silently increase the processing time as the size of the data set increases.
Stored Computed Fields in Odoo
However, when a computed field is declared with store=True, Odoo takes a different route. Odoo does not compute the value every time it is requested but computes it once and stores the result directly in the database. After this point, the field acts like a normal stored field but is still governed by Python logic.
Suppose we want to display the number of confirmed sales orders for a particular customer. This is usually shown in list views and used for filtering, making it a good candidate for a stored computed field.
order_count = fields.Integer(compute="_compute_order_count", store=True)
@api.depends('sale_order_ids.state')
def _compute_order_count(self):
for partner in self:
partner.order_count = len(
partner.sale_order_ids.filtered(
lambda so: so.state == 'sale'
)
)
In this example, Odoo computes the value only when the dependent data changes, which in this case is when the sales orders or their statuses are updated. The value, once computed and stored, can be directly retrieved from the database, making it efficient to display in list views, dashboards, and reports.
This is where the benefit of stored computed fields comes into play. Since the data is stored in the database, Odoo can easily utilize it in search domains, filters, and group by operations. However, the drawback is that write operations are slightly more expensive, especially when many dependent records are updated at once. This is why it is important to have proper dependencies marked with @api.depends.
Performance Impact of Stored and Non-Stored Computed Fields
It is in the area of performance that the actual difference between stored and non-stored computed fields becomes apparent. In the initial phases of a project, it may seem as if both methods are interchangeable. However, once the number of records increases and usage becomes more intensive, the actual internal workings of Odoo regarding these fields begin to have a direct impact on performance.
Read Performance
Consider a non-stored computed field that shows a customer’s outstanding balance, calculated by iterating over related invoices.
outstanding_amount = fields.Float(compute="_compute_outstanding_amount")
@api.depends('invoice_ids.amount_residual')
def _compute_outstanding_amount(self):
for partner in self:
partner.outstanding_amount = sum(
partner.invoice_ids.mapped('amount_residual')
)
In a form view, this works fine. But imagine a list view displaying 500 customers. Odoo executes this computation 500 times — once for each record. As the number of invoices grows, so does the computation time, and list views begin to load noticeably slower.
Now compare this with a stored version:
outstanding_amount = fields.Float(
compute="_compute_outstanding_amount",
store=True
)
With store=True, Odoo reads the value directly from the database when loading the list view. The calculation happens only when an invoice changes, not every time the view is opened.
Write Performance
Stored computed fields shift some of the cost to write operations. For example, consider a stored field that counts confirmed sales orders:
order_count = fields.Integer(
compute="_compute_order_count",
store=True
)
@api.depends('sale_order_ids.state')
def _compute_order_count(self):
for partner in self:
partner.order_count = len(
partner.sale_order_ids.filtered(
lambda so: so.state == 'sale'
)
)
Whenever a sales order is confirmed or cancelled, Odoo recomputes this field. In normal usage, this overhead is small. But during bulk updates — such as importing thousands of orders — poorly defined dependencies can cause unnecessary recomputation and slow down write operations.
A non-stored field avoids this cost entirely, since nothing is written back to the database. This is why stored fields should be used selectively and with precise dependencies.
Search, Filter, and Group-By Performance
Imagine a requirement to filter customers based on their total confirmed order count. With a non-stored computed field, this is not possible:
# This will NOT work if order_count is non-stored
[('order_count', '>', 5)]
Developers often work around this by writing Python logic, fetching records manually, and filtering them in memory.
With a stored computed field, the same requirement works naturally. Odoo pushes the filtering logic to PostgreSQL, which is optimized for exactly this kind of operation.
How Performance Changes Over Time
The most important difference is how these choices age. A non-stored computed field might perform well when the database is small, but slow down gradually as records increase. Stored computed fields usually show the opposite pattern — slightly heavier writes early on, but stable and predictable read performance over time.
Computed fields that are stored and non-stored are two different approaches to performance. Non-stored fields are best when flexibility and low write cost are desired, while stored fields are best when fast read access, searchability, and stability over time are desired. The trick is not to make this decision blindly, but to recognize how each will perform as the amount of data increases.
When developers make this decision with their eyes open, based on real-world usage patterns and dependencies, Odoo applications will remain responsive, maintainable, and stable well after the initial deployment. This is the distinction between code that works and systems that last.
To read more about How to Improve Data Model Efficiency with Computed Fields in Odoo 19, refer to our blog How to Improve Data Model Efficiency with Computed Fields in Odoo 19.