Skip to content
ZERO-RISK100% replacement guarantee on every hire.See how we work
Back to blog
LEGACY SYSTEM MODERNIZATION6 MIN READ

How to modernise legacy software without breaking what already works

The big-bang rewrite is the riskiest way to modernise. It asks you to stop learning from the old system, build a new one in parallel, and switch over on one day. Everything you did not know about the old system surfaces at the worst possible time.

SHAREinX
How to modernise legacy software without breaking what already works illustration

The big-bang rewrite is the riskiest way to modernise. It asks you to stop learning from the old system, build a new one in parallel, and switch over on one day. Everything you did not know about the old system surfaces at the worst possible time.

There is a safer path. It is slower to explain than "rewrite it", but it keeps the business running, and it produces value early. Here are the six steps we follow, with the reasoning behind each one.

1. Map before you move

Reverse-engineer the system module by module. List every integration and every scheduled job. Note which tables each module reads and writes. Talk to the people who run the system, and to the people who complain about it.

Surprises are cheaper on paper than in production. A nightly job that exports a file to a partner is easy to miss in the code, and impossible to miss when the partner calls on Monday.

2. Pick the seams

Find parts of the system with clear boundaries, such as billing, notifications or reporting. Those move first. A good seam has few inbound dependencies, a defined input and output, and a business owner who cares.

Avoid starting with the most tangled core module. You want an early win that proves the method and builds trust. Save the hard part for when the team has momentum and a working migration routine.

3. Strangle, don't swap

Put new services in front of the old system and route traffic to them one capability at a time. This is often called the strangler pattern. The old system shrinks until it can be switched off.

A routing layer or API gateway makes this practical. Each capability has a switch: old path or new path. If the new path misbehaves, you flip back. There is no cliff edge.

4. Migrate data with proof

Reconcile counts and totals after every migration step. "It looks right" is not a test. Compare row counts, key fields and financial totals between old and new. Write exceptions to a report, and have a person decide what each one means.

A real pattern we see: free-text fields with years of inconsistent entries, or business rounding rules living in stored procedures. Automated reconciliation finds these. A visual check does not.

5. Run in parallel

Keep old and new running side by side until the new path has handled real traffic without issues. Compare outputs. Let the business see the results. Only then retire the old component, and give the retirement a date.

Parallel running costs effort, because you are operating two systems. It is cheap compared with a failed cutover.

6. Protect the people who know

Pair your legacy experts with the modernisation team so their knowledge ends up in docs, not just in their heads. They are your best source of "why does it do that?" Make their role clear and valued. People who feel replaced do not share what they know.

A cutover checklist

  • Reconciliation passes on the latest data copy.
  • The rollback step is written down and has been rehearsed.
  • Support and business teams know the cutover window.
  • Monitoring covers the new path, with alerts that someone will answer.
  • The old system stays available, read-only, for a defined period.
  • A named person has authority to call a rollback.

A worked example: moving billing first

Suppose billing is the first seam. It has a clear input (usage records) and a clear output (invoices). You build a new billing service that reads the same usage records and produces invoices. For a month, both systems produce invoices. A script compares totals, line items and tax amounts for every customer.

Most will match. The few that do not are the valuable ones. One turns out to be a customer with a special contract rate stored in a spreadsheet. Another is a rounding rule. You fix the new service, record the rule and run the comparison again. When a full cycle matches, you route real invoicing to the new service and keep the old one read-only for a while.

Team and roles

A small group works best. You need an architect who can read old code and design the target. You need two or three engineers who build and migrate. You need a QA specialist who owns reconciliation and regression checks from day one, not at the end. And you need a business contact who can answer, "Is this result correct?"

Hold a short daily standup and a weekly review with the business. Keep a visible list of open exceptions and who owns them.

Deciding what not to move

Not every part is worth the effort. Rarely used features, reports nobody opens and modules with no active users may be retired instead. Ask the business to confirm usage before you spend time migrating. Each item you drop reduces risk and shortens the timeline.

Signs the plan is working

  • Releases get smaller and less stressful.
  • The list of undocumented behaviour is shrinking.
  • The old system handles less traffic each month.
  • Reconciliation differences are explained and fall over time.
  • The business trusts the new system because it has seen the numbers match.

If these signs do not appear, stop and look at the plan. Do not wait for the final cutover to find out.

Common mistakes

  • No rollback plan. If you cannot go back, you are not testing, you are gambling.
  • Skipping documentation because "the code is the documentation". It is not, for the people who join next year.
  • Migrating all the data at once. Do it in steps you can verify.
  • Letting the parallel run drag on forever. Set exit criteria and a date.

Handling the data layer

The database is usually the hardest part. Code can be replaced one function at a time. Data has to be consistent. There are three common options.

  • Shared database for a while. New and old services read and write the same tables. It is quick, but it ties the two together, so use it only as a stage.
  • Sync both ways. Changes in either system are copied to the other. It lets you move users gradually, but conflicts need clear rules about which side wins.
  • Move and cut over. Copy the data, verify it, then switch writes. It is clean, but needs a rehearsed window and a rollback.

Pick per module. Billing might use option three, while a reporting module might read a copy. Whichever you pick, write down how you would detect drift between the two sides, and who checks it.

Tests that protect you

Write characterisation tests before you change anything. These record what the old system does today, including odd behaviour, so you can prove the new one matches or differs on purpose. Capture real inputs and outputs from production, with sensitive data removed, and replay them against both systems. Differences become a to-do list, and each one needs a decision: copy it, fix it or retire it.

What to do next

Choose one capability with a clear boundary. Map its code, data and integrations. Define what "match" means for its data. Build the new service behind a switch, run it alongside the old one, and compare.

Most teams know all this. What they lack, as 71% told Growth Acceleration Partners, is time. Senior engineers who join in 72 hours give you that time. Brandsmashers can help you map, build and prove each step, working inside your team.

SHARE THIS ARTICLEinX

NEXT STEP

Need help with this?

KEEP READING

More insights.

ALL ARTICLES