A distribution company in Amman ran on a system written in 2009 by a developer who emigrated in 2014. Nobody knew how parts of it worked. It also processed every order the business took. That combination — critical and unknowable — is the hardest problem in enterprise software, and it is common.
Legacy migration done as a single switchover fails often enough that the pattern is well documented. Done in stages, it is unglamorous and it works.
Why the big-bang switch fails
Everything is replaced over one weekend. Monday arrives, something nobody anticipated does not work, and the business cannot operate. The old system has already been decommissioned or the data has moved past the point of return.
The failure is not usually technical. It is that fifteen years of accumulated special cases — the customer with the unusual credit terms, the product priced differently for one branch, the tax exception nobody documented — are invisible in the code and absent from every specification. You discover them in production, all at once, on the busiest day.
The strangler pattern
Named for a vine that grows around a tree and eventually replaces it. Instead of replacing the system, you replace one function at a time while the old system keeps running.
- Put a routing layer in front of the old system. Everything still goes through to the old code.
- Build one new module — reporting, say, since it is read-only and low risk.
- Point the router at the new module for that function only.
- Verify for a few weeks. If it is wrong, route back in minutes.
- Repeat with the next function.
Eventually the old system handles nothing and can be switched off without ceremony. It takes longer in total and each individual step is reversible, which is what makes it survivable.
Deal with data quality before anything else
Every legacy system contains data that is wrong in ways the business has adapted to. Duplicate customer records, products with two codes, addresses in a free-text field.
You cannot migrate this and fix it later. Migrate it and the new system inherits the problem, plus a new one: two systems now disagree.
Budget genuine time for cleaning. On a Jordanian dataset, expect to find:
- The same customer recorded three times with different spellings — Arabic and Latin transliterations of one name.
- Phone numbers in four formats.
- Addresses that only make sense to the driver who delivers there.
- Historic transactions with no matching customer record.
Clean in the old system if you can. Cleaning during migration means doing it under time pressure, which is when mistakes are made.
Run both, deliberately
For a defined period — usually a month — both systems process the same transactions and you compare outputs daily. It is duplicated effort and staff will complain, which is why it needs to be explained as a deliberate verification step with an end date.
What you are looking for is not whether the new system runs. It is whether it produces the same answers, including for the odd cases that only occur twice a month.
The rollback plan
Write it before cutover, on one page, and make sure someone other than the lead developer could execute it.
- What is the deadline for deciding to roll back?
- Who makes that call, and who deputises if they are unreachable?
- What happens to transactions entered into the new system in the meantime?
- How long does reverting take, tested rather than estimated?
Most rollback plans are never used. The ones that exist tend not to be needed, because writing them exposes the gaps that would have caused the failure.
Keep the old system readable
Do not delete it. Keep a read-only copy available for at least a year — ideally two, since audits and disputes surface late.
Storage is cheap. Being unable to answer a question about a 2022 transaction because the system that held it was decommissioned is not.
How long it takes
Longer than the estimate. For a mid-sized business system with fifteen years of history, plan nine to eighteen months for a staged legacy migration, with genuine value delivered from month three rather than at the end.
That is slower than a rewrite promises and faster than a rewrite delivers.