New: CentriCall AI voice agents that answer, qualify, and book around the clock
Modernization4 min read

Modernising a legacy system without a big-bang cutover

Full rewrites fail at a well-documented rate. The alternative is slower to describe and considerably faster to finish.

The short version
  • A rewrite competes against a moving target: the old system keeps gaining features while you rebuild it.
  • Strangler fig routes traffic seam by seam, so value ships in month two rather than month eighteen.
  • Not every application deserves a rebuild. Rank the estate by risk and value first.
  • The database is usually the hard part, not the application.

The proposal is always the same. The system is fifteen years old, nobody understands it, the original developers are gone. So: rewrite it, modern stack, eighteen months, then switch over one weekend.

It fails often enough that the pattern has a name and a literature. Not because the engineers are weak, but because of a structural problem in the plan. A 900-person distributor we worked with had already funded and cancelled one such rewrite before we arrived, which is a common enough starting position to plan around.

Why full rewrites fail

1

You are chasing a moving target

The old system does not freeze while you rebuild. The business keeps requesting changes, and they land in the legacy system because that is what is live. At eighteen months you are rebuilding something that has moved.

2

The requirements are in the code, undocumented

Fifteen years of edge cases, regulatory patches, and one-off fixes for a customer who complained in 2016. No specification captures them. You find them when the rewrite goes live and something quietly stops working.

3

Nothing ships for eighteen months

No value, no feedback, no proof. Sponsors change, budgets get reviewed, and a project with nothing to show is the easiest thing on the list to cancel.

4

The cutover concentrates all risk into one night

Every assumption made over eighteen months gets tested simultaneously, under time pressure, with rollback meaning eighteen months of nothing.

The alternative: strangle it

Named after the strangler fig, which grows around a host tree and gradually replaces it. Instead of rebuilding the system, you put a routing layer in front of it and move one capability at a time.

1

Put a facade in front

An API gateway or reverse proxy through which all traffic passes. On day one it forwards everything to the legacy system and changes nothing, which is the point. It is the seam you will use later, and it is what turns every subsequent move from a cutover into a toggle. Build it before you move anything.

2

Pick the first capability by pain, not by ease

Something self-contained with real business value: the piece that breaks most often or blocks the most requests. Build it new behind the facade.

3

Route a slice of traffic to it

Internal users first, then a percentage, then all of it. Both implementations run side by side and can be compared on live traffic. Rollback is a routing change, not a restore.

4

Repeat, and let the old system shrink

Each capability moves when its turn comes. The legacy system loses responsibility gradually until what remains is small enough to retire without ceremony.

The first release lands in month two instead of month eighteen. That is the difference between a project the business can see working and one it has to take on faith.

The database is the hard part

Routing requests is straightforward. Two systems reading and writing the same data is not, and it is where these programmes actually get difficult. It is database work before it is application work, and it is the usual reason the schema moves last rather than first.

  • Shared database, both systems write. Fastest to start, and you inherit the old schema plus a coupling that makes both harder to change. Acceptable as a bridge; dangerous as a destination.
  • New system owns its tables, syncs back. Cleaner boundary, but you now run a sync with conflict rules and reconciliation, which is its own product.
  • Legacy stays the system of record, new system reads through an API. Safest for a first slice, and it defers the data question rather than answering it.

Not everything deserves a rebuild

Before any of this, rank the estate. Most applications in a legacy portfolio should not be rebuilt at all.

SituationAction
Works, rarely changes, low riskLeave it. Modernisation is not a virtue.
Works, but the platform is end-of-lifeRehost. Move it to AWS or Azure, change nothing else.
Sound logic, unmaintainable structureRefactor in place. Cheaper than it looks.
Blocks the business, changes constantlyRebuild. This is where the budget belongs.
Commodity process, no differentiationReplace with a product. Do not rebuild it — see build versus buy.

A two-to-four week assessment producing that ranking is the highest-return work in any modernisation programme. It routinely removes half the proposed scope — on one estate of nine candidate seams, two came out marked for deletion rather than migration, which was the cheapest modernization in the programme. We run it as part of a cloud and DevOps engagement, because the landing zone and the ranking inform each other.

What good looks like from the outside

Signals the programme is healthy
  • Something went live in the first two months
  • Rollback for any slice is a configuration change, measured in minutes
  • Both implementations ran in parallel before the old one was switched off
  • Ownership of every data entity at the end state is written down
  • The legacy system is smaller than it was last quarter

The last one is the honest measure. If the old system has not shrunk, you are not modernising it. You are building a second system beside it, which is how estates get worse rather than better.

Working through this on a real project?

Tell us what you are building. You will get a scoped estimate and an architecture you own, not a capability deck.

Common questions

Four structural reasons: the legacy system keeps gaining features while you rebuild, so you are chasing a moving target; fifteen years of undocumented edge cases live only in the code and surface after go-live; nothing ships for eighteen months, so the project is easy to cancel and produces no feedback; and a single cutover concentrates every accumulated assumption into one high-pressure night.
You place a routing facade in front of the legacy system, then replace one capability at a time behind it. Traffic for each capability moves gradually: internal users, then a percentage, then all, with both implementations running in parallel and rollback reduced to a routing change. The legacy system shrinks until it is small enough to retire quietly.
Rank the estate first. Leave systems that work and rarely change. Rehost when only the platform is end-of-life. Refactor in place when the logic is sound but the structure is not. Rebuild only where the system actively blocks the business and changes constantly. Replace with an off-the-shelf product where the process is commodity. A two-to-four week assessment producing this ranking routinely removes half the proposed scope.
The data, not the routing. Once two systems read and write the same information you must decide who owns the truth: shared database, new system syncing back, or legacy as system of record behind an API. Each is acceptable as a temporary bridge and dangerous as a permanent state. Decide the end-state ownership of every data entity before the first slice moves.