Skip to content

How to modernize a legacy system while the business keeps running

A staged rewrite, module by module, with the old system live until each piece is proven. The audit that comes first, the order of attack, and the mistakes that cause outages.

By CharbelModernization

Audit before you touch anything

The system that runs the business is rarely documented, and the people who built it have usually moved on. The first deliverable of a modernization is not code; it is a map. What runs where, which jobs depend on which tables, what the cloud bill is paying for, which parts are at risk because one person understands them, and which parts quietly work and should be left alone.

Write the documentation as if the team would be replaced tomorrow, because in a sense it is being replaced. The audit also produces the first honest estimate, which is why we do it as a fixed first project rather than a sales exercise.

  • What runs where, what it costs, what is at risk
  • Documentation as the first deliverable
  • The audit is the estimate

Pick the order of attack

Start where the pain is highest and the blast radius lowest. A reporting module that frustrates everyone but touches no money is a better first slice than the billing engine. Each slice is rebuilt as a separate service or module with a clean interface, placed in front of or beside the old code, and the old path stays available.

This is the strangler fig pattern Martin Fowler described: new growth around the old trunk until the old trunk can be removed. In plain words, you never do the big-bang rewrite. The big bang is where outages, budget overruns and two-year projects with nothing shipped come from.

  • Highest pain, lowest blast radius first
  • Strangler fig, not big bang
  • Each slice has a clean interface and a way back

Release behind a switch

Every slice goes live behind a feature flag or routing rule, so the new and old paths run side by side. Verify against real traffic: compare outputs, check the numbers reconcile, watch latency and errors. Only when the new path has proven itself does the old one retire, and a switch means you can go back in a minute rather than a weekend.

Data is where most migrations hurt. Move it in stages, keep the old store readable until the end, and treat the reconciliation report as a release gate, not a nice-to-have.

  • Old and new side by side
  • Verification against real traffic before retirement
  • Data moved in stages with reconciliation as the gate

After the rewrite

A modernized system becomes legacy again the day upgrades stop. The team that rebuilt it should keep it healthy: framework and cloud upgrades as routine work on the weekly rhythm, monitoring that pages a person, and documentation that changes with the code. The cost of this is small compared with the next rewrite.

If you want to bring the system in-house later, that is a hand-over, not a cliff. Everything is already in your accounts and your repositories, so the question is only who turns up on Monday.

  • Upgrades as routine, not projects
  • Monitoring and documentation that move with the code
  • In-house later is a hand-over, not a rewrite

In short

Audit first, then replace the system module by module behind a switch, keeping the old one live until each piece is verified. The team that modernized it should keep it healthy afterwards.

Sources

  1. Martin Fowler, Strangler Fig Application

A question these posts didn’t answer?

Ask it on a 30-minute call, or send three quick answers and hear back from an engineer the same day.