Back to Blogengineering5 min read
Custom Odoo Modules: When to Configure, When to Customise, and How to Keep Upgrades Painless
Odoo is easy to customise — which is exactly how companies end up with unmaintainable systems. The decision rules, the module patterns, and the habits that keep a customised Odoo upgradeable.
Mazen Salah

The best thing about Odoo is that a developer can change almost anything in an afternoon. The worst thing about Odoo is the same sentence. We inherit systems every year where hundreds of small "quick fixes" have fused into a fork nobody dares to upgrade, and the company is stuck on a version that is three releases behind and out of support. None of that was necessary.
This is our playbook for customising Odoo without losing the upgrade path: how to decide what deserves code, how to structure a module, and the engineering habits that keep the bill for each annual version small.
The decision ladder
Before writing code, walk down this ladder and stop at the first step that solves the problem.
- Configuration. Settings, sequences, taxes, fiscal positions, routes, automated actions, email templates, access rights. Most "we need a customisation" requests end here once someone who knows the product looks at them.
- Studio (Enterprise). Extra fields, list and form tweaks, simple automations, report edits. Studio changes are stored as data, survive upgrades reasonably well, and need no developer.
- Existing modules. The Odoo App Store and the OCA (Odoo Community Association) publish thousands of maintained modules. An OCA module with active maintainers is usually a better bet than custom code for a generic need.
- A custom module. Your process is genuinely specific — a rental calculation, a laundry routing rule, a contractor's retention billing — and it delivers business value that justifies permanent maintenance.
"It would be nicer if" requests do not reach step 4.
How to structure a custom module
A clean Odoo module is small, named for the business capability, and depends only on the modules it extends.
- One module per concern.
acme_rental_pricing, notacme_customisations. When a concern is retired, its module is uninstalled without touching the rest. - Inherit, never edit. Extend models with
_inherit, extend views with XPath, override methods withsuper(). Editing core files means your changes evaporate on upgrade — and breaks Odoo's own updates in between. - Keep business rules in Python, presentation in views. Computed fields and constraints belong in the model; a QWeb report should not contain logic.
- Data files for configuration. Sequences, default records and security rules ship as XML or CSV inside the module so a fresh database reaches the same state.
- Security first. Every new model gets
ir.model.access.csvrows and, where needed, record rules. Odoo denies access to models with no rules by default; the fix is not to grant everything to everyone. - Tests. Odoo's test framework runs on module install. Even a handful of tests covering the pricing rule or the approval flow turns each upgrade from "hope" into "run the suite".
Integrations without pain
Most custom work in the GCC is integration: payment gateways, couriers, e-commerce storefronts, banks, mobile apps. Three rules:
- Use the external API (XML-RPC or JSON-RPC) from outside, and controllers inside, rather than letting external systems touch the database.
- Make integrations idempotent. Deliveries get re-sent; webhooks fire twice. Store the external reference and skip duplicates.
- Queue anything slow. A ZATCA submission or a courier booking should not block a salesperson confirming an order; use Odoo's job queue (the OCA
queue_jobmodule) or scheduled actions.
We build mobile apps on top of Odoo this way — see extending Odoo with a custom mobile app — with a thin API layer in a module rather than the app talking to models directly.
The upgrade habit
Odoo releases a major version every autumn and supports roughly the last three. A customised system stays upgradeable if you:
- Pin the version in the module manifest and keep a changelog of what each module changes and why.
- Upgrade every year, or every second year at most. Two versions is a project; four is a rewrite.
- Run the upgrade in staging first. Enterprise's upgrade service returns a migrated database; you then port modules, run tests and fix what changed. Community uses OpenUpgrade scripts and more manual work.
- Delete what you no longer use. Every custom module you carry forward costs time on each upgrade; retire the ones whose business reason has gone.
- Prefer OCA modules over your own when both exist — the OCA ports them to new versions for you.
Our Odoo 19 and 20 upgrade guide walks through the cycle in detail.
Signs a system needs rescuing
- Core files have been edited (
git diffagainst upstream Odoo shows changes outsideaddons/custom). - Custom modules named after people or dates.
- No tests, no staging environment, upgrades "not possible".
- A single
customisationsmodule with 40 models in it. - Business rules living in server actions and automated actions written in the UI, undocumented.
Rescue is possible — usually by rebuilding the custom layer as proper modules on a fresh, current version and migrating the data — and is often cheaper than another year of workarounds.
Key takeaways
- Walk the ladder: configuration, then Studio, then existing modules, then custom code.
- One module per concern, inherit rather than edit, ship security and tests with every module.
- Integrate through the API with idempotent, queued jobs.
- Upgrade every year; delete modules whose reason has gone.
SummationWorks builds and rescues custom Odoo modules and integrations for companies in the GCC and Egypt. See our Odoo and ERP services, read about Odoo versus a fully custom ERP, or talk to an engineer about your system.
About the author
Mazen Salah
Founder & Lead Engineer
Mazen Salah founded SummationWorks in 2019 to help startups and growing businesses ship real software. He leads engineering across the company's web, mobile, and AI work, building products with Next.js, Flutter, Laravel, and Node.
More about usRelated Articles

engineering6 min read
Odoo and ZATCA Phase 2: E-Invoicing Compliance for Saudi Businesses
Wave 24 closed in June 2026 and Wave 25 pulls in every business above SAR 187,500. Here is how ZATCA Phase 2 works, what Odoo does natively, and the setup steps that trip most companies up.
Mazen Salah

engineering5 min read
Odoo 19 Today, Odoo 20 This Autumn: When and How to Upgrade
Odoo 19 brought AI into every app and a new interface; Odoo 20 arrives around October 2026. A practical guide to what changed, which versions are running out of support, and how to plan an upgrade that doesn't break your customisations.
Mazen Salah

engineering5 min read
Extending Odoo with a Custom Mobile App: Field Sales, Delivery and Customer Apps
Odoo's own mobile app is fine for the office. Drivers, field sales reps and customers need something built for them. How we design and build Flutter apps on top of Odoo without turning the ERP into a bottleneck.
Mazen Salah
Have a project in mind?
Let's turn your idea into production-grade software.