The rewrite argument arrives with confidence and a timeline, and the timeline is almost always wrong for a reason that is structural rather than optimistic: the existing system's behaviour is not written down anywhere except in the existing system. Refactoring has its own failure mode, which is that it never quite happens. Choosing between them should start with measurement rather than preference.
01Diagnose the actual problem first
'The code is bad' is not a diagnosis. Is change slow because the code is tangled, or because there are no tests and every change requires manual verification? Are incidents frequent because of architecture, or because of one unreliable dependency? Is the technology genuinely unsupportable, or merely unfashionable?
These have different remedies. Missing tests are addressed by adding tests, not by rewriting. A tangled module is refactored. Only a small subset of problems - a fundamentally wrong data model, a runtime that is genuinely end-of-life, an architecture that cannot meet a hard requirement - actually indicate a rewrite.
| Symptom | Usual cause | Remedy |
|---|---|---|
| Every change takes weeks | No tests, manual verification | Test harness first |
| Frequent production incidents | Specific weak points | Fix those, add observability |
| Cannot hire for the stack | Genuinely obsolete runtime | Incremental migration |
| Cannot meet a performance requirement | Architectural limit | Targeted rewrite of that path |
| Data model is fundamentally wrong | Original assumptions no longer hold | Rewrite is defensible |
| Nobody likes working in it | Often the above, sometimes fashion | Diagnose further |
02Why rewrites overrun so consistently
The old system encodes years of edge cases, regulatory adjustments and one-off fixes that nobody remembers making. A rewrite must reproduce all of them to reach parity, and there is no document listing what they are - you discover them as bug reports after launch.
Meanwhile the old system cannot be frozen, because the business keeps needing changes. So you maintain two systems and build one, with the target moving throughout. This is why rewrite timelines are commonly out by a factor of two or more, and why so many are cancelled partway.
03The strangler pattern is usually the answer
Put a facade in front of the old system, then move capabilities behind it one at a time. Each piece is small, independently valuable and reversible. The old system shrinks gradually rather than being replaced in one terrifying event.
It is slower in aggregate and dramatically less risky, and crucially it can be paused. Priorities change, and a strangler migration that stops halfway leaves you with a working system. A big-bang rewrite that stops halfway leaves you with nothing.
| Big-bang rewrite | Strangler | |
|---|---|---|
| Time to first value | At the end, if it lands | Weeks |
| Risk | Concentrated in one cutover | Distributed, each step reversible |
| Can be paused | No | Yes, at any point |
| Total effort | Lower in theory | Higher, with overhead |
| Historical success rate | Poor | Good |
04When a rewrite is genuinely right
Small systems, where the whole thing can be rebuilt in weeks rather than years. Systems where the data model is fundamentally wrong and no amount of refactoring changes that. Runtimes that are genuinely unsupported with real security implications. And cases where the business requirement has changed so much that the existing system solves the wrong problem.
The common thread is that incremental change cannot get there from here. If a plausible incremental path exists, it is nearly always the better choice regardless of how unappealing the existing code is.
05Before committing either way
Write down what specifically is wrong, with evidence - deployment frequency, incident rates, time to implement a representative change. Then estimate both paths honestly, including the cost of maintaining the old system during a rewrite, and double the rewrite estimate because that is what the historical record supports.
If the rewrite still wins after that, it is probably genuinely the right call. If the case only works with an optimistic timeline and a frozen old system, you have found the reason most rewrites end badly.
Topics
Marcus Hale
Lead Architect · SyncTrix
Writes about the engineering decisions behind production systems - architecture, delivery and the trade-offs that only show up at scale.
Building something like this?
SyncTrix engineers AI, SaaS, platform and cloud systems for enterprises and high-growth teams. Tell us what you're shipping and we'll scope it with you.
Talk to an engineer