Rewrite vs Refactor: What to Do With Legacy Software That Still Runs the Business
An honest framework for deciding whether to rewrite or refactor legacy software: the signals for each, the incremental middle path, and why the big-bang rewrite is so often the wrong call.
Every team living with old software eventually has the same argument. One side says the code is beyond saving and the only way forward is to start again. The other side says a rewrite will take twice as long as anyone thinks and the business cannot stop while it happens.
Both sides are usually partly right. The good news is that the choice is rarely all-or-nothing. This is the framework we use when a client brings us a system that still runs the business but that nobody wants to touch.
Why the full rewrite is so tempting, and so risky
A rewrite promises a clean start: modern stack, no accumulated shortcuts, no code nobody understands. The appeal is real.
The risk is also real, and it comes from three places:
The old system knows things nobody wrote down. Years of bug fixes, edge cases, and customer-specific rules are encoded in that messy code. A rewrite has to rediscover every one of them, usually by getting them wrong in production first.
The business does not stop. While the new system is being built, the old one still needs fixes and features. You end up funding two systems, and the new one is chasing a moving target.
Nothing ships until everything ships. A big-bang rewrite delivers no value until the day it replaces the old system entirely. That day tends to move.
None of this means rewrites are always wrong. It means a rewrite has to earn its place.
Signals that refactoring is the right call
Refactor, meaning improve the existing code in place, when:
- The system works and the business logic in it is broadly correct
- The main problems are slowness to change, missing tests, and tangled code
- The technology stack is old but still supported and hireable
- The data model is fundamentally sound
- You need to keep shipping improvements while you fix things
Refactoring is unglamorous. It is also the lowest-risk path, it delivers improvements continuously, and it keeps all the hidden knowledge in the code intact.
Signals that a rewrite is justified
A rewrite of some or all of the system is justified when:
- The platform or language is no longer supported and cannot be patched
- The data model is wrong for how the business now works, and every feature fights it
- Security or compliance requirements cannot be met by the current architecture
- The cost of each change keeps rising and refactoring has stopped moving the needle
- The system has to do something fundamentally new, not just the same things better
Even then, the question is rarely "rewrite everything at once". It is "rewrite which part, in what order".
The middle path: replace it piece by piece
The approach we recommend most often is incremental replacement, sometimes called the strangler pattern:
- Put a stable interface in front of the old system. Usually an API layer that the rest of the world talks to.
- Pick one area to replace. Ideally the one that hurts most or changes most.
- Build the replacement behind the interface and route that area's traffic to it.
- Retire that piece of the old system once the new one is proven.
- Repeat, one area at a time.
Each step delivers something real. The business never stops. If priorities change halfway through, you are left with a working system, not an abandoned rewrite. And the hidden knowledge in the old code gets examined one area at a time instead of all at once.
A quick decision guide
| If this is true | Lean towards |
|---|---|
| It works, it is just slow and painful to change | Refactor |
| One or two areas cause most of the pain | Incremental replacement of those areas |
| The platform is unsupported or insecure | Re-platform or replace, in phases |
| The data model is wrong for the business | Rewrite, starting with the data |
| The project stalled or the team left mid-build | Audit first, then decide |
Start with an audit, not an opinion
The rewrite-versus-refactor argument usually happens on opinion. It should happen on evidence. A proper audit looks at:
- Which parts of the code change most often, and which cause most bugs
- Test coverage and how safely the code can be changed today
- The health of the data model
- Dependencies and whether they are still supported
- Security gaps
- How the system is deployed and how it would be rolled back
The output is a map: which areas to keep, which to refactor, and which to replace, in what order and at what cost. That map is what turns a heated debate into a plan.
This is how our legacy software modernization work starts: a fixed-price assessment, then phased delivery where each phase is scoped and priced on its own, with the business running the whole time.
FAQ
How do I know if my software is "legacy"? Legacy is less about age and more about cost of change. If every change is slow, risky, and depends on one or two people who understand the code, the system is legacy, whatever year it was written.
How long does a full rewrite take? Almost always longer than the first estimate, because the old system contains more behaviour than anyone documented. This is the main reason we prefer incremental replacement: each phase has its own, much more reliable estimate.
Can we modernize without changing the user interface? Yes. Many modernizations replace the back end, the data layer, or the hosting first and leave the interface alone, so users see no disruption.
Is moving to the cloud the same as modernizing? No. Moving hosting can remove infrastructure risk, but the application itself is unchanged. Sometimes that is exactly the right first step; see our cloud migration guide.
Muhammad Nabeel is the co-founder of Teamseven. We have taken over and modernized business-critical systems since 2017. If you're stuck in the rewrite-or-refactor argument, book a free 30-minute call and we'll help you settle it with evidence.
Related reading
Stay connected
Build notes, launches, and new articles from the Teamseven team.
