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:

  1. Incremental debt reduction — delete, standardise, convert modifications, over 2–3 years, then upgrade
  2. Greenfield re-implementation — expensive, but you stop carrying the debt
  3. Extended support at a premium — buys time, solves nothing
  4. Run unsupported — no security patches, no legal compliance updates, no vendor help. A board-level risk, not an IT decision

Practical rules

  1. Every customisation needs a business justification, an owner, and a review date.
  2. Log usage of every custom object — you cannot delete what you can’t prove is unused.
  3. Never modify core unless there is genuinely no alternative, and register it.
  4. Use released APIs only. Internal APIs break silently.
  5. Maintain an automated regression suite — it’s what makes upgrades routine instead of terrifying.
  6. Upgrade regularly. Small, frequent upgrades are far cheaper than rare, large ones.
  7. Budget for adoption, not just conversion.
  8. Read the release notes every cycle. Assign it to a named person.
  9. Track “versions behind” as a governance metric, reported upward.

Next