Legacy Modernization: Rewrite, Replatform, or Refactor?

Most legacy systems are not replaced because they stopped working. They are replaced because the people who understood them left, the platform fell out of support, or the business needs something the design cannot accommodate. Those are three different problems, and they point to three different strategies.

Option 1: Refactor In Place

Keep the system running and improve it incrementally — add tests, break apart the worst-coupled modules, replace dead dependencies, expose an API. Nothing dramatic happens on any single day.

Choose this when the business logic is still correct and valuable, the platform is still supported, and the real problem is that the system is hard to change. Avoid it when the underlying runtime is out of support with no upgrade path, or the data model actively prevents what the business now needs.

The honest risk: refactoring can become permanent. Without a defined end state, it turns into indefinite maintenance that consumes budget without ever arriving anywhere.

Option 2: Replatform

Move the system largely as-is onto supported infrastructure — a current runtime, a managed database, containerized hosting — changing as little application logic as possible.

Choose this when the pressure is operational: unsupported operating systems, hardware nobody will service, a hosting arrangement that has become a risk, or a compliance requirement about where data lives. Avoid it when the application logic itself is the problem — replatforming a system nobody can change gives you an unchangeable system on nicer infrastructure.

This is often the correct first move even when a rewrite is the eventual plan, because it buys time and removes the urgency that makes rewrites rushed.

Option 3: Rewrite

Build a replacement, migrate the data, retire the original.

Choose this when the data model cannot support the business as it now works, when the platform is genuinely dead, or when the cost of change has risen so far that small requests take months. Be careful everywhere else. Rewrites fail in a recognizable pattern: the replacement must match years of accumulated behaviour before anyone can switch, the original keeps changing during the build, and the switchover date slips until confidence runs out.

The Strategy That Usually Works: Strangle It

Rather than a single cutover, route one capability at a time to new code while the legacy system continues to serve the rest. A facade in front of both directs traffic; each slice moves independently; each is reversible.

  • Value arrives during the project rather than only at the end.
  • Every step is individually reversible, so risk stays bounded.
  • The legacy system can keep running for as long as it needs to.
  • If priorities change, you stop with real value delivered rather than a half-finished replacement.

It requires discipline — running two systems is genuinely harder than running one, and it is easy to leave the last stubborn twenty percent forever. Name the end state and track progress toward it.

Questions Worth Answering First

  • What breaks the business if this system is unavailable for a day? That sets your risk tolerance.
  • Who understands the business rules encoded in it? If the answer is nobody, discovery is a bigger job than the build.
  • Is the data model the constraint, or just the code? This is the single most important distinction.
  • What is the actual deadline — a support end date, an audit, a contract? Real deadlines change the calculus; imagined ones cause rushed rewrites.

The Short Version

Refactor when the code is the problem. Replatform when the infrastructure is the problem. Rewrite when the data model is the problem — and even then, move capability by capability rather than all at once. A modernization plan that cannot deliver anything for twelve months is a plan with a high chance of being cancelled at month nine.

Related service: Product engineering and legacy modernization