When to Rewrite, When to Refactor
11 March 2026

"We need to rewrite this from scratch."
I've said this. I've heard it said. I've been the person advocating for it and the person trying to talk someone out of it. The rewrite conversation is one of the most emotionally loaded in engineering — it feels like a technical discussion but almost never is one.
Here's how I actually think about it.
The rewrite is almost always a lie you tell yourself
Not always. But mostly.
The mental model behind a rewrite is that your current codebase is the problem. If you could just start clean — with everything you know now, no legacy decisions, no accumulated debt — the new version would be better and you'd build it faster.
This is almost never true. The mess you're trying to escape is usually a combination of three things: genuinely bad decisions made early, complexity that was inevitable given the problem, and your own incomplete understanding of the domain when you started. A rewrite doesn't fix the second or third. It just relocates them.
The old codebase has something the new one doesn't: years of edge cases, bug fixes, and production hardening. The weird branches in the code aren't accidents — most of them are scars. You'll rebuild them all, just more slowly.
When a rewrite is actually the right call
Sometimes it is, though.
The signal isn't "this code is messy." The signal is "the assumptions baked into this architecture no longer match the problem." When the shape of what you're building has changed so fundamentally that every new feature requires fighting the existing structure — not just reading it carefully, but actively working around it — then the code isn't technical debt. It's the wrong code.
I rewrote the meeting engine in Clover and Argan — switching from a WebRTC + TURN server architecture to mediasoup. Not because the original was broken. WebRTC with a TURN server works. But users buying a self-hosted meetings platform don't want to provision and maintain a TURN server. They want something that works out of the box.
The original technology choice had become the constraint — not because it couldn't do the job technically, but because the deployment assumptions it required didn't match what users were actually willing to do. That's still a wrong model. It just lives at a different layer than the code.
That's the distinction: wrong model vs. messy implementation. Wrong models need rewrites. Messy implementations need refactoring.
What refactoring actually means
Refactoring gets misused constantly. "We should refactor this" often means "we should clean this up" which often means "I don't like how this looks."
Real refactoring is something specific: changing the structure of code without changing its behavior, in service of making the next change cheaper. It's not an end in itself. It's a technique for reducing the cost of the thing you're actually trying to build.
This framing matters because it gives you a stopping criterion. You refactor until the next change is easy, then you stop. You don't keep going until the code looks the way you'd write it today. That's perfectionism with a different name.
The signals I use
Rewrite when:
- The core data model is wrong for how the product is actually used
- Every new feature requires touching the same risky, poorly-understood area
- The original technology choice is the constraint — a framework that can't do what you need, not one you just prefer differently
- The existing code can't be tested in a way that would give you confidence to change it
Refactor when:
- You understand what the code does but it's hard to change
- A specific area causes repeated bugs that wouldn't exist with better structure
- You're about to add a significant feature and the approach will be cleaner with some targeted cleanup first
Leave it alone when:
- It works and you don't need to change it
- You just don't like how it looks
- Someone else would have done it differently
The last category is where a lot of unnecessary work gets created.
The honest version
When engineers advocate for rewrites, it's often because they're bored with maintaining something, or they want to use a different technology, or they feel that the old code reflects badly on them and they want a fresh start that doesn't carry that history.
None of these are good reasons to rewrite. They're human reasons — I've felt all of them — but they're not engineering reasons.
The discipline is being honest about which one you're actually doing. If it's a genuine model problem, a rewrite can save you months of fighting the wrong abstraction. If it's preference dressed up as principle, you're about to spend significant time and create risk to end up roughly where you started.
Ask the question: is the architecture wrong, or am I just frustrated with it? Usually, a few days of honest effort will tell you which.