Back to Writing
Growth status: Evergreen EvergreenUpdated: Feb 13, 20265 min read

When to refactor vs rewrite

Legacy code is frequently a fossil record of production incidents. When you rewrite without fully understanding the behavior, you do not create a cleaner system. You create a regression generator.

A decision tree for grown engineers

Every engineering team eventually faces the same dramatic sentence.

We should just rewrite this.

It is usually said after a bug, a missed deadline, or a moment of emotional exhaustion while reading a file that appears to have been written during a power outage.

Rewriting feels clean. Refactoring feels responsible.

One sounds heroic. The other sounds like laundry.

But this decision is not about emotion. It is about risk, economics, and time.

Let us walk through it like adults.


First question

Does the system work

Not beautifully. Not elegantly. Not in a way that makes you proud.

Does it work.

If the system is stable, generating value, and customers depend on it daily, you are not staring at a technical problem. You are staring at a revenue engine.

Rewriting revenue engines is not bravery. It is surgery.

Refactor when the system works but hurts.

Rewrite when the system fundamentally cannot meet current or future requirements.

If it works and you just dislike the style, close the tab and drink water.


Second question

Is the problem structural or local

Local problems are ugly functions, confusing modules, long files, poor naming, duplicated logic.

Structural problems are incorrect domain models, broken abstractions, wrong architectural boundaries, impossible scaling constraints.

Refactoring fixes local problems very well.

Rewriting is justified only when the architecture itself prevents progress.

If you can improve it piece by piece without stopping delivery, refactor.

If every small change creates chaos because the foundations are wrong, then you may need a rewrite.

Be honest here. Most problems are local.


Third question

Do you fully understand the current system

This is where most rewrite projects quietly die.

If the current system is confusing, that confusion often contains business rules that no one documented.

Legacy code is frequently a fossil record of production incidents.

When you rewrite without fully understanding the behavior, you do not create a cleaner system. You create a regression generator.

If the answer is no, you do not understand it deeply, your first step is not rewrite.

Your first step is to learn.

Refactor while learning. Add tests. Document behavior. Shrink uncertainty.

Rewrite only after you can explain the old system clearly to someone else.


Fourth question

Is delivery allowed to slow down

Rewrites consume focus. They create parallel universes. You maintain old and new simultaneously.

If your company cannot afford slower feature delivery for months, rewriting is fantasy.

Refactoring allows incremental progress. You improve while shipping.

If the business needs momentum, refactor.

If the business is intentionally investing in a platform reset, and everyone understands the cost, then rewrite can be strategic.

But it must be a business decision, not a developer mood swing.


Fifth question

Are tests strong enough to protect you

Refactoring relies on safety nets.

If you do not have meaningful tests, refactoring feels dangerous and rewriting feels tempting.

But here is the uncomfortable truth.

Rewriting without tests is gambling at a higher table.

If you cannot confidently change the system today, you will not magically become confident rebuilding it from scratch.

Invest in tests first.

The decision becomes clearer once safety exists.


Sixth question

Is the pain growing or stable

Some code is ugly but stable. It does its job quietly.

Other systems become slower, harder to change, and more fragile every quarter.

If the cost of change is compounding, you are facing architectural debt.

In that case, continuing to patch may be more expensive than starting fresh.

If the cost is flat and predictable, refactoring over time is usually sufficient.

Measure change cost. Do not guess.


The practical decision tree

Here is the simplified version.

Does it work and generate value Yes Then prefer refactor

Does the architecture block critical future goals Yes Consider rewrite

Do you deeply understand current behavior No Learn and refactor first

Can the business tolerate slower delivery No Refactor

Are tests strong No Strengthen them before anything dramatic

Is change cost compounding Yes Rewrite might be strategic

Notice something.

Rewrite appears only after several gates.

That is intentional.


The emotional trap

Rewriting feels productive because it removes friction instantly.

You open a new folder. The files are clean. The abstractions are pure. You feel like an architect instead of a mechanic.

But software is not a painting. It is an evolving system embedded in reality.

The old code survived production traffic. It contains scar tissue that protects you from repeating mistakes.

Refactoring respects that history.

Rewriting erases it.

Sometimes erasing is necessary. Often it is ego.


A healthier pattern

Instead of thinking refactor or rewrite, think in layers.

Stabilize the existing system with tests.

Extract boundaries slowly.

Replace modules behind interfaces.

Strangle old components with new ones.

Over time, the system becomes new without a dramatic rewrite event.

The business never feels a reset. The engineers never freeze progress.

This is less cinematic. It is also less catastrophic.


The uncomfortable conclusion

Most teams do not need rewrites.

They need discipline.

They need tests, clearer boundaries, smaller pull requests, and patience.

Rewrites are rare strategic moves.

Refactoring is daily engineering.

If you find yourself wanting to rewrite, ask one final question.

Am I solving a structural constraint Or am I trying to escape complexity I have not yet understood

The answer determines whether you are being an engineer

Or just emotionally refactoring your feelings.

Share this writing