By Michaël Van Damme

To rewrite or to refactor: the question most teams answer wrong

Rewrite or refactor: the question most teams answer wrong

Every developer who works on a mature codebase long enough knows the moment. The code has become layered by years of changes. Decisions were made by people who left the company long ago. The architecture no longer fits how the application is actually used today. And then the sentence falls: "This system can't be saved. We're starting over."

I've watched that conclusion get drawn many times. It sounds logical, it feels liberating, and it's usually wrong.


Why rewrites rarely succeed

Joel Spolsky already wrote a classic about it in 2000, "Things You Should Never Do": it's harder to read code than to write it. Anyone reading code they didn't write themselves finds it messy almost by definition. That says little about the code and a lot about how reading works.

What matters more is what's hidden inside that messy code. A production system that's been running for years contains invisible knowledge. The edge case that once caused a customer escalation and has been quietly handled ever since. Business logic that's documented nowhere but is nonetheless correct. An integration with an external system that relies on subtle behavior with not a single line of documentation to explain it.

That knowledge isn't in the documentation, because the documentation is outdated or incomplete. It's not in the heads of the current team either, because the people who made the original decisions are gone. It only lives in the code.

A rewrite throws all of that away. The new application replicates the visible functionality, and you only discover the invisible knowledge afterward, complaint by complaint, every time a user reports that something "used to work." That's why large rewrite projects run over so often, or stall completely. Rarely because the developers weren't good enough. Almost always because everyone underestimated the complexity of the existing system.


When rewriting really is the right choice

I want to stay honest: sometimes there genuinely is no other way. If the application is built on a language or framework you can no longer find developers for. If the architecture is so fundamentally broken that every incremental improvement runs straight into the foundation itself. Or if the business requirements have changed so drastically that the existing system no longer offers a usable base.

Those are real scenarios, and we've run into all of them. They're just rarer than most teams think at the moment when frustration is at its peak.


What refactoring actually involves

Refactoring isn't "a quick cleanup." It's improving the structure of a system without changing its behavior, in small, verifiable steps.

What that looks like in practice depends on the application, but the pattern is recognizable. We almost always start with test coverage on the critical flows, because without a safety net, every change is a gamble. After that, it's about splitting up modules with too many responsibilities, pulling business logic out of controllers and views, and updating dependencies without destabilizing the system. Each step produces an application that does exactly the same thing as before, but is a little easier to understand, test, and extend.

The big difference with a rewrite: this happens while the application keeps running in production. There's no big bang, no migration weekend, no period where two systems have to be maintained side by side while neither one is finished.


The middle path for large systems: strangler fig

For large applications, there's a third way: the strangler fig pattern. You replace the system module by module. New functionality gets built in the new architecture, the existing code stays active in the meantime, and step by step traffic moves from old to new until nothing of the old system remains.

For larger modernization projects, this is usually how we work. The risk stays low, the business keeps running, and the team builds up exactly the system knowledge along the way that gets lost in a classic rewrite.


Look first, judge second

At Refaktory, the preference is baked into our name, so some bias is fair to assume. That's why we never start with a recommendation but with a technical audit: what shape is the codebase in, where do the risks sit, what does each path cost over several years. If the audit shows that rewriting is truly the only realistic option, we'll say so, along with the real costs and risks. An assessment that blows up six months later is worth nothing to us.


Frequently asked questions

How do I know if my application is refactorable? Almost every application is refactorable. The real question is how much work it takes and what it delivers, and that varies enormously by codebase. That's why we always start with a technical audit.

Is refactoring cheaper than rewriting? In most cases, considerably so, for two reasons. Rewrite projects structurally run over because the complexity of the old system gets underestimated. And refactoring delivers value along the way, while a rewrite only delivers something once everything is finished.

Can we keep using the application during a refactor? Yes, that's exactly the point. The application keeps running in production while the work happens.

What if the codebase truly can't be saved? Then we'll say so, along with the real costs and risks of a rewrite. Advice that isn't accurate comes back to us sooner or later regardless.

contact

What's your next
challenge?

Got an idea? A question? A specific challenge? We're happy to take the time to talk it through with you, no strings attached.

Not convinced yet?

Name
Last name
Email
Phone (optional)
What are you working on?