Odoo's built-in automation looks like automation right up until two hundred records need processing at once and the interface hangs. What's actually happening underneath is almost always the same mistake, and it's an easy one to make without realizing it.
Where Point-and-Click Automation Hits a Wall
Odoo's built-in Automated Actions and Server Actions are genuinely good for simple triggers, but they encourage a pattern that breaks down under real production load: firing a discrete action per record change. That works fine for occasional single-record updates. It falls over the moment a bulk import or a mass update touches five hundred records at once, because each one independently triggers the automation — and each one may independently query the database.
The ORM Trap Almost Everyone Falls Into
The single most common performance bug we find in custom Odoo automation is a search() or browse() call inside a loop, executed once per record instead of once for the whole batch. It looks harmless in testing with ten records. At five thousand records, it turns a two-second batch job into a fifteen-minute one, and the interface times out long before it finishes.
- Batch your reads: replace a per-record search() call inside a loop with one search outside the loop, then filter in memory or use a dictionary keyed by the field you were searching on.
- Batch your writes: call write() once on a full recordset instead of calling it inside a loop — Odoo's ORM is built to handle this efficiently, but only if you give it the whole batch at once.
- Watch for recompute storms: a computed field with a broad @api.depends will recompute for every affected record on every write, and a poorly scoped dependency can silently recompute far more records than the change actually affects.
- Be deliberate with automated actions on write: an action that triggers on write, and itself writes to the same or a related model, can chain into a sequence that's hard to reason about and easy to turn into a performance problem or a loop.
The Debugging Question We Ask First
When a client says "Odoo has gotten slow since we added automation," the first thing we check is whether a computed field or automated action is doing per-record database queries inside a loop. In the majority of cases we've diagnosed, that's exactly it — and the fix isn't more hardware, it's rewriting the loop.
When to Reach for Server Actions vs. a Proper Python Module
Server Actions and Automated Actions are the right tool for simple, low-volume triggers — send a notification, set a field, create a follow-up activity. They stop being the right tool once the logic needs conditionals spanning multiple models, error handling that does something smarter than failing silently, or performance characteristics that matter at scale. At that point, the maintainable path is a proper Python module: a scheduled action for batch processing, wrapped in real exception handling, with logging that tells you what happened when something inevitably goes wrong overnight with nobody watching.
- Use Automated Actions for simple, low-volume, single-model triggers you can reason about in one sentence.
- Move to a custom module the moment logic spans multiple models with conditional branches — debugging cross-model automated action chains in the UI is genuinely painful.
- Use scheduled actions (ir.cron) for anything that processes in batches rather than reacting to individual record changes — this gives you control over batch size and timing that record-level triggers don't.
- Always wrap batch logic in explicit try/except with meaningful logging — a silent failure in an overnight batch job is far more expensive to diagnose than a loud one.
What "3x Faster" Actually Means in Practice
When we talk about tripling process speed through automation, we don't mean anything exotic — we mean the boring kind: a manufacturing client's planning team went from manually re-keying purchase requisitions into three separate spreadsheets to a scheduled action that reconciles inventory levels against reorder points automatically overnight. The speed gain is the difference between two people spending hours a day on reconciliation and it running unattended before anyone arrives at their desk. The technology isn't the interesting part. The interesting part is that someone mapped the manual process precisely enough to automate it correctly.
The teams that get the most out of Odoo customization aren't the ones writing the most exotic Python. They're the ones who understand the ORM's batching behavior well enough to avoid working against it, and who are honest about when a five-line automated action has quietly become two hundred lines of unmaintainable logic that belongs in a real module instead.