When Should You Refactor—and When Should You Leave It Alone?

Refactor when code measurably increases change cost or risk, with a real next use for the improved structure.

When Should You Refactor—and When Should You Leave It Alone? — Troiana insight cover

In short

Refactor when the current structure repeatedly increases the cost or risk of a valuable change, causes defects in the same boundary, prevents reliable testing, or depends on unsupported components. Leave stable code alone when it is understood, isolated, rarely changed, and the proposed cleanup has no concrete product, reliability, security, or delivery benefit.

Refactoring has a customer: the next change

Good refactoring changes internal structure while preserving intended behaviour. Its return appears through safer changes, fewer defects, clearer ownership, easier testing, or lower operating risk.

If nobody can name the next valuable change or risk it supports, cleanup may be preference rather than priority.

Strong reasons to refactor

  • similar changes require edits in many places;
  • defects repeat in the same boundary;
  • tests cannot isolate important rules;
  • permissions or data logic are inconsistent;
  • deployments are dangerous or recovery is unclear;
  • unsupported dependencies create security or compatibility risk;
  • performance evidence identifies an architectural bottleneck;
  • one person is the only safe operator;
  • a committed feature cannot fit without multiplying workarounds.

Weak reasons

  • the code is not written in the current favourite style;
  • a new framework looks cleaner in examples;
  • the system is old but stable;
  • metrics are absent but performance feels inelegant;
  • a rewrite would be more enjoyable;
  • consistency would improve in code nobody needs to touch.

Refactor beside product work

Use the next change as the boundary. Improve the part required to add the feature safely, then deliver the feature. This keeps the refactor grounded in real behaviour and acceptance.

For broad structural debt, create a separate intervention with baseline, target, migration sequence, tests, rollback, and stop conditions.

Refactor or rewrite?

Prefer incremental replacement when behaviour is valuable but structure is weak. Rewrite only when boundaries cannot be isolated, the platform is unsupported, or preserving the system costs more than recreating and validating its behaviour.

Rewrites must rediscover years of undocumented rules. Inventory behaviour, data, integrations, operations, and edge cases before assuming new code is simpler.

Measure the result

  • lead time for representative changes;
  • defects and incidents in the boundary;
  • test reliability;
  • deployment and recovery time;
  • performance where relevant;
  • dependency or vulnerability exposure;
  • number of people able to work safely.

Common questions

Should code be refactored before adding features?

Only the structure required to add the feature safely. Avoid broad cleanup unless the feature exposes a systemic constraint with a justified intervention.

Is refactoring technical debt repayment?

Often, but not every refactor addresses debt. Debt implies a current shortcut with future consequence; refactoring is one possible response.

How much time should a team spend refactoring?

There is no universal percentage. Allocate work according to measured change cost, risk, incidents, and upcoming product needs.

Can refactoring change behaviour?

Intended behaviour should remain stable. Tests and monitoring protect it; any deliberate behaviour change should be scoped and reviewed separately.

When should old code be left alone?

When it is stable, understood, isolated, secure enough for its consequence, and unlikely to change—and when cleanup would displace more valuable work.

Have something worth building right?