Skip to content
Capability study7 min read

Replatforming without leaving two systems running

We rebuilt an entire product backend on a better foundation and switched the old one off. The switching-off is the part most migrations never finish.

Most replatforming projects do not fail loudly. They fail by stalling: the new system handles the straightforward cases, the old one keeps handling the awkward ones, and a year later both are still running. Everybody knows it is unfinished. Nobody has a safe moment to finish it.

We put ourselves through this on our own product. Mardio's backend needed to move onto a foundation that could carry multi-tenancy, a real permission model and an audit trail without fighting us. The rebuild itself was ordinary engineering. The interesting part was retiring what came before.

The constraint that shaped everything

We set one rule at the start: at no point could there be a question about which system held the truth for a given record. Not a convention, not a comment in a wiki — a rule the architecture enforced. That single constraint ruled out the comfortable option of letting both systems write to the same data for a while, which is exactly how migrations become permanent.

It made the early work harder and the ending possible, which is usually the trade worth taking.

How the migration was staged

  • One domain at a time — the new system took full ownership of a bounded area before anything else moved.
  • Reads first, then writes, so problems surfaced while they were still harmless.
  • A reconciliation job compared old and new continuously and alerted on any divergence.
  • Each stage had a rollback that was tested, not just written down.

Running both systems in parallel is not a hedge against a bad decision. It is how you produce evidence. The parallel period ends when the numbers agree on real data for long enough that nobody is nervous — and then it ends, rather than continuing indefinitely because stopping it was never anyone's job.

What the database had to enforce

The new foundation pushes tenant isolation down to the database rather than trusting every query to remember a filter. A query that forgets its scope returns nothing instead of returning another tenant's records. That is the difference between a bug and a breach, and it is not the kind of guarantee you can retrofit later by being careful.

A migration that leaves two systems running has not finished. It has just stopped being discussed.

What we would tell a client doing this

  • Decide what authoritative means for each record before writing code. Most integration pain is an unmade ownership decision.
  • Budget for decommissioning explicitly. If it is not in the plan it will not happen.
  • Find the undocumented behaviour early — it is where migrations come unstuck, and it is cheapest to discover during mapping.
  • Measure the parallel run. 'It seems fine' is not evidence anyone can act on.

None of this is exotic. It is mostly the discipline to treat the ending as part of the work rather than as cleanup that someone will get to later.

More writing

Read next.

Capability study

Payroll that knows the law

PF, ESI, professional tax, TDS and Form 16 encoded into an engine rather than reassembled by hand every month — and what that takes when the rules keep moving.

Capability study

Field operations that work without a signal

GPS-verified attendance and offline work orders for engineers who are regularly somewhere with no bars — and why offline-first changes the data model, not just the app.

Working on something like this?

Tell us what you're dealing with and we'll give you an honest view of what we would build.