Skip to content
Brain Matrix

Technology Strategy

Modernising legacy software without a rewrite

Big-bang rewrites ask a business to stand still for a year and carry all the risk until the end. Here is the incremental alternative, how to choose the first slice, and how to justify it to a board that does not care about technical debt.

Written by

Nadeem Sheikh

Software Architect & AI Automation Engineer

Published
Reading time
5 minutes
Written for
software modernization services / legacy system migration — a CTO or owner deciding what to do about a system that has become risky to change

Legacy is not a technology. Plenty of well-maintained systems run on old stacks, and plenty of two-year-old codebases are already legacy.

Legacy is a system that has become risky to change. That is the whole definition, and it is why the symptoms are organisational rather than technical: releases become rare, estimates become defensive, integration requests get refused, and eventually the technology is setting company strategy by determining what is considered possible.

The instinct is to propose a rewrite. The instinct is usually wrong, and it is worth being precise about why.

Why big-bang rewrites fail

They ask the business to stand still. For twelve to eighteen months, no new capability, while competitors keep shipping. Few businesses can actually afford this, so the rewrite gets squeezed, and a squeezed rewrite is the worst of both worlds.

All the risk lands at the end. You discover whether it works at cutover, which is the least convenient moment available.

They rediscover undocumented requirements the expensive way. The old system encodes years of accommodations to real situations. Much of that is not written down anywhere else. A rewrite finds it by breaking things that used to work, in production, in front of customers.

They are demoralising. Eighteen months of work with no user-visible outcome is difficult for a team to sustain, and turnover mid-rewrite is common and destructive.

None of this means replacement is never right. It means replacement should be incremental.

The incremental alternative

Step one: stabilise before changing anything

Unglamorous and frequently the highest-return work available.

  • Characterisation tests around critical paths — not tests of what the code should do, but tests that record what it does, so you can tell when you change it accidentally.
  • A repeatable, automated deployment.
  • Observability: you cannot modernise a system whose behaviour you cannot see.

Many organisations discover that stabilisation alone removes most of the pain. Releases stop being frightening, and the urgency for a rewrite evaporates. That is a successful outcome, not an abandoned project.

Step two: find the seam worth cutting

The first extraction should be valuable enough to justify itself and self-contained enough to succeed. Getting this choice right is most of the difference between momentum and a stalled programme.

Good first candidates share three properties: a clear boundary in the domain, relatively few dependencies back into the core, and a business reason someone outside engineering cares about.

Bad first candidates: whatever is technically most interesting, and whatever is most tangled. The second one is tempting because it hurts most; it is also where a failed first extraction will cost you the mandate for the rest.

Step three: strangle, do not replace

Route traffic for the extracted capability to the new implementation while the old one still exists. Compare outputs. Keep the fallback available until it is obviously unnecessary.

This is the strangler pattern, and its real value is that every step is reversible. Reversibility is what allows a modernisation programme to proceed at speed, because being wrong costs a rollback rather than an incident.

Step four: leave the knowledge behind

Decision records, documentation, tests. Otherwise the modernised system becomes the next legacy system for exactly the reasons the last one did.

How to sequence it

PhaseFocusYou can stop here if…
1Stabilise: tests, CI, observabilityReleases are safe again and delivery speed has recovered
2Expose an API over the existing systemThe blocker was integration, not the system itself
3Extract the first bounded capabilityThe extracted piece was the constraint
4Extract subsequent capabilitiesDiminishing returns are reached
5Retire what remains of the coreRarely necessary; often the remainder is fine

The right-hand column is the point. Each phase leaves you better off than before it, so continuing is a decision informed by the last phase rather than a commitment made at the start.

Many organisations stop at phase two or three. That is a good outcome — the pain that prompted the work has gone, and the money not spent on phases four and five is money not spent.

Justifying it to people who do not care about technical debt

Technical debt arguments do not travel outside engineering, and they should not — "the code is messy" is not a business case.

These four numbers do travel:

  1. Release frequency. How often can you safely ship? A business shipping monthly is making twelve decisions a year; one shipping weekly is making fifty.
  2. Incident rate and severity. Particularly incidents caused by changes.
  3. Time to deliver a representative change. Pick a real, recent, medium-sized request and measure it end to end. Then say what it would be after phase one.
  4. The list of things you have told the business are impossible. This is the most persuasive item in the set, because every executive recognises something on it.

Frame the ask as the first phase only, with its own cost and its own outcome. A board that will refuse an eighteen-month rewrite will frequently approve a six-week stabilisation with a measurable result — and phase two is a much easier conversation once phase one has landed.

The one thing to verify before you start

If the system has no version history, nothing on the server is a baseline until it has been verified against an external source. A folder named after a version number is a claim, not evidence.

We have seen a modernisation nearly built on an archive that looked pristine and was not. Checking took an hour. Not checking would have silently discarded real customisations and reintroduced changes that had been deliberately removed — and the discovery would have come months later, in production.


Related: a case study on recovering a broken upgrade path, and how we approach software modernization.

Written by

Nadeem Sheikh

Software Architect & AI Automation Engineer

Brain Matrix Solutions is deliberately small so that the person on your first call is the person doing the architecture and the person handing it over. There is no sales layer between us, and nothing gets passed to someone junior after you sign.

Next step

Let's talk about what's holding your business back.

A 45-minute conversation with a senior engineer. We will look at your situation, say what we would do, and tell you if the answer is not software. No pitch deck, no pressure.