Skip to content
Engineering2 min read

Migrating off a system nobody understands

How we moved a bank off an undocumented mainframe with zero production incidents — and why the rehearsals mattered more than the code.

Marcus Feld

Delivery Lead · 9 February 2026

The system had no API, no documentation, and no surviving author. It processed every customer transaction the business made. A previous attempt to replace it had been abandoned.

Eleven months later we completed the migration without a single production incident. Almost none of the reason for that was clever engineering.

Do not replace it

The instinct with a system nobody understands is to rewrite it from the specification. There is no specification. There is only behaviour, some of which is deliberate, some of which is a bug that downstream processes have quietly depended on for fifteen years.

So we did not replace it. We wrapped it.

An adapter layer sat in front of the mainframe, exposing a modern interface while the legacy system remained authoritative. New services talked to the adapter. Nothing behind it changed. This bought the single most valuable thing in a migration: the ability to move one capability at a time and stop at any point without being stranded.

Establish what "correct" means before changing anything

Before migrating a single capability we built continuous reconciliation: the old system and the new one processed the same inputs, and a job compared every resulting balance.

For six weeks this ran with the new system handling nothing real. It found eleven discrepancies. Nine were bugs in our implementation. Two were behaviours in the legacy system that were technically wrong but that downstream reporting had been built to expect.

Those two are the reason this approach matters. Rewriting from a specification would have "fixed" them and broken the monthly regulatory report in a way nobody would have noticed until the quarter closed.

Rehearse the cutover until it is boring

We ran seven full dry runs against production-shaped data. Each one: migrate, verify, roll back, and write down what went wrong.

The first took eleven hours and failed. The seventh took ninety minutes and did not.

The value was not the timing. It was that by the seventh rehearsal the runbook had been corrected by reality seven times, and every person involved had already done their part several times. On the real weekend nobody was improvising.

What we would tell anyone doing this

  • Wrap before you replace. Optionality is worth more than elegance.
  • Reconcile continuously, from before you need it. You cannot migrate what you cannot verify.
  • Treat data migration as its own workstream, with profiling, cleansing rules and repeatable dry runs. It is not a task for the final week.
  • Rehearse with rollback every time. A rollback you have never tested is a hope, not a plan.
  • Expect legacy bugs to be load-bearing. Ask before you fix them.

The migration weekend itself was uneventful. Someone brought pastries and we mostly watched dashboards. That is what success looks like: the interesting work had all happened in the preceding four months.

LegacyMigrationFinTech

Start the conversation

Tell us what you want to build.
We'll tell you how we'd build it.

Six questions gets you a recommended package, an indicative timeline and a technology plan. No sales call needed to get a useful answer.

  • Reply within 4 business hours
  • No cost, no obligation
  • NDA on request before you share anything