Joel Spolsky on Rewrites, Twenty-Five Years Later
In April 2000, Joel Spolsky published "Things You Should Never Do, Part I," arguing that throwing out a working codebase and starting over is the single worst strategic mistake a software company can make. Twenty-five years later it remains the piece most people cite when they argue against a rewrite, including, frequently, in our inbox.
Plenty gets attributed to that essay that is not in it.
The core argument
Spolsky's central claim is about information. Old code looks bad, but the ugly parts are usually bug fixes rather than carelessness. Each strange conditional encodes a real-world case somebody hit, reported, and fixed. Throw the code away and you throw away the accumulated knowledge, then rediscover every one of those cases the hard way.
Underneath it sits an observation about why the instinct is so universal:
It's
harder to read code than to write it.
That asymmetry is why every developer
finds existing code worse than it is and their own rewrite easier than it will be.
The essay's canonical example was Netscape, which
rewrote its browser engine and spent roughly three
years unable to ship a competitive release.
What has held up
Most of it. Twenty-five years on:
- The information argument got stronger. Systems now carry more integrations, more compliance rules, and more undocumented edge cases than in 2000, so each strange conditional buries more history than it used to.
- Feature parity is still a moving target. Nothing about modern tooling stops the old system from shipping while you chase it.
- The asymmetry is unchanged. Reading code is still harder than writing it, which is still why the rewrite estimate is always wrong in the same direction.
What the argument was missing
Two things, and both matter more now than they did.
It diagnoses without prescribing. "Never rewrite" is advice about what not to do. It leaves a team that cannot work in its system with nowhere to go, which is why the essay so often loses the argument in practice: the person advocating the rewrite has a plan, and the person quoting Spolsky has an objection. Our answer to that gap is TheseusShipping. Keep one system in production and replace its parts using boundaries, characterization tests, and controlled rollout. It is a plan you can put on a roadmap, which is the thing "do not do that" can never be.
The failure is organizational as much as informational. Spolsky's account explains why the new system will be worse than expected. It does not explain why rewrites destroy teams. In practice a rewrite goes quiet. No shipped features, no improved metrics, nothing outside the team can evaluate. The leader who approved it responds to that silence with oversight: more detailed updates, more frequent reviews, more stakeholders. To the team that is micromanagement; to the leader it is managing risk with no signals. Both readings are correct, and the supervision itself slows the work, which deepens the concern. The spiral comes from one missing ingredient: visible incremental results.
Where we would push back
The essay is sometimes read as "legacy code is sacred." It is not, and treating it that way produces its own paralysis: the module nobody will touch, the "do not touch" zone that keeps growing.
The more useful framing is that three kinds of problem justify going into a module: code that does not work consistently, code that needs to change for new business needs, and code that does not run fast enough. "Developers hate it" is not one of them. Bad code is an ambush predator. It sits still until you have to walk into it, so if nothing forces you in, leave it. When something does, that is the trigger, and you clean up while you are there.
That is a more actionable rule than "never," and it survives the case Spolsky's version does not: the system with a real forcing function, like the end-of-life platform Khan Academy was on when it migrated off Python 2.7. Sometimes you do have to replace the thing. The question is whether you do it with one cutover or two hundred.
Does AI change the verdict?
It sharpens it. Spolsky's argument rests on the cost of recovering knowledge locked in old code, and that is the cost AI has lowered most. AI can read the commits, the tickets, and the old decisions and explain why the system behaves as it does, then write characterization tests to lock that behavior in.
Which cuts against the rewrite, not for it. If the expensive part of working in legacy code just got cheaper, the case for escaping it got weaker. And whatever speed AI gives a rewrite it gives to iteration too, so the comparison has not moved in the rewrite's favor. What AI does change is the timeline. Instead of taking a year to fail, a rewrite can now fail in two months, and that smaller number should not be reassuring. Two months of focused iteration would have produced dozens of real improvements.