All insights

Technical strategy

Refactor or rewrite? A decision framework for aging products

How to distinguish frustrating code from a genuinely exhausted architecture—and improve a live system without gambling the business on a clean slate.

Published August 8, 2026 · 8 min read

Measure the constraint, not the frustration

Teams often ask for a rewrite after a painful release, but pain can come from missing tests, poor deployment practices, unclear ownership, or a handful of high-change modules. Replacing the language or framework does not automatically fix those conditions.

Collect evidence: lead time for common changes, defect concentration, recovery time, infrastructure cost, onboarding time, and parts of the system nobody can safely modify. The rewrite case should name the constraint it removes and how that improvement will be measured.

Try to buy safety first

Before replacing working behavior, add visibility around it. Characterization tests capture what the current system actually does, observability reveals the expensive paths, and a repeatable deployment process reduces the cost of every later change.

Look for seams where one capability can be isolated behind an API or module boundary. Moving a high-change area incrementally can create value sooner and test the proposed architecture under production conditions.

  • Map dependencies and data ownership.
  • Identify business rules that exist only in code or staff memory.
  • Separate operational problems from architectural ones.
  • Estimate migration, dual-running, training, and rollback—not only new development.

Know when replacement is justified

A rewrite becomes more reasonable when the current platform blocks required security support, cannot meet a demonstrated scale or reliability need, depends on unavailable expertise, or makes a necessary product model impossible without pervasive change.

Even then, a staged replacement is usually safer than a launch-day switch. Route a narrow capability to the new system, reconcile results, and expand only after its behavior is understood.

Plan for the data, not just the code

Data migration is often the real project. Define field mappings, invalid legacy cases, reconciliation reports, cutover ownership, and a rollback window. If old and new systems run together, decide which one is authoritative for every record and how conflicts are resolved.