Strategy · 7 min
When not to rewrite
The rewrite is the most expensive and most seductive decision in engineering. A framework for deciding when it is right, and when it is the wrong call dressed up as progress.
Rewrites are the most expensive decision a technology organization can make. They are also the most seductive, because the code in front of you always looks worse than the code you imagine writing next. Every engineer has had the thought: if we could just start over, with what we know now, how clean it would be. That feeling is not wrong, but it is not a strategy. It is a fantasy, and fantasies do not have budgets, timelines, or unhappy customers waiting for features that do not ship while you rebuild what already works. The honest test is not whether the current system is imperfect. Every system is imperfect, and every system you build to replace it will be imperfect too, in new ways you cannot yet see. The real test is whether the cost and risk of rebuilding, including the opportunity cost of what your team will not build while rebuilding, is genuinely lower than the cost of continuing to extend what exists. That is a hard comparison to make honestly, because the costs of the existing system are visible and painful, while the costs of the rewrite are hypothetical and easy to underestimate.
Most of the reasons teams reach for a rewrite are not reasons at all. The code is ugly. The framework is old. We are tired of working around it. These are real frustrations, but they describe how the team feels, not what the business needs. A rewrite justified by frustration will not survive contact with reality, because reality includes deadlines, changing requirements, and the fact that the new system will develop its own ugly corners within months. If the only argument for a rewrite is that the current code is hard to look at, the answer is almost always to refactor, not to rebuild.
A useful framework: rewrite when the cost of a unit of change in the current system exceeds the cost of a unit of change in a new one, and when the migration can be sequenced without halting the business. Measure the cost of a change in concrete terms, how long a typical feature takes, how many regressions it introduces, how much fear surrounds the deploy. Then estimate, conservatively, what the same change would cost in a clean system. If the gap is large and durable, not a single bad sprint, the rewrite may be justified. Otherwise, refactor. The refactor is almost always the right answer for longer than it feels.
The refactor is underrated because it is unglamorous. It does not produce a launch, a demo, or a slide that says we are modernizing. What it produces is a system that keeps shipping while it improves, which is the only outcome that matters to the business. Refactoring is also lower risk. You change one module at a time, keep the tests green, and roll back anything that breaks. A rewrite, by contrast, is a bet that you can reproduce months or years of accumulated behavior in a new codebase, including the parts nobody remembers but customers depend on. When a rewrite is right, sequence it. Use the strangler pattern: build the new system alongside the old, route traffic to it incrementally, and never make it a big-bang cutover. Validate in parallel, with the old system as a check, until the new one has earned trust on real load. The organizations that survive rewrites are the ones that never stopped shipping while doing them. The ones that fail are the ones that told the business to wait, lost a year, and delivered a system that does less than the one it replaced.
Opportunity cost is the cost most often ignored, and it is usually the one that kills the rewrite. While your team rebuilds, competitors ship. Customers wait. The roadmap stalls. A rewrite that takes eighteen months is not just eighteen months of engineering cost, it is eighteen months of not building the features that would have grown the business. Before you commit, list the things you will not build during the rewrite and price them honestly. If that list is hard to look at, you have your answer.
The discipline, then, is to separate the feeling of wanting a rewrite from the case for one. Wanting it is always present. The case requires evidence: that change is measurably harder, that the new system will be cheaper to extend, and that the migration can run in parallel. Absent that evidence, refactor with discipline, ship continuously, and keep the option open. The option to rewrite later is far cheaper than the commitment to rewrite now.