Skip to main content
ERP & AutomationBy10 min readUpdated:

The Upgrade You Inherit Is Not in the Guide

Executive summary

Every upgrade guide assumes you are moving the system you built. Most of the upgrades I have run were of systems somebody else built, left, and did not document — which is a different problem wearing the same name. At Tbar Holding I took an Odoo 15 estate to 18 in three months across seven operating entities, carrying database faults and code defects inherited from previous teams and a full data migration underneath. The version jump was the least interesting part. What decided the schedule was how quickly I could tell configuration from customisation, which customisations were still load-bearing, and which had been written for a business process the group had already stopped using. This is how I read an inherited implementation before touching it, and how the reading turns into a plan a finance director can hold.

Read it before you move it

An inherited implementation is a document written by people who are no longer in the room. Before I schedule anything I spend the first two weeks reading it: which modules are installed against which are actually used, which fields have data in them, which automated actions fire, which scheduled jobs still run and which have been failing quietly for a year because nobody watches a log that produces no complaint.

That reading is not a technical audit, and treating it as one is the common mistake. It is an archaeology of decisions. Every override in the system was written by somebody to solve a problem they had that week, and the useful question is not whether the code is good but whether the problem still exists. Half the time the person who needed it has left, the process changed, and the override is now a small permanent tax on every transaction that passes through it.

I write the findings as a list of statements a business owner can agree or disagree with, not as a technical inventory. Sales quotations are approved outside the system and entered afterwards. Three entities share a chart of accounts and a fourth does not. Nobody has closed a period in this module since last year. Each of those is a sentence somebody in the business will react to immediately, and their reaction tells me more about the scope than another week of reading code would.

The output of the two weeks is not a plan. It is an agreed description of the present, signed by the people who will have to live with what comes next. I have never regretted spending that fortnight, and I have regretted skipping it.

Configuration and customisation are two different risks

Configuration is what the product was built to let you change: fields, workflows, approval rules, pricelists, the shape of a journal entry. It survives a version jump because the vendor carries it forward on purpose, and when it breaks the break is visible and the fix is documented.

Customisation is code somebody wrote against the product's internals. It survives a version jump only to the extent that the internals it reached into did not move, and when it breaks it usually breaks silently — a computed field that stops computing, an inherited method whose parent signature changed, a report that renders with one column quietly empty. Nothing raises an error. A number is simply wrong from that day forward.

So the first artifact I build is a two-column list, and I build it before I estimate anything. Everything on the configuration side is schedule. Everything on the customisation side is risk, and each line gets a named owner in the business who can say what it is for. A customisation whose purpose nobody can state is the single most valuable finding in the exercise, and there are always more of them than anyone expects.

The estimate then writes itself in a way a finance director can follow, because the two columns behave differently under pressure. Configuration work compresses if you add people. Customisation work does not: it compresses only if you delete some of it, and deleting requires a decision from the business rather than effort from the team. Saying that sentence in the first week is what stops the project being asked in month two why more developers did not make it faster.

Half of what you are afraid to break is already dead

The reason inherited upgrades feel dangerous is that nobody knows what is still needed, so everything is treated as needed. That posture doubles the work and it is almost always wrong.

Usage data settles it faster than opinion does. For every customisation I ask three questions the database can answer: has the code path executed in the last ninety days, does the field it writes contain values newer than a year, and does any report or downstream integration read what it produces. A customisation that fails all three is not a risk to be carried across the upgrade. It is a deletion waiting for someone with the standing to approve it.

Getting that approval is a governance act rather than a technical one, and it is where the time is actually won. I put the dead list in front of the business owner as a decision with a stated consequence: this stops existing on the new version, here is what it did, here is who last relied on it and when. Almost nobody defends the ones that fail all three questions once the question is asked out loud. The ones somebody does defend are precisely the ones worth the migration effort.

At the holding group this exercise is what made three months possible. The version jump across seven entities was tractable because a meaningful share of what previous teams had written no longer needed to travel, and every removal was a decision the business had signed rather than a shortcut the technology team had taken. That distinction matters later, when something is missed and the question becomes who decided.

The data migration is the project

Teams plan an upgrade around the software and discover the data in the last fortnight. It should be the other way round. The software will move; the vendor tests that path and every other customer walks it. Your data has been tested by nobody, because no other group has your particular history of merged entities, corrected opening balances, and a period somebody reopened in 2022 and never closed again.

Across a group with several operating entities the hard part is rarely volume. It is that the entities disagree. One has customers keyed by commercial registration and another by a free-text name that has three spellings. One posts intercompany transactions through a clearing account and another through journal entries somebody writes by hand. A migration that treats these as one dataset produces a system that reconciles to nothing, and the discovery happens at the first month-end after go-live, which is the worst possible moment.

So I migrate in rehearsals, not in one attempt. Each rehearsal ends with the same fixed set of reconciliations — trial balance per entity, open receivables, inventory valuation where it applies, and a count of records that failed to load with the reason attached. The first rehearsal always fails. The value is that it fails in week four rather than in the go-live weekend, and that the failure arrives as a list somebody can work through rather than as an outage.

The last rehearsal before go-live should be boring. If it is not boring, the answer is to run another one, not to go live and fix forward. I have never seen fix-forward be cheaper on a finance system, because the errors do not stay in the system — they leave it, inside numbers people have already acted on.

Why a quarter, and what a quarter costs

Three months was not a target somebody handed me and it was not ambition. It came out of the reading: the dead list was long enough that the surviving customisation set was small, the entities were similar enough in structure that one migration script family covered them with per-entity mappings, and the group had a natural quiet period I could put the cutover inside.

What a quarter costs is optionality. A compressed schedule means every decision has to be made when it arrives rather than deferred to a workshop next month, and that only works if the person who can decide is available on a day's notice. I asked for that access explicitly before committing to the date, because a three-month plan with a two-week approval cycle inside it is a six-month plan that has not admitted it yet.

It also costs scope discipline in a specific direction. An inherited upgrade is the single most tempting moment to add the things everyone has been asking for, because the system is already open and the team is already there. It is also the worst moment, because a new feature and a migrated feature fail identically at go-live and you cannot tell them apart while you are triaging. Improvements go on a list dated the month after go-live, and that list is how you buy the discipline rather than just asking for it.

The honest trade is this: a quarter is achievable on an inherited estate if you are allowed to delete, if decisions arrive in days, and if nothing new is added. Take away any one of those three and the date is a wish. I would rather say that in the first meeting than discover it in the tenth.

What I would tell you before you accept it

Ask who built it and whether anyone from that team is reachable. One conversation with the person who wrote a customisation is worth a fortnight of reading it, and the request is usually easier to make than people assume. I have had those calls go well more often than not, because engineers generally want their work understood rather than cursed.

Ask what the last three month-ends looked like. A finance team that closes on time is telling you the data is in better shape than the code, and a finance team that closes late with manual adjustments is telling you where the migration will actually hurt. That answer changes my plan more than any technical finding.

Ask who can approve a deletion. If the answer is nobody, or a committee that meets monthly, the schedule has to absorb that and you should price it before you commit rather than discover it in week five. This is the question people forget to ask and it is the one that most reliably decides whether a date is real.

And write down, on the first day, what you will not do. An inherited system is an invitation to fix everything you can see, and the invitation is sincere, and accepting it is how a three-month upgrade becomes an eighteen-month transformation nobody chartered. The discipline is not in resisting the good ideas. It is in dating them.

Practical checklist

  • Spend the first two weeks reading the implementation before scheduling anything.
  • Write the findings as statements a business owner can agree or disagree with, not a technical inventory.
  • Split everything into configuration (schedule) and customisation (risk), before estimating.
  • Give every surviving customisation a named business owner who can state its purpose.
  • Test each customisation against execution in ninety days, data newer than a year, and a downstream reader.
  • Put the dead list in front of the business as a decision with a stated consequence.
  • Plan the project around the data migration, not around the software version.
  • Migrate in rehearsals, each ending with the same fixed reconciliations per entity.
  • Require the final rehearsal to be boring; if it is not, run another rather than going live.
  • Secure day's-notice access to the person who can decide, before committing to a date.
  • Date every improvement request to the month after go-live.
  • Ask who can approve a deletion before you accept the schedule.

Common mistakes

  • Treating an inherited estate as if you built it, and following an upgrade guide written for that case.
  • Carrying every customisation across because nobody can say which are still needed.
  • Estimating before separating configuration from customisation, then being asked why more developers did not help.
  • Planning around the software version and discovering the data in the final fortnight.
  • Migrating several entities as one dataset when their keys and postings disagree.
  • Going live on a rehearsal that was not boring, and fixing forward inside a finance system.
  • Adding the long-requested improvements during the upgrade, then triaging new and migrated failures together.

How Hamad approaches this

I have taken an inherited Odoo estate from 15 to 18 in three months across seven operating entities, carrying database faults and code defects left by previous teams and a full data migration underneath, and the schedule held because of what I removed rather than what I moved. The reading came first, the deletions were signed by the business, and the improvements were dated for after go-live.

I run an independent practice around Odoo and applied automation, and it has made me more conservative rather than less. The systems that age well are the ones where somebody could still explain, three years later, why each override exists — so I would rather ship fewer of them and write down the reason.

I do not promise that an inherited upgrade will be quick. I promise that within a fortnight you will know what you are carrying, what it is costing you, and which parts of it nobody has needed since the person who wrote them left.

Continue the conversation

The executive profile, the operating philosophy, and direct channels for advisory or transformation discussions.

Back to Insights

ERP & Automation4 min read

Odoo 18 Implementation Is Not an ERP Project

Why ERP programs collapse without ownership, rights discipline, workflow truth, and change management — and how to run Odoo 18 as an operating program, not a software install.

Read
Technology Leadership12 min read

One Line Called IT: Can It Be Smaller?

Splitting run from change, pricing the run per service, catching renewals before the notice window closes, and arriving at the cut meeting with options instead of adjectives.

Read