Skip to content
Konis Software
Architecture·10 min read

Modernising a legacy system without stopping the business

A full rewrite fails because the old system keeps moving while you build the new one. Modernisation that works proceeds in small, reversible steps — one slice, behind a façade, while the business keeps running.

In short

  • A full rewrite fails because the old system keeps changing while you build the new one, so the target is always moving.
  • The strangler-fig pattern moves one capability at a time behind a façade and deletes the old path only when no traffic flows through it.
  • The first slice to migrate is chosen for a high change rate, low coupling and a clear boundary.
  • An anti-corruption layer keeps the new model free of the old schema's sins, and data moves by dual-write, backfill and reconciliation.
  • Progress is measured by the share of traffic moved, not by lines of code written, and the migration nobody can see is the first to be cancelled.

Almost every company that has been trading for more than ten years runs at least one system everyone calls "the old one". It works, but nobody dares touch it. The documentation lives in the heads of two people, one of whom has left. Every change takes weeks because nobody knows what else will break. At some point someone proposes to simply rewrite it from scratch, properly this time. That is usually where the most expensive mistake begins.

Modernising a legacy system is doable, but almost never as a single replacement. It is doable as a sequence of small, reversible steps that do not stop the business for a single day. This piece is about what that path looks like and why the other, more tempting one, almost always ends badly.

Why the "big bang" keeps failing

A full rewrite — the big bang, where you build a new system for two years and then cut everything over one weekend — fails for a reason that is mathematical, not organisational. While you write the new system, the old one does not stand still. It keeps taking urgent changes: a new tax, a new payment method, a demand from a large customer. Each of those changes is a new target the new system has to hit, and it is shooting while the target moves.

The result is that the new system never "catches up" with the old one. The day before the planned cutover, the old system can do something the new one cannot, because it was added last month. The cutover slips, then slips again. After two years you have two systems to maintain, a burned-out team, and a board that no longer believes the word "migration".

On top of that, a big bang concentrates all the risk on one date. If something goes wrong during that weekend, there is no partial rollback — either everything works or nothing does. Serious cutovers avoid that date by not having one at all.

The strangler fig instead of the big bang

The strangler-fig pattern is named after the plant that grows over a host tree, gradually takes over its role, and only once it can stand on its own does the host rot away. In software it means three moves repeated until nothing of the old system is left.

First, you put a façade in front of the old system — a thin layer that all traffic passes through. At the start the façade simply forwards everything to the old system and changes nothing; users notice nothing. It is the point where you will later reroute individual flows.

Second, one capability at a time moves to the new code. For that single operation the façade starts calling the new system instead of the old one, while everything else still goes to the old. You do not move a module for elegance; you move it because it has a clear boundary at the façade.

Third, the old path is deleted only when zero traffic flows through it. Not when the new one is "done", but when measurement confirms nobody uses the old one any more. As long as a single nightly report calls the old procedure, it stays — and that is fine, because it is isolated behind the façade and threatens no one.

This permanently changes the question from "when do we cut over" to "how much have we already moved". There is no D-day, there is a percentage of traffic on the new system, and that percentage rises week by week instead of sitting at zero for two years.

How to choose the first slice

The choice of the first slice decides whether the whole effort has any credibility. The wrong first slice is either too large to finish in a reasonable time, or so entangled with the rest that it cannot be extracted. A good first candidate has three properties:

  • High change rate. A part that changes every month anyway. New code pays for itself immediately there, because the next change is made on something clean instead of on something frightening.
  • Low coupling. A part that does not depend on half the system. The fewer threads that lead to it, the clearer the boundary and the safer the move.
  • A clear boundary. An operation that shows up at the façade as a handful of calls, not a hundred interwoven ones. If you cannot draw the boundary, you do not have one yet — and that is work to do before the move, not during it.

A product catalogue, for example, is often a good first candidate: it changes constantly and is relatively separate from billing and accounting. That is why moving to a modern commerce platform such as NG Commerce usually starts with the catalogue and the storefront, while billing stays on the old system for a while longer.

The anti-corruption layer and data migration

The biggest danger in a migration is not the code but the new system inheriting the sins of the old schema. If the new data model copies every odd column and every "temporary" field from the old one, you have built the same system with a newer date on it. That is why you place an anti-corruption layer between old and new — a translator that turns old concepts into the clean concepts of the new model, and back. The old system speaks its language, the new one speaks its own, and the layer between them will not let the concepts mix.

Data moves in three moves that run together:

StepWhat it doesWhy
Dual-writeEvery new change is written to both the old and the new systemThe new model stays current from the moment it is switched on
BackfillHistorical data is moved in the background, in batchesThe new system gets the past without any downtime
ReconciliationOld and new are regularly compared for agreementA mismatch surfaces immediately, not on cutover day

Dual-write keeps both systems in step for the duration of the migration. Backfill moves the history without interrupting operations. Reconciliation is the control most often skipped and the one worth the most: if the record count or the sum of amounts is not the same in both systems, you have to learn it the same day, while the cause is small, rather than three months later when the gap has grown and nobody can tell where it came from.

Feature flags, reversible releases and visible progress

Each capability that moves ships behind a feature flag — a switch that reroutes traffic from the old path to the new without a new code release. That makes the release reversible: if the new path shows a problem, you flip the flag back and traffic returns to the old one instantly, with no panic and no late-night rollback.

For a migration to survive, it has to be visible and interwoven with business value. A few rules ensure that:

  1. Measure traffic moved, not code written. The report to the board is not "we moved 40,000 lines" but "35% of orders go through the new system". Lines of code mean nothing to the person paying for it.
  2. Every step carries a visible benefit. Moving the catalogue brings faster search; moving accounts brings better sign-in. The benefit a user feels is what keeps the project alive.
  3. Release small and often. Ten small, reversible steps carry far less risk than one large one, and each gives you a chance to stop if something is wrong.
  4. Keep the team shipping. If the whole team disappears into a "big migration" for a year, business value stops, and what stops gets cancelled. The migration has to run alongside delivering the thing the company exists for.

The migration nobody can see is the one that gets cancelled. If after three months the only evidence of progress lives in the engineers' heads, the first revenue dip or shift in priorities sweeps the whole effort away. Tie every step to a number the board understands — the share of traffic moved — and to a benefit the user feels.

We use the same pattern when a company moves its customer records into KickOff CRM or switches to document handling through DocDot: the old system stays the source of truth until traffic is gradually moved across, and the anti-corruption layer keeps the new model free of the old habits.

When not to modernise

Not every old system deserves a migration. If the system works, is cheap to maintain and nobody asks it to change, modernisation is a cost with no return. Old is not the same as bad. A system that has quietly done its job for years and changes once every two years should not be touched just because it is written in an unfashionable technology.

The decision to modernise is driven by pain, not aesthetics: changes take too long, the risk of every change is too high, the system cannot connect to new channels, or it is maintained by a single person whose departure would break the business. If none of that is true, the money is better spent where it actually hurts. And if it is — start with one slice, behind a façade, with a flag that can bring you back. If you are not sure where the first slice's boundary is, that is the first conversation worth having with a team that has already moved systems like this, before a single line is written.

Let's talk about your case

Describe the process that costs you the most. In a short call we tell you whether automating it pays off, and what that would concretely involve.

Frequently asked questions

Why does a full rewrite of an old system fail so often?

Because the old system keeps changing while you build the new one, so the new one is always shooting at a moving target and never catches up. A big bang also concentrates all the risk on one cutover date, with no way to roll back partially. After two years you usually have two systems to maintain and an exhausted team.

What is the strangler-fig pattern?

It is an approach where you put a façade in front of the old system, then move one capability at a time to new code while the old path stays untouched. The old part is deleted only when zero traffic flows through it. This shifts the question from "when do we cut over" to "how much have we already moved".

How do we choose which part of the system to modernise first?

Choose a part with a high change rate, low coupling and a clear boundary. A part that changes every month anyway justifies the investment immediately, and a clear boundary at the façade allows a safe move. If you cannot draw the boundary, define it first — that is work to do before the move, not during it.

What is an anti-corruption layer for?

It prevents the new system from inheriting the sins of the old schema. It is a translator that turns old concepts into the clean concepts of the new model and back, so old and new can run at the same time without mixing concepts. Without it you get the same old system with a newer date on it.

When is it not worth modernising an old system?

When the system runs stably, is cheap to maintain and nobody asks it to change. Old is not the same as bad. Modernisation is driven by pain — slow changes, high risk, an inability to connect to new channels — not by the technology being unfashionable.

Keep reading