Why I rewrote nothing: the case against the big rewrite

By Kunjan Dalal 2026-06-04 5 min read
ArchitectureRefactoringEngineering

When a codebase is a mess, the rewrite is tempting and almost always wrong. Here's why I refactor incrementally instead, and how a rescue actually works.

When I’m brought in to rescue a tangled codebase, the team has usually already decided what they want: burn it down and start over. It’s the most natural instinct in software, and it’s almost always wrong.

I rescued an F# finance platform for a UK client and a sprawling React codebase for a Swiss one. In neither case did I rewrite from scratch. Here’s why.

The rewrite throws away things you can’t see

A messy codebase looks like pure liability. It isn’t. Buried in that mess are hundreds of small fixes — the edge case someone hit in production at 2am, the validation that exists because a real user did something nobody predicted, the workaround for the third-party API that lies about its own responses.

None of that is documented. It lives only in the code. A rewrite deletes all of it and rediscovers each one the hard way, in production, with real users. The new system is cleaner and more broken, often for a year.

The rewrite races a moving target

While you rewrite, the business doesn’t stop. The old system keeps gaining features you now have to replicate, or you freeze it and fall behind competitors. Either way you’re spending your most expensive months producing zero new value — and “we’re almost done” is the most dangerous sentence in software.

Incremental is slower per step and faster overall

So instead I untangle in place. The shape of it:

  1. Read the real code and find where it breaks: the duplicated logic, the missing boundaries, the parts with no tests under them.
  2. Stabilize first. Put tests around the parts that matter, so changes stop being terrifying.
  3. Carve boundaries one at a time. Pull a coherent piece out behind a clean interface. Now it’s isolated and changeable without touching the rest.
  4. Fix what’s slowing them down now first, then improve architecture behind it.

Production stays live the whole time. The team keeps shipping. There’s no “big bang” cutover where everything has to work at once or nothing does.

Why it’s fast in practice

People assume incremental means slow. The opposite, usually. Because I’ve done this for years, I know where these messes break — especially the AI-generated ones, which fail in patterns I’ve seen dozens of times. I’m not exploring; I’m executing. The first clean, deployable build is often days, not months.

A rewrite feels fast because the early days are greenfield and fun. It gets slow exactly when it gets hard — re-implementing all those invisible fixes under deadline pressure. Incremental front-loads the hard part and stays predictable.

The one time a rewrite is right

Rarely, the foundation is genuinely unsalvageable — a platform that’s end-of-life, or constraints so different that nothing transfers. Even then, the move is usually the strangler-fig: stand the new thing up alongside the old and migrate piece by piece, never a flag-day cutover.

If your codebase is a mess and the team is reaching for the rewrite button, talk to me first. Book an architecture call — most of the time, there’s a faster, safer path that keeps everything you’ve already paid for.