Skip to content
Raghuraja — home

Modernization

How to Avoid Large-Scale Modernization and Migration Failures

Big modernization programs rarely fail because of the technology. They fail on vague outcomes, guessed inventories, late dependencies and unrehearsed cutovers. What I watch for — and the guardrails that work.

Raghuraja6 min read

There's a moment I've learned to recognize in large modernization programs. It usually arrives somewhere around month nine. The assessment is done, the new platform is up, the first applications have moved, and the status reports are green. Then someone asks a simple question in a steering meeting — "when do we switch the old data centre off?" — and the room goes quiet.

As a principal solution architect, I spend a lot of my time on programs at exactly that point. And the uncomfortable truth is that almost none of them are in trouble because of the technology. The cloud works. The containers work. The new framework works. What doesn't work is a set of decisions that were never made explicitly, or were made on guesses instead of evidence.

The good news is that these failures are predictable. They leave clues early. Here is what I look for, and what I put in place to stop them.

Learn from failures that were made public

Most failed migrations are never written up. A few are — usually because a regulator or auditor got involved — and they are worth reading slowly, because the lessons are rarely about code.

A UK retail bank, 2018. The bank moved millions of customer accounts from a legacy platform to a new one over a single weekend. For days afterwards, customers couldn't log in, saw other people's accounts, or couldn't make payments. The independent review that followed pointed at planning, governance and the oversight of a critical supplier — and, tellingly, at how testing was done, including testing on only one of two data centres. Regulators later fined the bank a combined £48.65 million. None of that is a technology choice. It is a set of decisions about evidence and readiness.

A US trading firm, 2012. A new release went to eight production servers. A technician missed one. That eighth server still carried code that had been dead for nearly a decade, and the new release reused a configuration flag that woke it up. In about 45 minutes the firm's system sent more than four million orders while trying to fill 212 customer orders, and lost more than $460 million. Internal systems had sent dozens of automated warning emails that morning. Nobody acted on them. The lesson I take from it: a deployment that can be partially applied, with no automated check that every node matches, is a migration risk — not just an operations one.

A government health insurance site, 2013. It launched on a fixed political date and largely fell over. The government auditor later found it had gone live without verification that it met its performance requirements, partly because performance reviews were pushed to the weeks before launch. A date won over the evidence.

Where programs go wrong, in the order they go wrong

  1. Name the outcome: Risk, cost or speed — with numbers, owners and a date.
  2. Inventory from evidence: Scan code, infra and traffic. Interviews confirm, not create.
  3. One path per app: Retire, rehost, upgrade, re-architect or replace — with a reason.
  4. Sequence by dependency: Shared libraries, data and identity first.
  5. Pilot something hard: Cover every path. Re-estimate from what you measured.
  6. Gate every release: Parity, performance, security, rollback — proven, not promised.
  7. Switch the old one off: Savings start on decommission day, not go-live day.
The guardrails I put in place, in the order a program meets them. Each one produces evidence the next depends on. Skip one, and it usually shows up two steps later as a stalled wave or a bad release.

1. Name the outcome, not the destination

"Move to the cloud" is a destination. An outcome sounds like: no unsupported runtimes on internet-facing systems by June, or cut run cost for this portfolio by a stated amount once the old estate is retired. It has a baseline, a target and a person who owns it.

I push hard on this in the first weeks, and it can feel pedantic. It isn't. Outcomes are how you say no to scope creep, and they are the only way a program ever gets to declare itself finished.

2. Build the inventory from evidence

The spreadsheet assembled from interviews is always wrong. Not because people are careless — because nobody knows every consumer of their service, or remembers the nightly job that drops a file on a share that three other systems read.

So I scan: repositories for frameworks, packages and APIs; infrastructure for what's actually running; telemetry for who really calls whom. Then the interviews add business context. The difference in quality is striking, and it changes the plan more often than people expect.

3. One path per application — and write down why

A single mandate for the whole estate — "lift and shift everything", or "rewrite on microservices" — is easy to announce and almost always wrong. Some applications should simply be retired. Some should be rehosted as they are. Some are good in-place upgrades. A few genuinely need re-architecture, and that should be argued case by case.

I make the classification rules explicit and record every override. If people keep overriding the rules, the rules are wrong — and that's useful to know early.

4. Let dependencies set the order

Waves often get ordered by whichever team volunteers first. That's how you end up with a wave that is "90% done" for three months, waiting on a shared library or a database that belongs to someone else.

My test for any proposed wave is simple: list everything it depends on that isn't in the wave. If that list has items nobody owns, the wave isn't ready.

5. Pilot something that can fail

If the pilot is the five easiest applications, the estimates will be fiction. I deliberately include one application everyone is nervous about: thin tests, a shared database, a strange integration. The pilot's job is to break the playbook while it's still cheap to fix it — and then the program re-estimates from what it measured, not from the business case.

6. Gate every release on evidence

This is the step I care most about, and it's the one the public failures above skipped. The team that migrated an application isn't the right party to declare it equivalent. Before go-live I want to see: behavior compared against the old system, performance within tolerance of a baseline captured before migration, clean security scans, health checks and telemetry wired up, and a rollback that has actually been exercised — not described in a document.

And then release progressively. A slice of traffic, a subset of users, one region. Big-bang weekends feel decisive; they are mostly just high-stakes.

7. The old system has to go

Data migration is where schedules slip quietly, so it gets its own plan and its own gates. And a migration is not done at go-live. It's done when the old system is switched off, the licences are cancelled and the hardware is released. Until then, you're paying for two estates.

What I put on the steering dashboard

Steering committees usually see activity: applications migrated, percent complete. Those numbers look healthy right until they don't. I ask for leading indicators instead:

IndicatorWhy it matters
First-time gate pass rateShows whether the playbook actually works
Incidents caused by migration, vs. baselineThe honest measure of risk
Classification overridesTells you when your rules are wrong
Days blocked by dependenciesShows sequencing problems early
Dual-running costWhat the delay is really costing

Before you commit the full budget

I ask seven questions. If any answer is "no", I'd rather fix that first than find out in month nine.

  1. Are the outcomes written down with baselines, targets and owners?
  2. Was the inventory generated from code, infrastructure and traffic?
  3. Does every application have a path — and a recorded reason?
  4. Is the wave order derived from dependencies?
  5. Did the pilot include something difficult, and were the estimates revised afterwards?
  6. Are release gates defined, and checked by someone other than the delivery team?
  7. Is switching off the old system part of "done"?

Modernization at scale is less about choosing the right technology than about making a long series of decisions in the right order, with the right evidence. The technology matters. The order and the evidence matter more.

If you'd like to see these ideas applied end to end, I've written up a reference architecture for modernizing a large .NET portfolio.


Sources for the public examples

Next conversation

Have a difficult architecture problem? Let's talk.

I'm interested in technical architecture challenges where the decisions matter and the engineering has to hold up in production.

Get in touch