The short version

The big rewrite fails for reasons that have nothing to do with how good your engineers are: the business keeps shipping features into the old system while you rebuild, feature parity is measured against behaviour nobody documented, and nothing of value lands until the very end. The alternative is to put a facade in front of the old system and move capabilities across one at a time. The hard part is not the technology — it is the business rules in the old code that nobody wrote down.

Every legacy system eventually produces the same meeting. The code is hard to change, onboarding takes months, and someone proposes starting again properly. The proposal is almost always sincere, usually technically reasonable, and more often than not a mistake — for reasons that have very little to do with engineering.

Why rewrites fail, and it is not the code

Three failure modes, none of which are solved by a better team:

The business does not pause. You are rebuilding a system that is still gaining features, because competitors exist and regulators publish deadlines. Every feature shipped into the old system during the rebuild is one you must also build into the new one. The target moves at roughly the speed you are chasing it.

Feature parity is measured against something undocumented. "Does the same thing as the old one" sounds like a specification until you try to write it down. Fifteen years of edge cases, regulatory patches and deliberate exceptions live in that code, and some of them are bugs your customers have built their own processes around. You will find them one at a time, in production.

Nothing lands until the end. A rewrite delivers zero value for most of its life, then all of it at once. That makes it fragile to the first budget review, the first change of sponsor, the first quarter where something more urgent appears. Many rewrites are not cancelled because they failed — they are cancelled because they had not yet succeeded.

What to do instead

Put something you control in front of the old system, then move work behind it a piece at a time. The pattern is usually called the strangler fig, after the plant that grows around a tree until it can stand without it.

PHASE 1 put the facade in. nothing else changes. PHASE 2 move one capability. both run. PHASE 3 the remainder is small enough to retire. traffic FACADE LEGACY untouched traffic FACADE NEW SERVICE LEGACY shared database traffic FACADE NEW SERVICES remainder
The facade goes in first and changes nothing — which is why it is safe to ship. After that, every move is one route at a time, and every route can be switched back.

The facade can be an API gateway, a reverse proxy, a routing layer in the application, or in the simplest cases a few rules in a web server config. What matters is not the technology but that you now own the decision about where a request goes, and that you can reverse it in seconds.

Four choices, made per component

"Modernise the system" is not a decision anyone can act on. "Decide what to do with the payments module" is. For each component, there are only four honest options:

  • Leave it alone. The most underused option. If a module is stable, rarely changes and nobody is blocked by it, the correct engineering decision is usually to do nothing. Old is not the same as bad.
  • Wrap it. Put an API in front of the existing logic without changing it. Everything new talks to the interface; the old implementation keeps running. Cheap, fast, and buys you optionality.
  • Extract it. Move the behaviour into a new service, route traffic across, retire the old path. The real work, done one component at a time.
  • Replace it. Drop it for something off the shelf. Frequently right for authentication, payments, search and reporting, where you were never going to build better than a specialist.

Most of a legacy estate should end up in the first two categories. A programme that puts everything in "extract" has quietly reinvented the rewrite with extra steps.

Where to start, and where not to

The instinct is to start with the worst part — the module everyone dreads. That is usually the wrong choice, because the worst part is worst precisely because it is the most entangled, and it is a poor place to learn a process you have not run before.

Start where change is frequent and the blast radius is small. Frequent change means the improvement compounds immediately. Small blast radius means your first attempt can go wrong without becoming an incident. You are buying a rehearsal.

The worst module comes third or fourth, once the facade is proven, the deployment path is established, and the team has done this before.

The database is the hard part

New and old code can share a schema for a long time, and early on they should — it keeps each step small and avoids a data migration landing in the middle of a behavioural change.

Eventually the shared database becomes the coupling. Two systems writing the same tables constrain each other's schemas, and splitting them is usually the hardest single piece of work in the programme. The mistake is not sharing the database early; it is reaching that point without having planned for it. Decide up front which data will eventually be owned by which side, even if you do nothing about it for a year.

What actually blocks this

Not the technology. The obstacle is the business rules encoded in the old system that nobody documented, and the people who wrote them have moved on.

This is also the strongest argument for the incremental route: the old code remains the specification while you replace it. You can run both paths against the same input and compare outputs. You can route a small percentage of real traffic to the new implementation and watch for divergence. A rewrite gives you none of that — it asks you to rediscover fifteen years of behaviour from scratch and find out whether you succeeded at cutover.

When a rewrite genuinely is right

It would be dishonest to claim never. A rewrite is the right call when the platform is at a true dead end — a runtime no longer receiving security patches, hardware you cannot buy, a vendor who has left the market. When the system is small enough that a rewrite is weeks rather than years. Or when the business has changed so much that preserving the old behaviour is not the objective.

Those cases are real. They are simply much rarer than the instinct, and the instinct arrives most strongly in the week after a painful production incident — which is the worst week to make an architectural decision.

Questions we get asked

Why do big-bang rewrites usually fail?

Rarely for engineering reasons. The business does not pause while you rebuild, so the old system keeps gaining features and the target keeps moving. Feature parity is measured against behaviour nobody documented, including bugs people now depend on. And nothing of value lands until the end, so the first budget review with nothing shipped is often the last.

What is the strangler pattern?

You put a facade in front of the legacy system so all traffic flows through something you control, then move one capability at a time behind it, switching routes individually. The legacy system shrinks until what remains can be retired or left alone. Each step is independently valuable and independently reversible.

How do we decide what to modernise first?

Not by what is most painful. Pick where change is frequent and the blast radius is small — frequent change means the improvement compounds, small blast radius means a mistake is survivable. The most painful component is usually the most entangled, which makes it the worst place to learn the process.

What actually blocks a legacy modernisation?

Almost never the technology. It is the business rules encoded in the old system that nobody documented and whose authors have left. A rewrite must rediscover every one, usually by breaking something in production. Incremental approaches work partly because the old code stays the specification while you replace it.

When is a full rewrite actually right?

When the platform is at a true dead end — a runtime without security patches, hardware you cannot buy, a vendor who has exited. When the system is small enough that a rewrite is weeks rather than years. Or when the business has changed so much that preserving old behaviour is not the goal. Real cases, just rarer than the instinct suggests.

Can you modernise without touching the database?

For a while, yes, and it is often the right sequencing — new and old can share a schema while you move behaviour. Eventually that shared database becomes the coupling, and splitting it is usually the hardest part of the programme. Plan for it from the start rather than meeting it by surprise.

Related service Digital transformation Legacy modernisation without the rip-and-replace

If you are weighing a rewrite against an incremental path, the useful first exercise is mapping the components onto those four options — leave, wrap, extract, replace. It usually takes a couple of days and frequently shrinks the programme, which is how we start modernisation engagements.