Upgrades, Migrations, and Technical Debt
Every ERP eventually has to move: a new version, a new platform, or a new product. How painful that is was decided years earlier, by how much you customised.
Types of change
| Type | Scope | Effort |
|---|---|---|
| Patch / hotfix | Bug fixes | Days |
| Support pack / cumulative update | Accumulated fixes | 1–4 weeks |
| Minor release | New features, same architecture | 1–3 months |
| Major version upgrade | e.g. Odoo 17 → 18, BC v22 → v25 | 2–6 months |
| Platform migration | e.g. ECC → S/4HANA, on-prem → cloud | 12–36 months |
| Product replacement | A different ERP entirely | 18–48 months |
The customisation tax
The single variable that determines upgrade cost:
Customisations Upgrade effort Typical outcome
─────────────────────────────────────────────────────
0–20 2–6 weeks Routine, near-annual
20–100 2–4 months Manageable project
100–500 6–12 months Significant programme
500–2,000 12–24 months Painful; often deferred
2,000+ "We can't upgrade" Stuck on an unsupported version
Every customisation is a permanent liability. It must be re-tested at every upgrade, may break when the surrounding code changes, and may become obsolete when the standard catches up.
This is the entire economic argument behind the clean core doctrine, and it’s why “just build it” is a more expensive answer than it looks. See Extensibility and Customization.
The upgrade project
1. ASSESS
- Read the release notes and deprecation list in full
- Run the vendor's readiness/impact analysis tool
- Inventory custom objects and rank by risk
- Inventory interfaces and third-party add-ons
- Check add-on vendor compatibility ← often the blocker
- Estimate
2. PREPARE
- Set up a sandbox on the target version with a production data copy
- Fix obvious deprecations first
- Delete unused custom code ← the cheapest effort reduction available
- Update the automated regression suite
3. EXECUTE (technical upgrade)
- Upgrade the sandbox; resolve conflicts and errors
- Adjust custom code
- Data model conversions
- Repeat until the sandbox is clean
4. TEST
- Full regression across all core processes
- Interface testing with real partners
- Performance testing at volume
- UAT on key processes
- A full period-close simulation
5. DEPLOY
- Rehearse the upgrade cutover, timed
- Production upgrade in a maintenance window
- Hypercare
6. ADOPT (the part that gets cut)
- Enable the new features you upgraded for
- Retire custom code the standard now covers
- Train users
Step 6 is where the value is, and it’s the first thing dropped when the schedule slips. A “technical upgrade” that delivers no new capability is pure cost. Protect the adoption budget explicitly.
Technical vs functional upgrade
| Technical (brownfield) | Functional (greenfield) | |
|---|---|---|
| Approach | Convert the existing system in place | New implementation, migrate data |
| Custom code | Carried forward and adapted | Re-evaluated; most dropped |
| Process change | None | Opportunity to adopt standard |
| Risk | Lower | Higher |
| Duration | Shorter | Longer |
| Value | Stays on a supported version | Genuine transformation |
| Cost | Lower now | Lower over ten years |
Selective data transition (bluefield) is the hybrid: a new system, but migrating selected configuration and data from the old. It’s become the most common choice for large SAP ECC→S/4HANA moves precisely because it splits the difference.
The decision: if your current system genuinely works and the customisations earn their keep, go brownfield. If your system is a twenty-year accumulation of workarounds nobody understands, greenfield is the chance to stop carrying it — and that chance comes once a decade.
The S/4HANA migration wave
The largest coordinated ERP migration in history, and a career opportunity:
2027 SAP ECC mainstream maintenance ends
2030 Extended maintenance ends
Thousands of ECC customers must move. There are not enough people to do it. If you’re choosing a specialisation now, this is a demand signal that runs for years.
What’s different in S/4HANA: the Universal Journal (ACDOCA) replacing dozens of tables, the Business Partner model replacing separate customer/vendor masters, simplified material and inventory tables, mandatory data model conversions, and Fiori replacing SAP GUI.
Managing technical debt
Measuring it
Debt indicators:
- Count of custom objects, trending
- Count of core modifications ← weight these 10×
- Custom objects with no recorded execution in 12 months
- Custom objects with no named owner
- Custom objects with no documentation
- Interfaces using unreleased/internal APIs
- Objects failing static analysis
- Versions behind current
- Time since last upgrade
- Manual workarounds documented in support runbooks
Publish this as a dashboard. Technical debt that isn’t visible never gets funded.
Reducing it
| Action | Effort | Impact |
|---|---|---|
| Delete unused custom code | Low | High — directly reduces upgrade scope |
| Replace custom with standard where the product caught up | Medium | High |
| Convert modifications to sanctioned extensions | Medium | Very high |
| Move logic side-by-side | High | High |
| Document what remains | Low | Medium |
| Add automated tests to what remains | Medium | High |
Start with deletion. Usage logging typically reveals that 20–40% of custom objects have never been executed. Deleting them costs almost nothing and reduces every future upgrade.
To do it safely: log every execution of every custom object for 12 months (to cover annual processes), then review anything with zero executions with its business owner, deprecate with notice, and delete.
The annual review
For every custom object:
□ Was it executed in the last 12 months?
□ Does it still have a business owner?
□ Does standard functionality now cover it?
□ Is it documented?
□ Does it have tests?
□ Is it a modification that could become an extension?
Outcome: keep / improve / replace with standard / delete
Add-ons and third parties
Often the real upgrade blocker:
Your ERP upgrade requires:
- Add-on A: compatible ✅
- Add-on B: compatible with the next version, not this one ⚠️
- Add-on C: vendor no longer trading ❌ ← project stopped
Rules: check add-on compatibility in the assessment phase, before committing to a date; include add-on vendors in your upgrade plan; and avoid add-ons from vendors whose survival you’d bet against. An abandoned add-on with no source code access can strand you on a version indefinitely.
Cloud migration
Moving on-prem → cloud has its own considerations:
| Aspect | Change |
|---|---|
| Customisation | Public SaaS restricts it severely. Some modifications simply cannot come |
| Integration | Network topology changes; firewalls, VPNs, private endpoints |
| Performance | Latency to on-premise systems (warehouse, MES) becomes a real factor |
| Data residency | Now a contractual and regulatory question |
| Upgrade control | You lose it |
| Cost model | CapEx → OpEx |
| Operations | You lose direct DB access — and every tool that relied on it |
The loss of direct database access surprises people most. Custom reports built on SQL views, third-party tools reading tables directly, and ad-hoc queries all stop working. Inventory these before committing.
The “we can’t upgrade” trap
How organisations end up stranded:
Year 1 Heavy customisation to match legacy processes exactly
Year 3 First upgrade estimated at 9 months → deferred
Year 5 Now two versions behind; upgrade estimated at 18 months → deferred
Year 7 Vendor support ending; nobody understands the customisations;
the original team has left
Year 8 Forced decision: a 3-year re-implementation, or run unsupported
Escape routes, in order of preference:
- Incremental debt reduction — delete, standardise, convert modifications, over 2–3 years, then upgrade
- Greenfield re-implementation — expensive, but you stop carrying the debt
- Extended support at a premium — buys time, solves nothing
- Run unsupported — no security patches, no legal compliance updates, no vendor help. A board-level risk, not an IT decision
Practical rules
- Every customisation needs a business justification, an owner, and a review date.
- Log usage of every custom object — you cannot delete what you can’t prove is unused.
- Never modify core unless there is genuinely no alternative, and register it.
- Use released APIs only. Internal APIs break silently.
- Maintain an automated regression suite — it’s what makes upgrades routine instead of terrifying.
- Upgrade regularly. Small, frequent upgrades are far cheaper than rare, large ones.
- Budget for adoption, not just conversion.
- Read the release notes every cycle. Assign it to a named person.
- Track “versions behind” as a governance metric, reported upward.