Configuration or Customisation: The Odoo Decision That Sets Your Next Five Years
· 14 min read · Faceela
There is one decision in an Odoo project that outlives everything else in it. Not the edition, not the partner, not the go-live date. It is the decision made, over and over, in workshops during weeks three to ten: when a requirement does not match what the product does, do you change the product or change the requirement?
It gets made dozens of times, usually in under a minute, usually by whoever speaks first, and almost always without anyone naming the cost. Five years later it is the only thing that explains why one company runs a boring, current, cheap-to-own Odoo and another runs a version-locked system that costs more each year and nobody will quote to upgrade.
The two companies bought the same software.
We write custom code. We sell it. Read what follows with that in mind, and note that the argument runs against our own short-term interest: code bills better than a conversation concluding you did not need it.
If you are earlier in the process than this, what Odoo does well and badly in the UAE is the wider picture; this page is the technical core of it.
There are not two answers. There are five.
The framing "configuration versus customisation" is already too coarse. In practice every requirement lands in one of five buckets, and they have wildly different costs, different risk profiles and different behaviours at upgrade time.
| Answer | What it is | Where it lives | What happens at the next version |
|---|---|---|---|
| Standard | The product already does this, differently from how you do it today | Nowhere. It is the product | Nothing. It moves for free |
| Configuration | Settings, chart of accounts, taxes, pricelists, warehouse routes, approval rules, user groups, document sequences | Database records that the product is designed to hold | Carried across. Occasionally a setting is renamed or replaced |
| Studio | Fields, views, simple automations and reports built without code | Database records, in the same tables a developer would write to | Carried across by the upgrade process, mostly. It is not free and not guaranteed |
| Custom module | Python and XML written for you | Files in a repository, deployed to your server | Yours to move, test and re-certify. Every version. Forever |
| Process change | You stop doing it your way | In your people | Nothing to move. The cheapest answer available and the hardest to sell |
Where the line actually sits
The usable rule is not about difficulty. It is about who owns the behaviour afterwards.
Everything Odoo is designed to let you shape — the structure of your accounts, which route a product follows, who approves what above which amount, what a pricelist does, which sequence a document takes, what a user can see — is configuration. It is data. The product ships knowing this data varies per company, and it carries it forward on your behalf.
Everything that changes what the product does — a new model, a method overridden, a computed value that did not exist, a workflow with a state Odoo does not have, a screen that behaves differently from every other screen of its type — is code. From that moment the behaviour is owned by you, and the product no longer takes responsibility for it existing next year.
Studio sits in an uncomfortable middle, and it is routinely described as a safe alternative to development, which is only half true.
What Studio actually does is write the same underlying records a developer would: a field definition, an inherited view, an automation rule. Those are data, and the upgrade process knows about them, which is why Studio work survives a version change far more gracefully than a custom module. That is a real advantage.
What Studio also does is remove every engineering control at once. No code review, no version control, no test, no environment separation unless someone deliberately builds one, and — critically — no record of why. A field added in year one to solve a problem that was solved differently six months later is indistinguishable, in year three, from a field the business depends on.
The characteristic Studio failure is not a crash. It is an ageing system with two hundred added fields where nobody can say which twenty are used, or what breaks if any of them is removed.
So nothing is ever removed, and every later change is made on top of sediment.
There is a third category people forget entirely, and it is the worst option available: Python written into automation rules and server actions inside the database. It looks like configuration because it lives in a settings screen. It behaves like code because it is code. No version control, no review, no test, no visibility to anyone not looking for it, and it breaks on upgrade exactly like a module would — except that nobody has a list of it.
Why code costs you at every version, specifically
This is the part that gets waved away as "there is some maintenance", so it is worth being concrete about the mechanism rather than the sentiment.
Odoo ships a major version every year, and the framework moves between versions in ways that do not fail politely. A change in a core model's field names, a stricter view validator, a method whose signature moved, a deprecated pattern that now emits a warning — none of these produce a message saying "your customisation is out of date". They produce an install error, or worse, silence and wrong behaviour.
One concrete example, because abstractions do not persuade anyone: between Odoo 18 and 19 the field holding a user's group membership was renamed, and the mechanism that groups permissions on the settings screen moved to a different model entirely. Security definitions written the old way generate no warning. They stop the module installing. A team meeting that for the first time, mid-upgrade, on a Thursday, will lose more than a day to it.
Multiply that across every custom field, modified view, extra report, overridden method and automation somebody added in year two. Each must be read, moved, tested and re-signed-off by the business. The bill is proportional to how much of it there is, and nobody counts it until the first upgrade, at which point counting it is itself part of the cost.
Not all code ages equally, and the difference is engineering discipline rather than luck:
- Additive code ages well. A module that adds a model of its own, adds a field, and inserts into an existing view at a stable anchor point will usually move forward with modest effort.
- Overriding code ages badly. A module that replaces core logic is coupled to the internals of that logic. When the internals change, your override either breaks loudly or, far worse, silently keeps doing the old thing next to core's new thing.
- View surgery ages unpredictably. A modification anchored to a specific element in a standard screen depends on that element still being there and still being called the same thing. Redesigns happen.
- Printed documents age on their own schedule, because they are rendered by a different engine from the one drawing your screen, with its own constraints.
- Untested code ages worst of all. A custom module with automated tests tells you, in minutes, what the new version broke. A module without them tells you in production.
Which produces the single most useful contractual requirement in this whole article: every custom module delivered to you must ship with automated tests, and the test suite must run clean on a fresh database. If a partner treats that as an unusual request, you have learned something about what your upgrades will cost.
This is the same mechanism that decides whether an upgrade is a formality or a project, which is why judging whether an upgrade is worth doing is really a question about decisions made years earlier.
Telling a real gap from an unwillingness to change
Most requirements that appear to need code do not. They need somebody to say out loud that the current process exists for a reason that no longer applies.
Here is a sequence that works. It takes about ten minutes per requirement, and it is the highest-return ten minutes in the whole project.
1. Ask where the requirement comes from. There are four honest sources: a law or regulator, a customer contract, a genuine operational constraint (a machine, a warehouse layout, a bank's file format), or a competitive advantage you can articulate. Anything else — "this is how we do it", "the previous system worked like that", "the finance manager prefers it" — is a preference. Preferences are legitimate and they are not requirements, and the difference must be visible in the document.
2. Ask who benefits. If the answer is one person and the cost is a permanent module, that is not a business case, it is seniority expressed as scope.
3. Ask whether the process is a workaround for a constraint that has just been removed. A large proportion of "requirements" in ERP projects are scar tissue from the old system: a three-step approval that exists because the old system could not restrict a field, a reference format that encodes what the old system could not store, a spreadsheet that exists because two modules did not talk. On one data model, some of these dissolve on contact. Nobody notices unless somebody asks.
4. Ask what the standard flow would actually cost you. Not "is it different" — different is a given. What is the measurable cost of doing it Odoo's way: extra clicks, a reconciliation someone has to do, a customer who notices? Frequently the honest answer is a few minutes a week, and it is being solved with a module that must be re-tested annually.
5. Offer the ninety-day test. Go live standard. Live with it for a quarter. If it is still genuinely painful, build it then, with evidence of what it costs. Little survives this test, and what does is exactly what was worth building. The objection is always the same — "we can't go live without it" — and it is worth asking whether that is a fact or a forecast.
Some requirements pass every one of these tests, and they are real. Sector processes the product does not contain — the interim payment certificate chain that standard Odoo cannot do for a UAE contractor is the clearest example in this market. Regulatory file formats. Integrations. Performance work at genuine volume. Understating a real gap is as damaging as inventing a false one: a business whose core process does not exist in the product, told "Odoo does everything", is being set up for the month-five discovery.
The judgement is not "avoid code". It is to spend it where the business genuinely differs from every other business, and nowhere else.
How to write the requirement so the answer cannot be quietly chosen for you
The commercial asymmetry is simple. A day of configuration and a day of development bill similarly, but development creates a maintenance stream and configuration does not. No conspiracy is required for this to bend outcomes; it is enough that nobody in the room is paid to argue the other way. The defence is documentary, and it has to be in place before the contract rather than after.
Write requirements as outcomes, not as solutions. "The system must prevent a delivery being confirmed when the customer is over their credit limit, unless the finance manager approves it" is a requirement. "Add a button to the delivery screen" is a design decision you have made on the partner's behalf, and it eliminates three cheaper answers before anyone has considered them. A requirement stated as a screen, a button or a field will be built rather than configured.
Demand a disposition against every requirement, in writing, before contract. One row per requirement, and one of five values:
| Disposition | What it commits the partner to | What you should ask for |
|---|---|---|
| Standard | It works today, as shipped | A demonstration on your data, not on the demo database |
| Configuration | Achievable with settings and master data | Which settings, named |
| Studio | Fields, views or automation, no code | The artefact list, and who maintains it |
| Custom module | Code | A named module, an estimate, and the upgrade implication stated |
| Process change | You change how you work | Named owner and what changes |
The document that carries this is worth more than the price on the cover of the proposal. It is also, in our experience, the single most common thing missing from Odoo proposals in this market.
Make reclassification a controlled event. The clause that matters: any requirement moving from Standard, Configuration or Studio to Custom Module is a change request, requires your written approval, and states the upgrade cost implication at the time of the request. Without that clause, dispositions drift upward silently during delivery and you find out from the invoice.
Ask the reverse question in the demo. Not "can Odoo do this" — with enough code the answer is always yes. Ask: "show me this working in a standard system today, and if it needs building, say so now." How fast and how specifically a team answers that is the clearest read available on them, which is the theme of how to choose an Odoo partner in the UAE.
Require a customisation register as a project deliverable. One row per artefact: the module or Studio object, the core model it touches, the requirement it serves, who asked for it, the date, and whether it has tests. It takes an hour a week and it is the document that prices your first upgrade. Companies that keep it get a quote; companies that do not get a discovery exercise billed at a day rate before anyone can quote at all.
Insist that custom code lives in a repository you can read today, with the intellectual property assigned in the contract. Not source on request — access now.
Code that exists only on a supplier's server is not an asset you own; it is a relationship you cannot leave.
The order to work in
The sequence below is not a preference. It is a cost ordering, and every step you skip multiplies the ones after it.
- Standard. Try the flow as shipped, on your data, with the people who will use it. Not a demo — a real transaction, end to end.
- Process change. If standard is different but workable, change the process. Free to build, and the only answer with no maintenance at all.
- Configuration. Settings, master data, routes, approval rules, groups, sequences. Reversible, carried forward, and far more capable than most buyers realise.
- Studio, deliberately and with a register. For genuinely small additions: a field the business needs, a view arrangement, a simple automation. Written down as it is created, not reconstructed later.
- An existing application from the Apps store, if one genuinely fits. Ask who maintains it, whether it has been released for the current version, and what happens when it is not released for the next one.
- A custom module, written properly. Additive rather than overriding. Tested. In your repository. Documented as to why it exists, and costed with the upgrade tail inside the number you approve.
Steps one and two are where the money is saved. Steps five and six are where the money is spent. A partner who arrives at step six in the first workshop has skipped the four cheapest answers and should be asked, out loud, why.
There is a wider version of this judgement — whether to buy a product at all or write software for a process that is genuinely yours — set out in how to decide between building and buying. The Odoo-specific version is narrower and more brutal: inside a product that ships annually, every line you write is rented, not owned.
What this decision does to the rest of your project
The configuration-first position is not conservatism, and it is not a claim that custom code is bad. It is an observation about compounding.
Configuration compounds in your favour: each decision is reversible, carried forward by the vendor, and understandable to whoever inherits your system. Code compounds against you. Each module adds to the surface that must be re-tested at every version, increases the number of people who must understand your system before they can change it, narrows the pool of firms willing to take it on, and raises the cost of the next change — including the changes that would have been trivial.
The companies frozen three versions back are rarely the ones that customised badly. They are the ones that customised casually: no register, no tests, no disposition document, no clause requiring approval before a requirement became code. Each individual decision was defensible. The aggregate was not, and by the time anyone looked at the aggregate it was already the system.
The choice of edition and hosting sits underneath all of this, because one of the hosting options forecloses custom code entirely and is therefore the strongest governance control available — the trade-offs are in the real difference between Community and Enterprise.
If a genuine gap does need building, build it properly: additive, tested, owned by you, written to be moved forward. That is how software written specifically for you should be delivered whatever the platform.
And if you are holding a proposal now and cannot tell which of its requirements will be configured and which will quietly become code, that is the document to fix before you sign. Producing it — each gap classified, priced and argued honestly, including the ones we would recommend you drop — is where our Odoo implementation work begins.
