"Never rewrite from scratch" has been treated as gospel in software engineering for over two decades. Joel Spolsky wrote about it in 2000, and the industry has been repeating it ever since. But like most absolute rules, it deserves more nuance.

The Original Argument

The case against rewrites is well-understood: you lose all the accumulated bug fixes and edge case handling baked into the existing code. You underestimate the scope. You end up with two systems to maintain during the transition. These are real risks.

But the argument assumes a specific context — one where the existing system is fundamentally sound and just needs incremental improvement. That's not always the case.

When Rewrites Make Sense

When the architecture can't support the business. If your monolith needs to become a distributed system, or your batch processing system needs to become real-time, no amount of refactoring bridges that gap.

When the technology is truly end-of-life. Maintaining a system on an unsupported framework or language version isn't pragmatism — it's accumulating risk.

When the team can't reason about the system. If no one on the current team understands how the system actually works, you're already maintaining a rewrite's worth of risk without the benefits.

When the cost of change exceeds the cost of replacement. If every feature takes 3x longer than it should because of accumulated technical debt, the math eventually favors starting fresh.

How to Rewrite Successfully

The rewrites that fail are the ones that try to replicate the existing system feature-for-feature. Successful rewrites take a different approach:

  1. Define the target scope. Not everything in the old system needs to exist in the new one. Use the rewrite as an opportunity to shed features that no longer serve the business.

  2. Migrate incrementally. Use the strangler fig pattern. Run both systems in parallel and migrate functionality piece by piece.

  3. Start with data. Get the data model right first. Everything else can be rebuilt, but data migrations are the hardest part.

  4. Set a deadline. Open-ended rewrites are the ones that fail. Define a cutover date and work backward from it.

The Real Lesson

The lesson isn't "never rewrite." It's "understand what you're getting into and plan accordingly." Sometimes the bravest engineering decision is admitting that the current path is a dead end and charting a new one.