Every legacy system invites the same fantasy: tear it down and rebuild it clean. It's almost always a mistake. Big-bang rewrites are where budgets die, and the new system usually reinvents bugs the old one had already solved, years later and at several times the cost. The instinct is understandable: the old code is ugly, no one fully understands it, and a green field feels liberating. But the ugliness is often load-bearing.
Why rewrites fail
- The old system encodes years of undocumented edge cases (the weird tax rule, the customer-specific discount, the workaround for a partner's broken API) that a rewrite quietly drops, then rediscovers as production incidents.
- You ship nothing new for months, sometimes years, while the rewrite catches up to where you already were. The business doesn't stop needing features in the meantime.
- Two systems in parallel doubles maintenance, not halves it. Every bug fix and every new requirement now has to land in two places.
Rewrite versus strangle, on the dimensions that decide it
| Big-bang rewrite | Incremental (strangler) | |
|---|---|---|
| Time to first delivered value | Launch day, months or years out | The first slice, usually weeks |
| If you are wrong about a decision | Discovered late, expensive to unwind | Discovered in one slice, cheap to change |
| Rollback | All or nothing | Route traffic back, per slice |
| Business continuity during the work | At risk from the cutover | Never interrupted |
| Feature delivery meanwhile | Frozen | Continues |
| Systems to maintain | Two, until the day it lands | Two, but shrinking every slice |
| What happens if funding stops halfway | Two half-systems, nothing shipped | A working system, partly modernised |
That last row is the honest argument. Rewrites are not usually killed by a technical failure; they are killed by a budget cycle, a reorganisation or a change of sponsor, and the incremental path is the only one of the two that survives being interrupted.
Why this matters
Modernisation is rarely a technical problem in isolation; it's a business-continuity problem. The legacy system is, right now, making money and serving customers. A rewrite asks the business to bet that fragile, low-visibility process against a multi-month project that delivers no value until the very end. That's a bad trade, and it's why so many rewrites are quietly abandoned halfway through, leaving the organisation maintaining two half-finished systems instead of one working one.
The incremental path
- 1.Strangle, don't replace. Put a façade in front of the legacy system; route functionality to new services one slice at a time, until the old core has nothing left to do.
- 2.Start at the seams. Modernise what changes or hurts most first, so the early work pays for itself.
- 3.Keep the data where it is, at first. Decoupling the data store is its own project; don't take it on at the same time as everything else.
- 4.Ship continuously. Every slice delivers value and de-risks the next, and at every point you have a working system you could stop on.
Choosing the first slice
The first slice sets whether anyone lets you do a second one, so pick it on evidence rather than on which code annoys the team most. Four criteria, and a good candidate meets at least three:
- It changes often. Modernising code nobody touches buys you nothing; modernising the file with the most commits pays back immediately.
- It has a clean boundary. Something you can put behind a façade without unpicking the data model on day one.
- It hurts visibly. A slow checkout or a nightly job that keeps failing gives you a before-and-after number a non-technical sponsor can see.
- It is reversible in one step. If routing traffic back is not a config change, it is the wrong first slice.
What to avoid first, however tempting: the data layer, anything with a regulatory audit trail, and the piece one person understands and is on holiday. Those come later, when the team has learned the system's real behaviour on something safer.
Where the incremental path goes wrong
Being honest about the failure modes of the approach I am recommending, because it has three:
The façade becomes permanent. Routing layers are easy to add and nobody is ever assigned to remove one, so a decade later there are three of them stacked up. Give each façade a written retirement condition when you create it.
The strangling stops halfway. The easy slices go first, the hard core stays, and the organisation quietly settles into maintaining both forever. This is the most common outcome in practice, and the guard is a named owner for the last slice rather than the first.
Nobody locks in existing behaviour. Legacy code encodes undocumented rules, so if you rebuild a slice without characterisation tests over the old path first, you will ship the same edge-case bugs the old system had already solved. Write the tests against the legacy system while it is still running.
A good modernisation is invisible to users and reversible at every step. A rewrite is a held breath until launch day.
A concrete example
A retailer with a 15-year-old monolith wants to modernise checkout. Instead of rebuilding the platform, they put a routing layer in front of it and rebuild only the payment flow as a new service. Traffic shifts gradually, the old path stays as an instant fallback, and the team learns the real-world quirks before touching anything else. Six weeks in, customers have a faster checkout and the business has taken on near-zero risk, the opposite of a two-year rewrite that ships nothing until it's done.
What this means for your team
Frame modernisation as a sequence of small, shippable, reversible bets, each justified on its own merits, the same build, buy, or AI thinking applied to an existing system instead of a greenfield one. Modern AI tooling genuinely accelerates the grind (understanding old code, mapping dependencies, drafting tests to lock in existing behaviour before you change it) but it accelerates a disciplined process; it doesn't replace one. If you're staring down a system everyone's afraid to touch, and wondering whether that's one of the signs you've outgrown your dev agency or just a question of choosing a software development partner who's done this before, we've done this before and can help you map the seams.