Skip to content
Imran Ramzan

# blog

Migrating Data Centres to AWS, Part 3: Execution, Hidden Wins, and Leaving the Client Self-Sufficient

28 Jul 2026
Migrating Data Centres to AWS, Part 3: Execution, Hidden Wins, and Leaving the Client Self-Sufficient

This is the final part of a series on running AWS MAP migrations. Part 1 covered discovery and the Assess phase; Part 2 covered landing zones, migration treatments, Microsoft workloads, and wave planning.

This article is about the Migrate & Modernize phase — and about the two things I believe actually determine whether a migration was worth doing: the benefits nobody wrote in the business case, and whether the client can run the platform themselves afterwards.

Execution is a rhythm, not an event

By the time you’re executing waves, the interesting decisions have mostly been made. What execution demands is rhythm and discipline: replication running days or weeks ahead of each cutover, cutover rehearsals for anything business-critical, a runbook that gets sharper with every wave, and honest go/no-go calls.

The operational reality is that plans move constantly. A vendor misses a date, a test surfaces a dependency that discovery didn’t catch, a business unit requests a freeze. This is exactly why we invested in wave-planning tooling wired into AWS Migration Hub — when the plan is a living system rather than a spreadsheet, re-sequencing a wave is a Tuesday afternoon, not a steering-committee crisis. Track everything, expect to re-plan, and treat each completed wave as input for improving the next one. The tenth wave should run dramatically smoother than the first, and if it doesn’t, the programme isn’t learning.

The other execution habit worth naming: retire aggressively as you go. Every cutover strands infrastructure on the on-premise side — the source VM, its backup jobs, its monitoring agents, its row in someone’s capacity plan. Decommissioning is unglamorous, and it’s also where a large slice of the promised savings physically live. Programmes that defer cleanup to “the end” discover that the end never quite arrives.

“It worked on-premise”: the network lockdown problem

There’s one category of cutover issue that deserves its own section, because it appeared on every programme and blindsided teams every time: network rules.

On-premise networks are, almost universally, far more permissive than anyone admits. Applications that had been talking to each other for a decade were doing so across flat VLANs and generous firewall rules that nobody had audited in years. Things “just worked” — which really meant nobody knew why they worked.

AWS best practice takes the opposite stance: security groups and NACLs locked down to exactly what needs to be open, and nothing more. The right stance, without question — but it collides head-on with an uncomfortable truth from the discovery phase: for a large share of the estate, nobody could tell you the complete set of ports an application actually required. Application owners knew the headline port; they didn’t know about the licensing callback, the odd management agent, or the batch job that connects somewhere at 2 a.m. on the last day of the month. Discovery dependency data got us most of the way, but “most of the way” still means broken applications after cutover.

Debugging with facts, not guesswork

Diagram showing a rejected connection at a security group gate, diagnosed using VPC Flow Logs to identify the missing rule

The tool that turned this from days of firefighting into minutes of diagnosis was VPC Flow Logs paired with CloudWatch Logs Insights.

With flow logs enabled on the migration VPCs, every accepted and rejected connection is recorded. When an application misbehaved post-cutover, the workflow was simple: query the flow logs filtered to REJECT records for that instance’s network interface.

-- CloudWatch Logs Insights query to find blocked connections instantly
fields @timestamp, srcAddr, dstAddr, srcPort, dstPort, protocol
| filter action = 'REJECT' and dstAddr = '10.100.4.25'
| sort @timestamp desc
| limit 20

The ACCEPT records were just as valuable in the other direction: before tightening rules further, you could verify from real traffic exactly what a workload used, and lock down with evidence rather than hope.

We eventually made this standard practice rather than incident response: flow logs on from day one of each wave, a saved set of Logs Insights queries in the runbook, and a rule that no post-cutover network fault gets debugged any other way. It’s a small operational habit that repaid itself on every single wave — and it left the client with something on-premise never gave them: a network where every open port can be justified from observed traffic.

Build it in code from wave one: GitLab, Terraform, and pipeline discipline

The last piece of execution machinery worth describing is the delivery toolchain itself, because it quietly determines whether a migration produces a well-governed platform or a fragile, ClickOps estate running on premium cloud rates.

The rule we held from day one: everything is Terraform. The landing zone, the networking, the security groups, the per-workload infrastructure each wave stamps out — all of it defined in code, none of it clicked together in the console. Once the first few waves establish reusable modules for the common patterns, migration stops being bespoke engineering and starts being a factory: each new wave largely instantiates known-good building blocks.

Pipeline diagram showing merge request, plan, approval, and apply stages

GitLab tied it together. Every infrastructure change was a merge request; the pipeline ran terraform plan and posted the output as the review artifact, so reviewers approved a concrete diff of what would change, not a description of intent. Apply ran on merge, behind approval gates for the environments that warranted them. No out-of-band changes, full history in Git, and every wave’s infrastructure reproducible from the repository.

There was a second-order benefit to all this discipline: the client’s engineers were in those merge requests from the beginning — first reviewing, then authoring. The toolchain wasn’t just how we delivered the migration. It was the classroom.

The benefits nobody put in the business case

Migration business cases are usually written in the language of cost: hardware avoided, data centre contracts exited, licensing rationalised. All real. But on every programme I delivered, somewhere around the halfway mark, the client’s engineers would discover a set of advantages nobody had priced in — and those often ended up mattering more.

Iceberg diagram showing hardware and licensing savings above the waterline, and infrastructure as code, observability, and team reallocation as larger hidden benefits below

Infrastructure as code is the big one — and it arrives as a side effect of the delivery toolchain described above. On-premise, infrastructure changes meant tickets, procurement, and waiting. Post-migration, the client inherits an estate where environments are reproducible artifacts and every change is a reviewed merge request. Teams that had never version-controlled infrastructure were suddenly reviewing infrastructure changes in pull requests — and that single shift dragged deployment practices, testing discipline, and documentation quality upward with it.

Observability follows the same arc. Estates that had been monitored through an ageing SCOM deployment and tribal knowledge landed in an environment where metrics, logs, and dashboards were native, uniform, and available to application teams rather than gatekept by an infrastructure function. Several teams understood their own applications’ behaviour properly for the first time because of the migration.

And then there’s human reallocation, which is the most underrated benefit of all. A meaningful fraction of an on-premise infrastructure team’s calendar goes to keeping physical reality alive: hardware failures, firmware, storage capacity, power and cooling, data-centre logistics. Post-migration, that time doesn’t disappear — it gets reinvested. The same engineers who were swapping failed disks are, a year later, building deployment pipelines and automating guardrails. The organisation didn’t just move its servers; it repurposed a chunk of its most experienced people onto work that compounds.

None of this happens automatically — a pure lift-and-shift estate left untouched will happily replicate old habits at cloud prices. But the migration creates the opening, and organisations that walk through it get far more value than the cost model ever promised.

The real success metric: can they run it without you?

Here’s an uncomfortable truth about consulting-led migrations: a programme can hit every milestone, cut over every wave, and still fail — if the client’s team can’t operate the platform after the consultants roll off.

The engagements that worked treated client enablement as a first-class workstream from day one, not a handover document at the end. Client engineers were embedded in the migration squads, doing the work alongside cloud specialists rather than observing it. They ran cutovers, wrote the runbooks, made the landing zone changes — with our people beside them early on, and progressively less beside them as waves went by. Formal training has its place, but the durable learning happened inside the programme itself: eighteen months of migrating your own estate is the best cloud education money can buy, provided the delivery model deliberately puts client hands on keyboards.

Diagram showing a consultant figure fading out on the left and a client engineer figure solidly present on the right, with a key transferring between them near a central platform console, illustrating client enablement and handover

The test I’d apply to any migration partner, and the one I applied to my own engagements: three months after the programme closes, is the client’s team confidently making changes to the platform, or are they afraid to touch it? The first outcome is a migration. The second is a dependency.

What I’d tell someone starting a MAP programme tomorrow

If I compress three years of MAP delivery into a handful of sentences, it’s these:

  1. Spend properly on discovery, because every downstream decision inherits its quality — and expect to find an estate messier and smaller-than-it-looks once the zombies and the operational scaffolding are stripped out.
  2. Write down why you’re migrating and let that answer settle every contentious decision that follows.
  3. Don’t rush the landing zone.
  4. Treat the Microsoft estate — licensing, SQL Server, Active Directory — as its own strategy.
  5. Build a wave plan that’s cheap to change, because it will change.
  6. Deliver everything as code from wave one — with locked, segmented Terraform state and a pipeline in front of every change.
  7. Expect the locked-down network to break things nobody predicted, and let VPC Flow Logs — not guesswork — tell you which rule is missing.
  8. Retire ruthlessly as you go.
  9. Measure success not by the last cutover, but by whether your own people own the platform when the dust settles.

The data centre exit is the headline. The organisation you become while doing it is the actual return.


Imran Ramzan | 21 years leading cloud, platform engineering, and AI platform strategy. Drawing on real-world leadership and cloud engagements in the UAE and globally, I write about the realities of scaling platforms for the AI era. While I use AI tools to help shape and polish this content, the technical insights and opinions are entirely my own.