genaipros← The path
Line D · CloudC9 · Migration & Modernization
Cloud for GenAI · Line D · C09

Migration & Modernization

3 sessions · AWS | Azure | GCP
00Stage map
The framing for everything that follows

You don't lift-and-shift your way to cloud-native.

Every previous stage taught you how to build in the cloud. This one is about everything that already exists somewhere else — and the uncomfortable fact that moving it and improving it are two different projects that people constantly confuse for one.

Three ideas hold this stage together. First: the R's are a spectrum of effort versus payoff, and you choose one per application, never per portfolio. A realistic enterprise migration plan has five different R's in it. Second: incremental beats big-bang. The villain of this stage is the freeze-everything-and-cut-over-once rewrite, and its lazy twin — lift-and-shift-then-stop, which relocates your technical debt to a more expensive address and calls it transformation. Third: assess before you move. Dependencies, data gravity, and cutover risk decide the sequence. A migration is a wave plan, not an event.

What "cloud-native" means here

Stages 2–8 are the destination. Identity, network, compute, storage, application patterns, reliability, governance and cost — the landing zone you learned to build is the thing you migrate into. C9 never re-teaches the target. It teaches how to get things there without breaking them, and how to reshape them once they arrive.

01The signature
diagram

The 7 R's, plotted honestly

Most diagrams of the R's are a list. A list hides the only thing that matters: each R buys you a different amount of cloud benefit for a different amount of effort, and the curve is not linear. Click any rung to see what it means, what it costs you, and a workload that belongs there.

Interactive — click a rung on the axis Effort · cost · risk · time ⟶ Cloud benefit ⟶ none full × RETIRE Reporting portal, 12 users, dead RETAIN HSM-bound payments switch RELOCATE 400-VM vSphere estate, one move REHOST Internal SSO broker on 3 VMs REPURCHASE Home-grown CRM → SaaS REPLATFORM Stateless API → containers + managed DB REFACTOR Ledger monolith → services ← decisions not to move move as-is, change nothing change the platform, not the code

Select a rung above to read its definition, cost profile, and the trap that comes with it.

Read it this way: the dotted curve is benefit, and it stays flat through rehost. Rehosting is cheap and fast and it buys you almost nothing architecturally — its value is that it gets you out of a data centre and onto a bill you can now optimise. The steep part of the curve only starts once you begin changing the application. Everything to the left of replatform is logistics; everything to the right is engineering.
Where the R's came from — and why the count keeps changing

Gartner published 5 R's around 2010–2011 (rehost, refactor, revise, rebuild, replace). Stephen Orban condensed and renamed them into 6 Strategies for Migrating Applications to the Cloud at AWS in 2016 — the "6 R's" the patterns catalog teaches. AWS later added a seventh, relocate, after VMware Cloud on AWS launched, to cover hypervisor-level moves that fit none of the other six. AWS Prescriptive Guidance documents seven today. Some AWS mainframe material now references an "8 R" set. Don't memorise the number. Memorise the axis: how much do you change, and what do you get for it.

02What you'll
be able to do

End state for this stage

  1. 01Pick the right R for a given application, and defend the choice against someone who wants to refactor everything and someone who wants to rehost everything.
  2. 02Take a portfolio, map its dependencies, and sequence it into waves that respect coupling and data gravity — including knowing which apps must move in the same wave.
  3. 03Apply the strangler-fig pattern to a monolith so that there is a working system and a cheap rollback at every single step.
  4. 04Do the data-gravity arithmetic on paper: how long a transfer takes on a given link, what it costs in egress, and the crossover where a physical appliance beats the network.
  5. 05Compare AWS, Azure and GCP migration tooling and hybrid platforms, and know which product names in the materials are already dead.
  6. 06Explain precisely why your own stateless, externalised-state model-serving stack is a genuinely easy migration — and where its real gravity actually sits.
03How the
sessions build

Three sessions, one arc

S1 gives you the decision framework with no products in it. S2 gives you the one modernization pattern that actually works at scale, also with no products in it. Only S3 introduces tooling — deliberately last, because a tool cannot rescue a bad sequencing decision.

Session 1 · concept-first DECIDE Which R per app. Dependencies, data gravity, waves, cutover. Session 2 · concept-first RESHAPE Strangler fig. Facade, ACL, dual-write, backfill, decommission. Session 3 · three clouds MOVE VM / DB / bulk-data services and hybrid control planes, compared. the R you chose in S1 determines which tool in S3 is even applicable Decide before you reshape · reshape before you shop for tools
Sequencing note: S1 and S2 are marked concept-only. There is no product to buy for "choosing an R" and no product to buy for "strangler fig" — they are decisions and patterns. S1 does get one honest three-cloud row (the adoption frameworks), and S2 gets a short note on where each vendor documents the pattern. The real three-cloud comparison lives in S3.
Decision tree · guard clauses
Is this a migration problem or a modernization problem?
The question people skip, which is why they buy tools for problems tools don't solve. Answer in order. "No" falls through. The first "yes" exits right. Bottom-left is the default.
Q1Is the application already running in the cloud, and the complaint is about how it's built rather than where it lives?
yes ⟶
Pure modernizationNothing needs to move. Go straight to Session 2 — this is a strangler-fig problem and no migration tool will help.
no ↓
Q2Is there a fixed external date — a lease, a licence, an acquisition — that the move must hit?
yes ⟶
Migration first, hard stopSession 1 for sequencing, Session 3 for the tools. Do not attempt modernization inside the deadline; source it as funded follow-up work.
no ↓
Q3Is the driver a specific capability that only exists at the destination — managed GPUs, a data platform, a region you need?
yes ⟶
Targeted migrationMove only what needs to be near that capability. Session 1's data-gravity section decides what has to follow it and what can stay.
no ↓
Q4Is the real constraint the data — too large, too regulated, or too latency-bound to move at all?
yes ⟶
Hybrid, not migrationPut compute next to the data instead of the reverse. Session 3's hybrid section is where this lives.
no ↓
Default — bottom left Both, sequenced — migrate, then modernize This is the normal case and the whole reason the stage runs in this order. Move it as-is to get out of where it is (S1 and S3), then reshape it incrementally once it's stable (S2). The failure mode is doing them simultaneously: modernizing during a migration is how deadlines slip and how rollbacks become impossible, because you can no longer tell whether a defect came from the move or from the change.
04Source
corrections

Before we start: your reading list was wrong in three places

Three of your assumptions need correcting, and one of them changes the plan for S3.

Confirmed ✓
Cloud_Patterns.pdf

the cloud application patterns catalog, a cloud patterns catalog . §9 is "Application Migration and Modernization." §10 is "Strangling Monoliths." Exactly as you had it. This material is the spine for S1 and S2 and it earns that role.

Correction 1
AWS notes does have a migration section

AWS guidance's guide has §26 "Migration Strategies and Tools" and §27 "Modernizing Existing Architectures." §26 covers a six-phase migration process, the 6 R's, Migration Hub, Application Discovery Service and DMS. So we do use the source for S3 — but see correction 3, because it is badly out of date on tooling.

Correction 2
GCP §14 is not migration

In GCP guidance's a leading GCP architecture reference, §14 is "Google Cloud Operations Suite" and §15 is "Agile, DevOps, SRE, SDLC…". There is no dedicated migration or hybrid section at all. The material is scattered: hybrid-cloud types in §1, Storage Transfer Service and Transfer Appliance in §3, Cloud VPN and Cloud Interconnect in §4, and the Dress4Win migration case study in §15. Anthos gets two passing mentions and no treatment. The material promises hybrid offerings "later in this material" and never delivers a section on them.

Correction 3
Azure.pdf confirmed — and all three are stale on tooling

Mastering Azure (vendor guidance et al.) has 16 section, none on migration; closest are §3–4 networking and §16 governance. As you expected, Azure Migrate / DMS / Arc come from docs. More importantly: the AWS source teaches Server Migration Service and CloudEndure as the primary rehost tools. Both are retired. It never mentions MGN. Full staleness audit is in S3.

Consequence for S3

Because no source has current migration tooling, every product name, capability and price in Session 3 is grounded in vendor documentation and news from the last six months, not the materials. Each table flags what the materials say versus what is true now, with links. Two of the changes landed within the last two weeks and one within the last day.

05Vocabulary
you'll need

Terms defined once, used throughout

Every one of these is defined properly at first use inside its session. This is the index, not the teaching.

Landing zone
The pre-built, governed destination from C1 — org hierarchy, accounts/subscriptions/projects, guardrails, networking, identity — ready before the first workload arrives. Migrating into an ungoverned account is how you get 400 untagged VMs.
Data gravity
Large datasets are slow and expensive to move, so compute tends to migrate toward the data rather than the reverse. Coined by the data-gravity essay in 2010. It is the single biggest constraint on wave sequencing.
Wave / move group
A batch of applications migrated together in one window because they share dependencies, data, or a cutover. The unit of planning in every real migration.
Cutover
The moment production traffic starts hitting the new target and stops hitting the old source. Everything before it is reversible; everything after it costs something to undo.
Rehost
Move it, change nothing. Also "lift and shift."
Relocate
Move the hypervisor estate wholesale — no OS change, no app change, no re-IP.
Replatform
Move it and swap components for managed services without touching application code. Also "lift, tinker and shift."
Repurchase
Stop running it; buy the SaaS equivalent.
Refactor
Change the application's architecture to use the cloud properly. The only R that fixes technical debt.
Retain / Retire
Decide not to move it, either because you can't (retain) or because nobody is using it (retire).
Strangler fig
Grow a new system around the old one, redirect one slice of traffic at a time, and remove the old code as each slice goes live. Named in the refactoring literature after the strangler vine.
Anti-corruption layer
A translation boundary that stops the legacy system's data shapes and vocabulary from leaking into the new service's domain model. Abbreviated ACL — nothing to do with access control lists.
Dual-write
A transition period where writes go to both the old and new data stores so either can serve as source of truth.
Backfill
Copying the historical rows the dual-write never saw, so the new store has full history and not just what happened since Tuesday.
Hybrid
On-premises and cloud running as one connected estate. Distinct from multi-cloud, which is two or more public clouds.
S1·1Why this
session exists
Session 1 · Migration strategy, vendor-neutral · concept-only

Two hundred applications, one team, and a data centre lease that expires in fourteen months

Nobody's migration fails because they picked the wrong instance type. Migrations fail because somebody treated a portfolio as if it were one thing.

Here is the actual situation, every time. There is a list of applications. Some are load-bearing and some are ghosts. Nobody has a complete dependency map, because the map lives in three people's heads and one of them left. There is a deadline that comes from a lease, a licence renewal, or an acquisition — not from engineering. And there is enormous pressure to answer one question: "so, how long will it take?"

The two failure modes are symmetrical. The refactor-everything plan is architecturally correct and finishes after the deadline, if ever. The lift-and-shift-everything plan finishes on time and delivers a data centre you now rent by the hour, with the same technical debt and a worse bill. Both come from the same mistake: applying one strategy to a whole portfolio.

A real portfolio is not homogeneous — one strategy cannot fit it how coupled ⟶ how often it changes ⟶ the monolith the switch ghosts One strategy for all of it produces one of two outcomes refactor everything Correct. Unfundable. Misses the lease date. rehost everything On time. Same debt, now billed hourly. what actually works Retire the ghosts. Rehost the boring middle to hit the date. Spend your entire refactor budget on the monolith. Retain the switch.
The portfolio is the unit of planning; the application is the unit of decision. You produce one plan and dozens of different decisions. The skill this session teaches is making those decisions defensibly and then ordering them.
Session type

This session is concept-only. There is no product called "wave planning" you can go and buy — though as of this year Azure Migrate has shipped a preview feature with exactly that name, which is a nice sign that the vendors have finally caught up with the practice. The one genuine three-cloud mapping here is the adoption frameworks, and it's a short table.

S1·2Core concepts
▸ the seven R's

The seven R's, one at a time

Pass 1 · intuition

You are moving house, and every object in the house gets its own decision. The sofa you like goes on the van as-is (rehost). The old fridge stays behind because the new kitchen has one built in (repurchase). The boxes of paperwork from 2009 go in the skip (retire). The piano stays because the new place has no ground-floor room and moving it costs more than it's worth (retain). The flat-pack shelving gets rebuilt to fit the new alcove (replatform). And the kitchen itself — the thing you actually use every day, that has annoyed you for a decade — gets redesigned from scratch, which is why you do exactly one of those (refactor).

Nobody sensibly says "I will apply the same treatment to every object in my house."

Pass 2 · mechanism

Mechanically, the R's differ along three independent axes that the patterns catalog separates cleanly, and which are worth holding apart in your head:

  • Platform — where it runs: traditional IT or cloud. Changing this is migration.
  • Architecture — how it's structured: unstructured monolith, modular monolith, or distributed. Changing this is modernization.
  • Packaging — how it's deployed: bare metal, virtual server, or container. Changing this is also modernization, and it's independent of architecture — you can containerise a big ball of mud, and people do.

These vary independently, which is the whole reason the R's exist as separate labels. Rehost changes platform only. Replatform changes platform and packaging. Refactor changes architecture, and usually all three.

Expand each R below for its definition, what it actually costs, and the specific trap that comes with it.

Retire  Turn it off. Nobody will notice.

What it is: the application runs, but nobody meaningfully uses it. Shut it down instead of moving it.

Cost: near zero to execute, but real effort to prove — you need usage telemetry, a communication window, and an archived copy of the data for whatever your retention policy says.

Why it goes first: AWS's own guidance recommends retiring before waves begin, because every retirement shrinks the portfolio, removes a node from the dependency graph, and improves the business case. In large estates a meaningful fraction of applications turn out to be retireable. It is the cheapest win in the entire programme.

The trap: "nobody uses it" is a claim, not a fact. The classic disaster is retiring a service that one nightly batch job calls once a month. Turn it off with a dark period first — block traffic, keep it running, wait a full business cycle (usually a quarter, to catch month-end and quarter-end), then delete.

Retain  Leave it where it is. On purpose.

What it is: a deliberate, documented decision not to move — with a review date.

Legitimate reasons: data sovereignty or residency rules; a hardware dependency the cloud can't reproduce (an HSM, a serial-attached instrument, a dongle); a vendor licence that doesn't permit cloud hosting; latency to a physical process; or an application so fragile that the risk of touching it outweighs any benefit.

Cost: zero to execute, but it is not free — you keep the data centre, the hardware refresh cycle, and the operational skills for it. A retain decision on one application can keep an entire facility open, which is why one retained app can be more expensive than migrating fifty.

The trap: "retain" quietly becoming "we forgot." A retain decision without a review date is not a decision, it's an omission. Also: check whether retaining it forces hybrid connectivity — a private link back to the data centre — because that cost belongs on the retain decision's ledger, not on the network team's.

Relocate  Move the hypervisor, not the machines.

What it is: hypervisor-level lift and shift. Your vSphere estate moves onto a managed VMware-compatible service in the cloud. No OS change, no application change, no re-IP, and your team keeps using vCenter and its existing runbooks and automation.

Cost: the lowest per-VM effort of any R that actually moves something, but it carries a licensing and capacity commitment, and the hosts are chunky — you buy hosts, not instances, so it only makes economic sense above a certain estate size.

Why it's the seventh R: it genuinely didn't fit anywhere. It isn't rehost (rehost converts each machine into a native cloud instance); it isn't replatform (nothing is swapped for a managed service). AWS added it after VMware Cloud on AWS launched.

The trap: relocate delivers speed and continuity, and almost no cloud benefit. It is the most comfortable R and therefore the easiest one to stop at. Treat it as a staging position with a follow-on plan, not a destination.

Rehost  Lift and shift. The workhorse.

What it is: recreate an equivalent compute environment in the cloud and put the application on it, changing as little as possible. The patterns catalog gives four concrete steps that are worth memorising because they are the whole job: duplicate the compute environment (same OS family and version); duplicate the network environment (the VPC/VNet stands in for the old LAN — many clouds even let you bring your own IP ranges); connect to any on-prem resources that can't move yet (SSO, monitoring, systems of record) over VPN or a dedicated link; and resolve data dependencies — either move the database or reach back to it.

Cost: lowest risk, fastest schedule, and by far the most common choice at scale. AWS field guidance notes that in large legacy migrations organisations often rehost 70% or more of applications, because speed and low disruption outweigh optimisation early on.

The trap — and this is the important one: rehosting moves your technical debt with the application. Worse, it converts capital expenditure into operating expenditure without any of the agility that's supposed to justify it: you're using the same processes, the same tools, and the same deployment cadence, just on someone else's hardware. If you rehost and stop, you have made your architecture worse and your bill more visible. The rehost is only defensible as step one of a two-step plan.

Repurchase  Stop running it; buy it.

What it is: replace a custom or licensed on-prem application with a SaaS product. CRM, ERP, HR, ticketing, expense management — anything where your custom version is not a competitive advantage.

Cost: the migration engineering is small; the organisational cost is large. You are changing how people work, migrating data into someone else's schema, rebuilding integrations, and renegotiating a licence. Budget for change management, not for servers.

The trap: repurchase has the widest blast radius of any R on other applications. Every system that integrated with the old app now integrates with a different API, a different identity model, and a different data shape. In a dependency graph, repurchasing a node with five inbound edges means five more pieces of work you didn't plan. Check the in-degree of a node before you repurchase it.

Replatform  Lift, tinker, and shift.

What it is: move the application and swap infrastructure components for managed equivalents — without changing application code or architecture. Self-managed PostgreSQL becomes a managed database service. A hand-rolled load balancer becomes the platform's. Files on an NFS mount become object storage. The app still thinks it's the same app.

Cost: moderate and, crucially, predictable. Each swap is bounded and independently testable. This is the best effort-to-benefit ratio on the whole curve, which is why it sits where it does in the Tab 0 diagram.

Replatform versus refactor — the line that people constantly blur: replatform changes what the application runs on; refactor changes what the application is. Containerising a monolith is a replatform: the code and architecture are untouched, the packaging changed. Splitting that monolith into services is a refactor. If you find yourself opening a source file to change business logic, you have crossed the line.

The trap: managed services have opinions. A managed database may not allow the extension, the superuser grant, the stored procedure, or the exact minor version your application assumed. Each of those is a small code change, and small code changes are how a replatform quietly becomes a refactor with no budget line.

Refactor  Change what it is.

What it is: restructure the application's architecture to actually use the cloud — decompose the monolith, externalise state, make it replicable and stateless, adopt managed backing services. This is the only R that repays technical debt rather than relocating it.

Cost: the highest by a wide margin, and the least predictable, because you are discovering undocumented behaviour as you go. It also requires operational readiness you may not have: a delivery pipeline, independent deploys, distributed tracing, and people who have done it before.

When it's worth it: the application changes often, the change is painful, and the pain is costing the business measurably. If an application is stable and rarely touched, refactoring it is a hobby.

The trap: refactor shades into rebuild without anyone declaring it. The patterns catalog is blunt here — an application can be so encrusted that "refactoring" effectively becomes replacing it, and if replacement is genuinely necessary it is easier to build fresh than to keep pretending. Say which one you're doing, out loud, before you start. And when you do refactor, do it incrementally: that's Session 2.

Pass 3 · trade-offs and numbers

Distribution. A common shape for an enterprise portfolio, reported by practitioners running AWS Migration Acceleration Program engagements, is roughly 40–50% rehost, 20–30% replatform, 10–15% refactor, and the remainder split across retire, retain, repurchase and relocate. If your plan is 80% refactor, you have written a wish; if it's 100% rehost, you have written a relocation invoice.

The R is not permanent. The most useful mental model is that R's compose over time: rehost now to hit the lease date, replatform in year two once the estate is stable, refactor the two applications that actually justify it in year three. AWS Prescriptive Guidance says this explicitly for large migrations — refactor is not recommended during a large migration precisely because it's hard to manage across many applications at once; rehost, relocate or replatform, then modernise afterwards.

Where it breaks. Two failure signatures worth recognising:

  • The R was chosen by the wrong person. Architects pick refactor; finance picks rehost; the app owner picks retain. The choice needs all three inputs, and the tiebreaker should be the application's change frequency, because that's what determines whether architectural improvement pays back.
  • The R was chosen once and never revisited. Discovery changes the picture. An app you scoped as rehost turns out to depend on a physical licence dongle; that's a retain, and it may drag three dependents with it.

The one honest three-cloud mapping in this session. There is no product for "choose an R," but all three vendors publish a structured adoption/migration framework, and they genuinely differ in emphasis:

Vendor frameworkAWSAzureGoogle Cloud
Named framework AWS Cloud Adoption Framework (CAF) + Migration Acceleration Program (MAP) Cloud Adoption Framework for Azure, with a distinct Migrate methodology Google Cloud Adoption Framework, plus the "Migration to Google Cloud" guide series
Phase model Assess → Mobilize → Migrate & Modernize (the AWS source teaches a six-phase variant adding Operate and Optimize) Strategy → Plan → Ready → Adopt (Migrate / Innovate) → Govern → Manage Assess → Plan → Deploy → Optimize
Strategy vocabulary The 7 R's, formally documented in Prescriptive Guidance Rehost / refactor / rearchitect / rebuild / replace (five, Gartner-derived) Lift-and-shift / improve-and-move / rip-and-replace (three)
What it's actually good for Portfolio mechanics and large-scale execution. The most detailed on wave planning. Organisational readiness and governance. Strongest on landing-zone design. Concise and architecture-led. Fewest ceremonies, least prescriptive on programme management.

Sources: AWS Prescriptive Guidance — migration strategies Microsoft Cloud Adoption Framework Google Cloud — Migration to Google Cloud

Decision tree · guard clauses
Which R for this application?
Answer in order. "No" falls through to the next question. The first "yes" exits right. If you reach the bottom, take the default.
Q1Has it had no real users or no inbound calls for a full business cycle — including month-end and quarter-end?
yes ⟶
RetireDark-period it first, archive the data, then delete. Do this before wave planning.
no ↓
Q2Is it blocked from moving — sovereignty, a licence that forbids cloud, a physical hardware dependency, or a latency tie to a physical process?
yes ⟶
RetainWith a written review date and the hybrid-link cost charged to this decision.
no ↓
Q3Is this a commodity capability where a mature SaaS product already does the job, and you can absorb the integration rework on its dependents?
yes ⟶
RepurchaseCount the inbound dependencies first — each one is unplanned integration work.
no ↓
Q4Is it part of a large virtualised estate that is moving as a single block, where keeping vCenter and existing runbooks is worth more than native instances?
yes ⟶
RelocateHypervisor-level. Staging position only — write the follow-on plan now.
no ↓
Q5Is the deadline externally fixed (lease, licence, acquisition) with no room to change the application before it?
yes ⟶
RehostMove it as-is. Source the modernization work as a funded follow-up, not an intention.
no ↓
Q6Can you get most of the benefit by swapping infrastructure components for managed services without opening a source file?
yes ⟶
ReplatformBest benefit-per-unit-effort on the curve. Verify the managed service's constraints early.
no ↓
Default — bottom left Refactor You reach this only when the app is strategic, changes frequently, and the pain of changing it is measurable. Refactor incrementally using the strangler-fig pattern (Session 2) — never as a big-bang rewrite. And if you can't fund it this year, the honest answer is rehost now, refactor later: say so explicitly rather than letting "refactor" sit on a plan as a placeholder for "we haven't decided."
S1·3Core concepts
▸ assessment

Assessment: you cannot sequence what you haven't mapped

Pass 1 · intuition

Before movers arrive, somebody walks through the house and writes on each box which room it goes to, whether it's fragile, and what it's connected to. Skip that and the movers make the decisions for you — badly, at speed, at 6pm.

Assessment is that walk-through. Its output is not a spreadsheet of servers. Its output is a dependency graph with an R written on every node.

Pass 2 · mechanism

Assessment collects four things, in this order:

1 · Inventory
What exists

Servers, VMs, their OS versions, CPU/memory/disk, and — critically — utilisation over time, not a point-in-time snapshot. Right-sizing off peak-hour numbers is how you overspend by 40%.

2 · Dependencies
What talks to what

Network flow data over weeks. Two boxes exchanging packets on port 1521 is a dependency even if no human knows about it. This is where the ghosts and the surprise couplings surface.

3 · Data
How heavy, how hot

Dataset sizes, change rates, and residency constraints. Size sets transfer time; change rate sets whether you can do a one-shot copy or need continuous replication.

4 · Constraints
What forbids what

Licences, compliance boundaries, change-freeze windows, and the maximum tolerable downtime per application. Downtime tolerance is the number that decides your cutover technique.

Three kinds of dependency edge behave very differently, and mixing them up is the single most common wave-planning error:

Not all dependency edges are equal A · API call — loose app A app B Survives being split across the gap — add latency and a private link, and they can live in different waves. B · Shared database — welded app A app B one schema Cannot be split. A and B are one move group, full stop. C · Batch file drop — invisible app A app B /share Fires at 02:00 monthly. Flow capture over one week never sees it. Capture for a full cycle, and read the crontabs.
Rule: an API edge tolerates a wave boundary. A shared-schema edge does not — those applications are one move group whether you like it or not. A batch edge is the one that bites, because discovery tooling running for a fortnight simply will not observe a monthly job.
Pass 3 · trade-offs

Agent versus agentless discovery. Agentless collectors read from the hypervisor or the network and give you inventory and coarse flows with no footprint on the guests. Agents give you process-level detail — which process opened that socket — which is what you actually need to attribute a flow to an application. Agents also require change approval on hundreds of production servers, which in a regulated environment is a months-long conversation. The usual answer is agentless across the estate, agents on the twenty machines you're most worried about.

How long to collect. Two weeks is the common default and it is too short. It catches daily and weekly patterns and misses everything monthly, quarterly, and annual. If your deadline permits, collect for a full quarter. If it doesn't, compensate by reading scheduler configuration directly — crontabs, scheduled tasks, job-scheduler definitions — because those declare the periodic dependencies that flow capture will miss.

The thing assessment can't tell you. Tooling reports what the estate does. It cannot tell you what the business needs, what the maximum tolerable downtime is, or whether an application is strategic. Those come from humans, and they are the inputs that decide the R.

S1·4Core concepts
▸ data gravity

Data gravity: the force that reorders your plan

Pass 1 · intuition

Moving a person is easy. Moving a person's library of ten thousand sources is not. So when someone with a huge library relocates, the materials go first and everything else arranges itself around when they arrive — and if the materials genuinely can't move, the person ends up living near the materials.

That's data gravity, a term coined in 2010. Large datasets are slow and expensive to move, so applications and services accumulate around them rather than the reverse. Mass attracts.

Pass 2 · mechanism

Gravity has three separate components, and they don't always point the same way:

Three forces, one direction of pull 8 TB dataset batch job reporting the app 1 · Transfer time Bytes ÷ usable bandwidth. Not negotiable, not parallelisable beyond the link. This sets the earliest possible wave date. 2 · Transfer cost Egress is charged on the way out; ingress is free everywhere. Cloud-to-cloud moves pay the source's exit toll, not the destination's — a genuinely asymmetric market. 3 · Latency coupling Once the data is somewhere, anything chatty with it must be nearby. Split a chatty app from its database across the WAN and each page render turns 200 queries into 200 round trips. Force 3 is why "just leave the DB on-prem for now" usually fails.
Practical consequence: the heaviest dataset in a move group sets that group's schedule, and everything chatty with it must land in the same window. You do not choose the order of a wave freely — the data chooses it, and you arrange the rest around that.

The arithmetic is worth having in your head, because it converts an argument into a number. Work in decimal units and remember that 1 TB = 8,000 gigabits:

The two formulas that settle most sequencing arguments

Transfer time. days = TB ÷ (10.8 × Gbps × efficiency). The 10.8 is just 86,400 seconds ÷ 8,000 gigabits-per-TB. Use efficiency ≈ 0.7 for a dedicated link you control and ≈ 0.5 for anything shared.

Egress cost. USD ≈ TB × 1,000 × per-GB rate. At mid-2026 list rates that's roughly $0.09/GB on AWS, $0.087/GB on Azure, $0.12/GB on GCP Premium Tier for the first tier of internet egress — so about $900, $870 and $1,200 per 10 TB respectively. Ingress is free on all three.

Rates as published mid-2026; tiers reduce the rate at volume and all three vendors now waive exit egress under specific conditions — see S3 for the fine print.

Pass 3 · trade-offs and the 2026 nuance

Gravity is now shaping architecture, not just schedules. The interesting shift over the last couple of years is that at AI scale the old assumption — move data to compute — has inverted for a growing class of workloads. Moving hundreds of terabytes across clouds can cost on the order of the compute itself, sovereignty rules increasingly forbid it outright, and open formats have made compute more portable than data ever was. The pattern that's emerging is the opposite of the one you were taught: put the workload where the data already lives.

Beware fake gravity. Not all bytes are equally heavy. A dataset is only gravitationally significant if it is irreplaceable at the destination. Ten terabytes you can re-derive, re-download from a public source, or regenerate has almost no gravity, however large it looks in the inventory. This distinction matters a great deal for your own workloads and it's the core of the apply-it section below.

The escape hatches. When gravity is genuinely too strong, you have four moves, in increasing order of commitment: (1) don't move the data — put compute next to it via a hybrid link; (2) move it physically on an appliance rather than over the wire; (3) move only the derived/aggregated form and leave the raw data behind; (4) accept a period of dual residency where both copies exist and you pay for both. Option 4 is the most common and the least planned-for.

S1·5Core concepts
▸ waves & cutover

Wave planning and cutover

Pass 1 · intuition

You don't move a hospital in one night. You move a ward at a time, keeping every patient treated throughout, and you pick the first ward because it's the one where a mistake is survivable — not because it's the most important.

A wave is a batch of applications that move together in one window. A move group is the set of applications that must move together because splitting them would break something. Waves are a planning choice; move groups are a physical fact you discover during assessment.

Pass 2 · mechanism

Wave planning follows six rules, in priority order. When they conflict, the earlier rule wins.

Wave 0 · before anything moves
Retire first, so you never plan work you don't need

Every retirement removes a node and its edges from the graph, which can dissolve a move group entirely. Retiring is also the only migration activity with no rollback risk, so it costs nothing to do early. Do it before you size waves, not after.

Wave 0 also contains the non-application work: the landing zone must exist, the hybrid link must be up and tested, identity federation must work, and the first target account or project must be governed. Migrating into an ungoverned destination is how you produce an estate nobody can audit.

Constraint · not negotiable
Move groups are atomic

Applications sharing a database schema, a file share with tight write coupling, or a distributed transaction move in the same wave. There is no clever sequencing around a shared schema — you either move both, or you split the data first, which is a refactor and belongs in Session 2.

This is the rule people break. A shared-schema pair gets split across two waves because they have different owners, and then a fortnight of production runs with cross-WAN database traffic while everyone wonders why the batch window doubled.

Ordering · with a real caveat
Move dependencies before their dependents — usually

The default is leaf-first: move the things nothing else depends on, then their consumers. That way each application arrives to find its dependencies already in the target, and you're never reaching backwards across the gap.

The caveat: the leaf is often shared identity or a shared database — the thing with the highest blast radius. Moving it in wave 1 means your riskiest component moves before your team has learned anything. Two legitimate answers: move a low-risk leaf first purely for learning, or accept a temporary hybrid link so a dependent can move before its dependency. The private link you built in wave 0 is precisely what buys you the freedom to violate strict ordering.

Scheduling · the data decides
The heaviest dataset in a group sets that group's date

Run the transfer-time formula for every dataset in the wave. Whichever is largest determines when replication must start, and therefore when the wave can cut over. A group with an 8 TB database on a 1 Gbps link cannot cut over sooner than the seeding takes, no matter what the project plan says.

Sequence heavy-data groups so their seeding overlaps other waves' execution. Replication is mostly wall-clock time, not people time — which means it should be running in the background while your team is doing something else.

Risk · the first wave is a rehearsal
Wave 1 exists to teach you, not to deliver value

Pick something with real users but survivable failure, few dependencies, and an owner who will co-operate. The point of wave 1 is to discover everything your runbook got wrong while the cost of being wrong is low: the change-approval process, the firewall rule nobody documented, the DNS TTL that's set to 24 hours, the monitoring that doesn't follow the app.

This is the patterns catalog's Start Small, and its companion Pave the Road: whatever wave 1 teaches you becomes the template, pipeline and runbook that waves 2 through 20 reuse. A migration where every wave reinvents the process is a migration that never gets faster.

Cadence · the metric that matters
Establish a rhythm, then measure velocity in applications per wave

Fixed-length waves — commonly two to four weeks — with a fixed sequence of activities: prepare, replicate, test, cut over, validate, hand to operations. The value of a fixed cadence is that velocity becomes measurable, and "how long will it take?" becomes arithmetic instead of a guess.

Expect the curve to be slow, then fast, then slow again: early waves are slow because you're learning, the middle is fast because the road is paved, and the last waves are slow again because what's left is what everybody avoided.

Cutover: the only irreversible hour

Everything up to cutover is reversible at near-zero cost, because the source system is still serving traffic. The technique you can use is decided by exactly one number: how much downtime the application can tolerate.

Cost of turning back, over the life of a cutover CUTOVER reversible — source still authoritative rollback now costs data replicate test launch validate freeze writes final delta flip DNS / LB smoke tests users write Rollback here = stop the job. Nothing lost. Test launches into an isolated subnet cost you nothing but compute — do several. Rollback here = replicate backwards, or lose writes. Decide the abort criteria and who calls it BEFORE you flip. Write it in the runbook.
The runbook question people forget: not "what is our rollback plan" but "who has the materiality to call it, against what criteria, and by what time?" A rollback decision taken at 04:00 by a tired team with no pre-agreed threshold is how a two-hour incident becomes a two-day one.
Downtime toleranceTechniqueHow it worksWhat it costs you
Hours–daysCold copyStop the app, copy everything, start it in the target.Nothing technically. The business pays in outage.
MinutesContinuous replication + short freezeReplicate continuously while the source runs; freeze writes, ship the final delta, flip. This is what every VM-replication service does.Replication infrastructure and agents for the duration. Careful DNS TTL management.
SecondsChange data capture with a read-only windowThe database service streams changes into the target; you drain in-flight transactions and switch the connection string.Schema constraints — CDC has opinions about primary keys and DDL changes during replication.
ZeroDual-write / parallel runBoth systems accept writes; traffic shifts gradually; either can be authoritative.By far the most expensive. You are building and operating a distributed system to perform a migration. Covered in Session 2 — and it is a modernization technique, not a migration one.
Pass 3 · where it breaks

DNS TTL. A record with a 24-hour TTL means some clients keep hitting the old endpoint for a day after you flip. Drop TTLs to 60 seconds days before the cutover, not during it. And remember that some clients — particularly older JVM configurations — cache DNS resolution for the life of the process regardless of TTL.

The source you left running. If the old system stays up "just in case" and still accepts writes, you now have a split brain and nobody has noticed. Firewall the old system's write path at cutover, keep it readable for comparison, and set a hard deletion date.

Licensing and hardcoded assumptions. Licences keyed to MAC addresses or hostnames. Certificates pinned to old names. IP addresses hardcoded in configuration files that no longer exist in source control. These are discovered at 03:00 on cutover night unless you find them during a test launch — which is precisely what test launches are for.

Wave fatigue. Fixed cadence means the same people run a cutover every fortnight for a year. Rotate the on-call role, keep a written runbook rather than tribal knowledge, and treat the third-to-last wave with the same discipline as the first — the failure rate goes up at the end, not down, because the remaining applications are the ones everybody deferred.

S1·6Reality
check

Worked on paper: sequencing a five-application portfolio

A mid-size financial services firm. Data centre lease ends in fourteen months. Five applications, one shared Oracle database, and a 40 TB tick-data archive sitting on an NFS filer. Here is the whole exercise: map it, choose an R per node, form move groups, then sequence.

Step 1 — the graph

Discovered inventory · edge style encodes coupling strength AUTH-SSO 3 VMs · LDAP · leaf LEDGER-CORE Java monolith · Oracle 11g · 8 TB changes weekly · 60% of all defects RECON-BATCH nightly · reads Oracle direct PARTNER-API Node · stateless · REST only REPORT-PORTAL 12 users · no commit in 3 yrs TICK-ARCHIVE 40 TB NFS · cold · data only SHARED SCHEMA Legend API / network call — survives a wave split shared schema — atomic move group
The finding that changes the plan: RECON-BATCH reads LEDGER-CORE's Oracle schema directly, not through an API. That thick red edge means they are one move group. No amount of project management separates them.

Step 2 — an R per node, with the reasoning

ApplicationDecisionWhy this R and not the neighbouring oneData weight
REPORT-PORTALRetire Twelve users, no commits in three years, and every report it produces is reproducible from LEDGER. Dark-period it through one quarter-end first — a reporting tool is exactly the kind of thing someone uses once every three months.
AUTH-SSORehost
then repurchase, year 2
Repurchasing to a managed identity provider is clearly right long-term. But it has three inbound dependents, so repurchasing it now adds three integration projects to a fourteen-month deadline. Rehost to hit the date; repurchase once the estate is stable. This is the R composing over time.Trivial
LEDGER-COREReplatform
then refactor — Session 2
It changes weekly and generates most of the defects, so it is the one genuine refactor candidate in the portfolio. But refactoring during a deadline-driven migration is the classic mistake. Replatform now: containerise the app tier, move Oracle to a managed Oracle-compatible service. Refactor afterwards, incrementally.8 TB — sets the wave date
RECON-BATCHRehost Nothing to gain from changing it, and it can't be separated from LEDGER's schema anyway. It moves when LEDGER moves. Splitting the schema so it could move separately is refactor work — legitimate, but not on this timeline.Small — writes to a file share
PARTNER-APIReplatform Stateless, talks only over REST, no local state. This is the easiest node in the graph: build a container image, point it at the new LEDGER endpoint, done. It could go in almost any wave.None
TICK-ARCHIVEData move Not an application — 40 TB of cold data. It has no cutover, no downtime constraint, and no dependents that are latency-sensitive. Which means it can start moving on day one and finish whenever. Never let cold data sit on the critical path.40 TB — heavy but not urgent

Step 3 — the wave plan, with the arithmetic behind the dates

Fourteen months · bars show occupancy, not effort M2M4M6 M8M10M12 ◂ lease ends M14 WAVE 0 landing zone · link · retire DATA TICK-ARCHIVE 40 TB — background, off the critical path entirely WAVE 1 AUTH-SSO rehost ← the rehearsal WAVE 2 8 TB seeding + CDC LEDGER + RECON ← one move group WAVE 3 PARTNER-API WAVE 4 buffer contingency + decommission source ▸
Two things to notice. The 40 TB archive starts on day one and never blocks anything — cold data is the easiest thing in a migration to schedule badly. And wave 2's cutover date is set by seeding time, not by team availability: the 8 TB database is the pacemaker for the entire programme.
The arithmetic that produced those dates

LEDGER's 8 TB over a 1 Gbps dedicated link at 70% efficiency: 8 ÷ (10.8 × 1 × 0.7) = 1.06 days for the initial seed. That's fine — so why does wave 2's bar show weeks of seeding? Because the seed is the easy part. The weeks are consumed by schema conversion validation, running change data capture long enough to prove the delta stays small, and rehearsing the cutover twice. Transfer time is rarely the binding constraint on a database move; confidence is.

The 40 TB archive over the same link: 40 ÷ 7.56 = 5.3 days of continuous transfer — but it would saturate the link that wave 2 needs. So it's throttled to run overnight only, stretching to several weeks of wall-clock. Which is completely acceptable, because nothing waits for it. Throttling a non-urgent transfer to protect an urgent one is a wave-planning decision, not a networking one.

If the link were 100 Mbps instead: the 40 TB becomes 40 ÷ (10.8 × 0.1 × 0.7) = 53 days at full utilisation. At that point the physical appliance stops being an exotic option and becomes the obvious one. That crossover is computed properly in S3.

Three cited examples worth knowing

Grounding · sources + current sources
  • Capital One's portfolio approach. The patterns catalog cites Capital One's public accounts of their cloud journey specifically as an example of rehosting being one of several strategies applied across a portfolio — not the strategy. It's the cleanest available illustration of the "R per app, not per portfolio" principle at genuine enterprise scale.
    the cloud application patterns catalog, "Lift and Shift" examples.
  • Dress4Win — the case study your GCP source actually has. GCP guidance walks the Google Professional Cloud Architect case studies, and Dress4Win is the migration one: a traditional enterprise moving on-prem applications to GCP while maintaining security and minimising downtime. The source's guidance for it is precisely this session's content — recommend phased migration, start with non-critical workloads, use VPN/Interconnect for hybrid networking during the transition. Worth reading as the exam-shaped version of the wave plan above.
    a leading GCP architecture reference, "PCA Case Studies."
  • Wave planning became a product this year. The strongest evidence that this practice is now standard: Azure Migrate shipped a public-preview capability literally called Wave Planning, which breaks large migrations into manageable waves of workloads and applications. AWS Transform's VMware agent likewise now performs dependency mapping and "intelligent wave planning" as an orchestrated step. Five years ago this was consultancy IP in a spreadsheet; it's now a console feature on two clouds.
    What's new in Azure Migrate AWS Migration & Modernization blog
S1·7Apply it
your context

Apply it — your stack, and one lab

Where a GenAI workload sits on this map

Run your own stack through the which-R tree and something interesting happens: it exits early and cheaply at almost every node. Your vLLM inference service is stateless, already containerised, and its state is externalised to object storage. That combination means Q6 — "can you get most of the benefit without opening a source file?" — answers yes immediately. It's a Replatform, and a shallow one: rebuild or re-tag the image, re-point the weights path, re-create the autoscaling policy. On the Tab 0 axis you are already sitting near the top-right without having done the expensive climb, because the application was born there.

That is not luck and it's worth naming precisely, because it's the whole argument for cloud-native architecture stated in migration terms: the properties that make an application easy to operate are the same properties that make it easy to move. Statelessness means no cutover data loss. Externalised state means the data migration and the app migration are separate, independently schedulable projects. Containerisation means the compute target is interchangeable. Your Modal deployment, your Vertex AI script, and a KServe deployment on GKE are three bindings of the same artefact.

Now find the real gravity. Run the four-item assessment checklist over your own setup and the answer is not what the inventory suggests. Gemma's weights are large but they have fake gravity — they are re-downloadable at the destination, so moving them is a bandwidth question, never a risk question. The genuinely heavy objects are the ones you cannot re-derive: a fine-tuning dataset you built, your eval suite and its golden outputs, and accumulated request/response telemetry. Those are usually far smaller in bytes and far heavier in gravity. If you ever plan a real cross-cloud move, inventory by irreplaceability, not by size.

Optional hands-on lab — a wave plan for something you actually run

This session is concept-only, so the lab is deliberately a paper exercise with a small cloud component. It costs nothing if you follow the guard rails, and it produces an artefact you'll reuse in S3.

Part A · no cloud account needed
Map your own stack as a graph

Take your Modal + Vertex + local vLLM setup and draw it as the dependency graph above. Nodes: the inference service, the weights bucket, the eval dataset, any gateway or proxy, your telemetry sink. Edges: label each one as API, shared-store, or batch.

Then write an R on every node and identify the move groups. You'll find at most one — and that is the point.

Part B · minimal cloud, free tier
Measure a real transfer rate

Before you trust the formula, calibrate it. Push a single 1–5 GB file to a bucket, time it, and compute your actual achieved throughput. Compare it to your link's rated speed — the ratio is your real efficiency factor, and it is almost always worse than 0.7 on a shared connection.

Then use your number, not the reference text's, for the rest of this stage.

Cost guard rails · read before you touch a console
  1. Set a budget alert first. Before creating anything: a budget with an alert at a threshold low enough to be annoying — a few dollars. On every cloud this is free, takes two minutes, and is the only thing standing between you and a surprise.
  2. Smallest SKU, free tier only. This lab needs one storage bucket and one small file. No compute instance, no migration agent, no replication task.
  3. Ingress is free; egress is not. Uploading your test file costs nothing. Downloading it back is billed per GB. Upload, measure, and don't pull it down again.
  4. Teardown, in this order: delete the test object → delete the bucket → confirm the bucket is gone in the console, not just in the CLI response → leave the budget alert in place for the rest of the stage.

Part B uses object storage only. S3's lab involves migration-service agents and replication tasks, which bill continuously while they exist — the teardown discipline there is considerably more important, and it's spelled out in that tab.

Bridge

You've now got LEDGER-CORE sitting in the cloud on managed infrastructure, still a monolith, still generating 60% of the defects. The migration is done and the problem is not solved — which is exactly the lift-and-shift-then-stop trap this stage opened with.

Session 2 is how you get out of it without a big-bang rewrite: the strangler fig, one slice at a time, with a working system and a cheap rollback at every step.

S2·1Why this
session exists
Session 2 · Modernization via the strangler fig · concept-only

The system is bad, it makes money, and you cannot turn it off

Every serious modernization starts from the same three facts, all true at once. Ignore any one of them and you get the wrong plan.

LEDGER-CORE from Session 1 is now in the cloud. It is still a monolith. It still absorbs 60% of the defect budget, it still takes four hours to test, and a one-line change still requires deploying the whole thing. The migration succeeded and the actual problem is untouched. Somebody — usually somebody smart, usually in their first month — is now going to say: "Let's just rewrite it properly."

They are describing the single most reliable way to destroy a software organisation.

Two plans, same destination, drawn against time Plan A · big-bang rewrite 18–36 months of building. Zero delivered value. Old system frozen or forked. CUTOVER ? One bet. One rollback plan, which is "don't." Every risk lands on the same day. Meanwhile the old system must still be maintained, so you now staff two systems. Plan B · strangler fig Each block is one slice: shipped, in production, measurable, individually reversible. Value from month two. Risk arrives in small pieces you can absorb. You can stop and still be better off. old gone
The asymmetry that decides it: Plan A's risk is concentrated on one date and its value arrives only at the end, so a slip in month 20 costs everything. Plan B's risk is spread across thirty small events, and if the programme is cancelled in month nine you keep everything shipped so far. Incremental isn't safer because it's slower. It's safer because it's reversible.
The canonical failure — worth knowing by name

In 1998 Netscape decided that Navigator 4 was too messy to maintain and rewrote the browser from scratch. Version 5 never shipped. Three years of development produced a buggy, feature-incomplete version 6 while Internet Explorer went from afterthought to total market dominance. Lou Montulli, one of Navigator's original engineers, later confirmed to a classic engineering essay that the rewrite was one of the major reasons he resigned. The rewrite didn't just fail technically — the company did not recover.

The pattern repeats with depressing consistency: big-bang replacement, a feature freeze on the old system, a timeline that doubles and then doubles again, and competitors gaining ground while the team rebuilds what already existed. Analyses of enterprise modernization programmes published this year put the failure-or-underperformance rate for modernization projects somewhere in the region of two-thirds to three-quarters. The rewrite is not a bold choice. It's the default choice, and it's usually wrong.

Session type — and the honest vendor note

Concept-only. There is no product called "strangler fig." What does exist is documentation: Microsoft publishes Strangler Fig and Anti-Corruption Layer as named patterns in the Azure Architecture Center, AWS covers the strangler fig in Prescriptive Guidance, and Google's migration guides describe the same shape under different wording. Those are references, not products, and forcing a three-cloud table onto them would be theatre. The one place tooling genuinely enters is the routing layer — an API gateway, service mesh, or reverse proxy — and you already built those in Stages 4 and 6.

S2·2Core concepts
▸ the pattern

The strangler fig

Pass 1 · intuition

A strangler fig germinates in the canopy of a host tree and sends roots down its trunk. Over years the roots thicken, fuse into a lattice, and take over the job of holding the canopy up. Eventually the host dies and rots away, and what's left is a hollow, self-supporting fig in exactly the shape of the original tree. At no point was there a moment when the forest had no tree standing there.

the refactoring literature borrowed the metaphor for software. You grow a new system around the old one rather than beside it, take over one responsibility at a time, and delete the old code as each responsibility transfers. There is never a day when the system is down, and there is never a version that hasn't been in production.

The patterns catalog adds a useful distinction: strangling is really two activities running in parallel. Abandonment — all new work happens outside the monolith, so it stops growing. Migration — existing functionality is progressively reimplemented outside it, so it starts shrinking. In rare cases where usage patterns change fast enough, abandonment alone finishes the job and the monolith simply becomes irrelevant.

Pass 2 · mechanism

Mechanically the pattern has exactly one prerequisite and then four repeating phases. The prerequisite is a facade: a routing layer through which all client traffic passes before it reaches either system. Without it you cannot redirect a slice, and without redirection there is no strangler fig — just two systems.

Phase 0 · the only step with no functional change
Put a facade in front of everything and change nothing else

Insert a proxy between all clients and the monolith. Initially it passes 100% of traffic through unmodified. Nothing behaves differently, no feature moved, and the deploy is trivially reversible. The patterns catalog calls this Wrap the Monolith.

Two things this buys you immediately, before any migration work: protection for existing clients — including third-party ones you cannot change — and an observability baseline. Every request now flows through one point where you can measure it, which means you finally learn which endpoints are actually used and how often. That data is what tells you which slice to take first.

Ship this phase on its own and let it bake for a fortnight. If it's going to break something, you want that to happen while nothing else is in flight.

Phase 1 · one slice, shadowed then shifted
Build the new service, route a trickle, compare, then commit

Choose one cohesive slice of functionality. Implement it outside the monolith. Then move traffic onto it in graded steps rather than a switch: shadow first (send a copy of real requests to the new service, serve the old one's response, compare in the background), then a small canary percentage, then all of it.

Two supporting pieces attach here. An anti-corruption layer at the boundary, so the monolith's data shapes don't infect the new service's model. And a monolith-to-microservice proxy for the reverse direction, so code still inside the monolith that used to call this functionality in-process now calls out to the new service instead. Both are covered below.

Phase 2 · the long middle
Repeat, and defend the directive that stops the monolith growing

Slice by slice, the facade's routing table shifts from mostly-legacy to mostly-new. This phase lasts months to years and its main enemy is not technical.

The technical work is a repeating loop you get faster at. The organisational work is holding the line on new features go outside the monolith. Adding to the monolith is always faster this sprint, which means without an explicit directive the monolith grows faster than you shrink it and the programme never converges. The patterns catalog documents both the carrot (templates, examples, paved pipelines that make the new way easier) and the stick (a governance review that must approve any change made inside the monolith). Real organisations end up needing both.

Phase 3 · the step everyone skips
Delete the old code — and know when to stop

Once a slice has served 100% of traffic for long enough to trust, remove the legacy implementation. Not disable. Not comment out. Delete, and delete its tables too once nothing reads them. Code left behind gets accidentally re-enabled, gets patched during incidents, and keeps appearing in dependency scans for years.

Stopping deliberately is legitimate. Some parts of a monolith are stable, rarely changed, and already wrapped behind a clean facade — the benefit of extracting them is close to zero. The patterns catalog is explicit that complete elimination is the ideal, not the requirement. What is not legitimate is stopping by accident: doing the three interesting slices, losing executive attention, and running two systems indefinitely at double the maintenance cost. That is the single most-cited failure mode of this pattern.

The facade over time — the routing table is the migration Month 0 clients FACADE — 100% pass-through MONOLITH statements payments postings fx one shared schema Month 9 FACADE — 2 routes moved MONOLITH postings fx schema (shrinking) statementservice paymentservice dashed = monolith calling out Month 22 FACADE — routes to services only retained core statement payment posting fx each owns its own store The clients never changed. The facade's routing table did — and that table is the migration plan, in executable form.
Note what stays constant: the client contract. Third parties calling your API in month 22 are hitting the same endpoints they hit in month 0. That is what makes the pattern usable in an organisation where you don't control your callers.

The mechanism itself, in eight lines

The facade is not conceptual — it's a routing rule. Here is what shifting one slice actually looks like, expressed as a weighted split at the proxy. This is the artefact the entire pattern rests on:

# facade: move 5% of one slice to the new service, everything else untouched
location /api/statements/ {
    split_clients "${remote_addr}${request_id}" $slice {
        5%   statement_svc;   # canary share — raise 5 → 25 → 100 over days
        *    monolith;        # default stays legacy until you say otherwise
    }
    proxy_pass http://$slice;
}
# every other path falls through to the monolith, unchanged

Three properties make this the right primitive. It is reversible in one deploy — change 5% to 0% and you are back. It is sticky per client, because the split key includes the client address, so a given user doesn't flip between implementations mid-session. And it is observable: the proxy emits which branch served each request, so your comparison data comes for free. A feature flag inside the monolith gives you none of the first and only some of the third.

Pass 3 · trade-offs, limits, and the honest costs

You run two systems for a long time. This is the real price, and it is not small: two deployment pipelines, two monitoring stacks, two on-call rotations, two sets of skills, and a technology diversity that raises total cost of ownership for the duration. Teams reject the pattern on these grounds and they are not being stupid — they are just comparing it to a rewrite that finishes on schedule, which is a fictional comparison. Against a rewrite that actually finishes when rewrites actually finish, strangling is cheaper as well as safer.

The benefits arrive late and the costs arrive early. Because it's gradual, you carry the overhead of two systems from month one and only reach a materially better architecture in year two. This is a funding and attention problem more than an engineering one, and it's why the pattern needs an executive sponsor who understands what they've signed up for.

Data is where it genuinely gets hard. A monolith uses a centralised database; services want to own their own stores. Every slice you extract raises the same questions: consistency across two stores, transactions that used to be one commit and now aren't, queries that used to be a join and now need two calls, and reporting that assumed everything lived in one schema. The cross-service transaction that used to be a database transaction typically becomes a saga. Budget for this explicitly — the data work is usually larger than the code work.

When it doesn't apply. The pattern needs a chokepoint. If clients call the system as an in-process library, or link against it, or hit hardcoded addresses you cannot change, there is nowhere to put a facade. Your first job then is not strangling — it's refactoring internal boundaries until a facade becomes possible, which is the patterns catalog's Refactor the Monolith as a precondition rather than a goal.

What the numbers say. Published research on incremental modernization is encouraging but should be read with the usual caution about vendor-adjacent studies: Kyndryl's 2025 research reported an average ROI around 288% for organisations modernizing mainframe applications using incremental approaches, and McKinsey's analysis of programmes completed in 2024–25 reports infrastructure cost reductions in the 30–50% range with 20–30% improvement in development cycle times. Treat those as evidence that the approach works, not as a forecast for your programme.

S2·3Core concepts
▸ the boundary

Keeping old and new decoupled: facade, ACL, and the reverse proxy

Three distinct pieces sit on the boundary between the monolith and the new services. They are routinely confused with each other, and the confusion produces real architectural damage, so it's worth separating them precisely.

Direction: client → system
Facade

Sits in front of everything. Routes each incoming request to the monolith or a new service. Translates protocols where old clients speak an old dialect.

Protects: your clients, from knowing a migration is happening at all.

Direction: legacy data → new domain
Anti-corruption layer

Sits inside the new service at its edge. Translates the monolith's data shapes, naming and semantics into the new service's own domain model.

Protects: the new service's design, from being colonised by legacy concepts.

Direction: monolith → new service
Monolith-to-microservice proxy

The old component keeps its exact signature inside the monolith, but its body now just forwards the call to the new service.

Protects: the hundred call sites inside the monolith you don't want to edit.

Pass 1 · intuition · the anti-corruption layer

You've hired a brilliant translator to work with a foreign partner whose contracts use archaic terminology, inconsistent units, and one field that means three different things depending on a flag elsewhere in the document. The translator's job is not to pass the archaic terms through with a footnote. It is to produce a clean document in your language, so that everyone downstream can reason normally without learning the partner's dialect.

That is the anti-corruption layer. Note the name: the thing being prevented is corruption of your model, not corruption of data. Without it, the monolith's ST_FLG column with its values 'A', 'C' and 'X' propagates into your new service, then into its API, then into the next three services that consume it, and five years later somebody is still asking what 'X' means.

Pass 2 · mechanism · the adapter itself

Concretely an ACL is a translation function at the service's edge, and the whole discipline is that the legacy vocabulary must not survive the crossing. Nothing past this function knows the monolith exists:

# anti-corruption layer: legacy shapes stop here and go no further
def to_statement(row):                                    # row = raw LEDGER_STMT record
    return Statement(
        id      = StatementId(row["STMT_ID"].strip),     # padded char → typed id
        period  = Period.from_yyyymm(row["PRD"]),         # "202607" → Period
        balance = Money(row["BAL_CENTS"], row["CUR_CD"]),  # int + code → Money
        status  = STATUS_MAP[row["ST_FLG"]],              # 'A'/'C'/'X' → enum
    )                                                    # unknown flag ⇒ raise, don't pass through

Four things that small function is doing, each of which is a boundary you'd otherwise leak: normalising a padded fixed-width identifier into a typed one; converting an encoded date into a real domain concept; combining two columns that only mean something together into a single value object; and turning an opaque flag into a named enumeration. And the last line matters most — an unmapped flag raises rather than falling through, so unknown legacy states surface as errors during the shadow phase instead of as silent nulls in production.

Facade versus monolith-to-microservice proxy — when to use which

The patterns catalog separates these carefully and the distinction is practical. A facade intercepts traffic arriving from outside. It cannot intercept calls made inside the monolith, because those are in-process method calls that never touch the network. So when you extract a component that other monolith code calls, you have two options:

ApproachWhat you changeChoose it whenCost
Rewrite the callers Every call site inside the monolith is edited to call the new service directly. There are few call sites, and you own them all. Cleanest end state. Linear in the number of call sites, and each edit is a chance to break something.
Monolith-to-microservice proxy Nothing at the call sites. The extracted component keeps its signature; its body becomes a forwarding call. There are many call sites, or the calling code is fragile, or you want the change reviewable in one file. One extra network hop, plus the monolith must be rebuilt and redeployed each time you extract. Distributed-system failure modes now exist inside code that never had them.

In practice most teams use both: the proxy first, to get the extraction shipped, then rewrite call sites opportunistically whenever they're touching that code anyway. And note the proxy can be asynchronous — the old synchronous method can publish to a queue that the new service consumes, which is exactly how the retail example in the patterns catalog fixed a Black Friday thread-pool collapse by decoupling order capture from order writing.

Pass 3 · trade-offs

The ACL has an expiry date, and you should write it down. While the monolith exists, the ACL earns its keep. Once the legacy source is gone, an ACL that survives is just an extra mapping layer nobody remembers the reason for. Tag these classes so that "delete the ACL" is a visible item on the decommissioning checklist, not an archaeological discovery in 2031.

Facades accumulate responsibilities. A facade is an attractive place to put things: routing, protocol translation, authentication, rate limiting, caching, circuit breaking. Each is defensible; collectively they turn your routing layer into a second monolith that every team must change and nobody owns. Keep policy in the facade and keep business logic out of it. The test: if changing a business rule requires a facade deploy, the rule is in the wrong place.

Every hop is a new failure mode. An in-process call that could not fail is now a network call that can time out, retry, and partially succeed. Adding a proxy hop to a call path that was previously a method invocation changes its reliability characteristics, and the code around it was written assuming it couldn't fail. Timeouts and circuit breakers at these boundaries are not optional polish.

S2·4Core concepts
▸ finding slices

Where do you cut? Hairline cracks and the three extraction moves

Pass 1 · intuition

A stonemason splitting a block doesn't hit it in the middle. They look for the fracture plane — the line along which the material already wants to separate — and apply force there. Hit the wrong place and you get rubble.

Monoliths have fracture planes too. The patterns catalog calls them hairline cracks: places where functionality is already more cohesive internally than it is coupled externally. Finding them is most of the skill; the extraction itself is comparatively mechanical.

Pass 2 · mechanism

Three categories of crack are easy to spot, in decreasing order of luck:

Where monoliths already want to separate Case 1 · existing REST or async services Already network-addressable. Untangle the deployment unit, ship it separately. Mostly a packaging problem, not a design one. easiest · do these first, to learn Watch for: shared in-process caches and static state the service quietly relies on. Case 2 · older distributed interfaces SOAP, EJB, CORBA. A defined interface exists but speaks a dead dialect. Most of these were CRUD on one object, which maps cleanly to a REST resource; the rest become commands. re-express the contract, keep the logic Watch for: transactional semantics you inherit. Case 3 · web forms straight onto tables No domain layer at all — the UI talks to the database. There is nothing to extract yet, so you build the missing domain layer first, then extract it. refactor then extract · slowest path Watch for: logic hiding in stored procedures.
When none of the three apply — no interfaces, no seams, business capabilities not reflected in the code at all — the patterns catalog's advice is to work backwards from the data: start with the tables and the stored procedures, infer the domain concepts they imply, then trace back into the code that touches them. It's slow, and it's often the only way in.

Once you've found a crack, exactly three moves are available. Which one you use is determined by how coupled the target is, not by preference:

MovePreconditionWhat you doRisk profile
Extract Component The functionality is already loosely coupled with a defined interface. Copy the code out, run it as a service, route callers through a facade or proxy. Often you extract a large macro service first — deliberately bigger than a microservice — and split it further once it's stable outside. Lowest. Behaviour is preserved because the code is preserved.
Refactor then Extract Partially coupled — a boundary is visible but not clean. First reorganise inside the monolith into a module with a real interface (a facade internally, then a proper service API), update internal callers to use it, and only then pull it out. Medium. Every refactoring step must be behaviour-preserving, which requires test coverage you may not have.
Replace as Microservice Tightly coupled, spread across the monolith, impossible to extract. Freeze the functionality in the monolith, reimplement it from scratch outside, validate against the original, canary-release, then redirect and eventually delete. Branch-by-abstraction is a specific variant of this. Highest. You are rewriting, and the original is your only specification — which is exactly why playback testing exists.

A useful diagnostic for locating candidates that the material recommends and that costs almost nothing: look at your commit history and your issue tracker. The parts of the monolith that change most often and break most often are, almost by definition, the parts where extraction pays back fastest. Static analysis tools that surface coupling and code smells help, but change frequency is the better signal because it's about cost, not aesthetics.

Pass 3 · trade-offs

Macro services are a feature, not a compromise. There is real pressure to extract "proper" microservices immediately. Resist it. Pulling out one large, internally-tangled component is a genuine win — it is now independently deployable and independently scalable — and you can split it later with far better information, because you'll have watched it run. The patterns catalog's airline example did exactly this: the ticket purchase process came out as one large service with messy internal switches, and was refined over several later releases.

Two orderings, both valid. Bottom-up means starting with the obvious low-hanging fruit — fast wins, good for morale and learning, but the resulting service boundaries may not follow the domain. Top-down means starting from business capabilities and carving downward — better boundaries, much slower start. Most successful programmes are bottom-up for the first few slices to build capability and credibility, then switch to top-down once the team understands the domain well enough to model it.

Right-size against the domain, not against a line count. Whichever move you use, the boundary should follow a bounded context from C6. A service split along a technical seam that cuts through a domain concept will need chatty coordination with its neighbour forever, and that chattiness is permanent.

S2·5Core concepts
▸ the data

Dual-write, backfill, reconcile: moving state without losing any

Pass 1 · intuition

Changing banks. For a while you keep both accounts open. New income goes into both — well, you can't actually do that with money, which is precisely why this is hard in software too. What you can do is: run both accounts, move the historical statements across, check the balances match for a couple of months, and only then close the old one. Nobody sensible closes the old account the day the new one opens.

Three separate activities hide in that story. Dual-write — new events land in both places. Backfill — the history the new place never saw gets copied across. Reconciliation — you prove the two agree before you commit to one.

Pass 2 · mechanism

The full sequence for moving one slice's data, with the source of truth marked at every stage. The whole design principle is that exactly one store is authoritative at any moment, and the switch of authority is a single explicit step — never an emergent property of routing weights.

Six stages · the source of truth moves exactly once 1 · shadow read2 · read flip 3 · dual-write4 · backfill 5 · reconcile6 · flip truth READS monolith new service (reading a replica, then its own store) WRITES monolith only BOTH — monolith authoritative new only TRUTH MONOLITH IS THE SOURCE OF TRUTH — everything up to here is reversible new service ◂ the one-way door ROLLBACK free — change one routing weight costs data C4 backfill runs concurrently with dual-write and must be idempotent — it will race live writes and re-run after failures. C5 is the gate. Do not proceed to 6 on a schedule. Proceed when the nightly diff has been empty for N consecutive days — and N must be long enough to include a month-end, because month-end is when the weird code paths run.
The single most important line on this diagram is the dashed one at C6. Before it, rollback is a routing weight. After it, rollback means replaying writes backwards or losing them. Everything in stages 1–5 exists to make you confident enough to cross it once.

What each stage is actually for

Stages 1–2
Reads first, because reads are safe

Reads can be wrong without destroying anything. Serve them from the new service — initially against a read replica of the monolith's own database, so there is no new store yet and no consistency question at all. Shadow the responses and diff them.

This is where you discover that the legacy system rounds differently, or returns records in an order somebody depends on, or has a bug that has become a documented feature.

Stages 3–4
Writes, and the history problem

Dual-write means the application writes both places. It is not a distributed transaction — the monolith commits first and remains authoritative, and a failed write to the new store is logged and repaired, never rolled back. Accepting that asymmetry is what keeps this simple.

Backfill then copies everything that predates the dual-write. Chunk it, make it idempotent, run it during quiet hours, and track a high-water mark so it can resume.

C5
Reconciliation is the evidence

A scheduled job compares both stores and reports differences: row counts, checksums per period, and full field-level diffs on a sample. The output is a number that goes to zero and stays there.

This number, not a project milestone, is what authorises C6. It is also the artefact that convinces a risk committee, which matters more than engineers expect.

C6 and after
Flip, then actually finish

Switch authority to the new store. Keep dual-write running into the old store for a defined period so the monolith's reports keep working and a rollback is still theoretically possible.

Then finish properly: stop the dual-write, delete the monolith's tables for this slice, and delete the code. A slice is not migrated until the old tables are gone.

Playback testing: how you validate a rewrite with no specification

When you Replace as Microservice you are reimplementing behaviour that nobody fully understands, in a system with inadequate tests, where some of the bugs are load-bearing. The patterns source's answer is playback testing — also called a parallel run. Capture a set of real inputs and actions against the original system, replay the identical sequence against the new implementation, and compare the results.

Two practical forms. The simplest: run both against equivalent databases and diff the resulting state — feasible when the new schema is similar, harder when it isn't, in which case you write extraction scripts that normalise both sides before comparing. The richer form: capture live transactions as events over a period, transform them to the new service's API, and replay. If you're using CQRS, capturing calls to the write model gives you this almost for free.

The decision that catches people out is how often you compare. Comparing only final state at the end of a long replay is cheap and tells you little about where a divergence started. Step-by-step comparison after each transaction localises failures immediately and costs far more to build. Start with end-state comparison plus periodic summaries; add step-by-step only for the slices where you're finding divergences.

Pass 3 · where this breaks

Dual-write is not atomic, and pretending otherwise is the classic bug. The monolith commits, then the write to the new store fails. If your code treats that as a transaction and rolls back, you've made a working system fail because of a system that isn't live yet. The correct behaviour is: commit to the materialitative store, attempt the secondary write, log failures to a repair queue, and let reconciliation catch what the queue misses. Your divergence count will be non-zero for a while. That's the design working, not a defect.

Backfill races live writes. While you're copying 2019's rows, 2026's rows are arriving. Chunk by a stable key, make every write an upsert keyed on identity, and never let backfill overwrite a newer value with an older one. Getting this wrong produces the worst class of bug in the whole pattern: silent, historical, and discovered months later during an audit.

Reporting is the slice everyone forgets. Reports join across everything. The moment one slice's data lives elsewhere, every report touching it breaks or silently under-reports. Plan for reporting explicitly — usually by keeping a consolidated read model fed from both sides for the duration, which is more work than it sounds and is never in the original estimate.

Deciding when to stop reconciling. There is no formula. What works is a written criterion agreed in advance — for example, zero unexplained differences across two consecutive month-end cycles — recorded before you start, so the decision isn't made under deadline pressure by whoever is most tired.

Decision tree · guard clauses
Strangler fig, rewrite, or leave it alone?
Answer in order. "No" falls through. The first "yes" exits right. Bottom-left is the default.
Q1Is it stable, rarely changed, and not blocking anything anyone is trying to do?
yes ⟶
Leave it aloneWrap it behind a clean interface so it stops being visible, and spend the budget elsewhere. Modernizing a system that isn't hurting is a hobby.
no ↓
Q2Have the business requirements themselves fundamentally changed — would you build something structurally different today, not just a cleaner version of this?
yes ⟶
RewriteGreenfield. The old system is a source of requirements, not a design to preserve. Still run both in parallel and migrate users gradually.
no ↓
Q3Is it small enough that a complete rewrite fits inside one or two release cycles while the original keeps running untouched?
yes ⟶
Rewrite, parallel-runLegitimate for small systems. The test is whether you can avoid freezing the original — if you must freeze it, you're back to big-bang.
no ↓
Q4Is it impossible to intercept client traffic — callers link it as a library, or hit hardcoded addresses you cannot change?
yes ⟶
Refactor in place firstYou have no chokepoint, so no facade is possible. Create internal module boundaries and a real interface, then re-enter this tree.
no ↓
Q5Is the data so entangled that no candidate slice can plausibly own its own state — everything joins to everything?
yes ⟶
Split the data firstRefactor-then-extract, starting at the database. Denormalise, break through-database communication into interfaces, then extract.
no ↓
Default — bottom left Strangler fig Facade in front, one slice at a time, working system at every step. Start with the easiest slice rather than the most valuable one — the first extraction is a rehearsal for the process, not a delivery. And write down the criterion for finishing before you start, because stopping halfway is the most common way this pattern fails.
S2·6Reality
check

Worked on paper: strangling one slice of LEDGER-CORE

Same system as Session 1, now sitting in the cloud, still a monolith. We take one slice — statements — from first facade deploy to deleted legacy tables, and cost every step. The point of the exercise is to see how much of the calendar goes to confidence rather than to code.

WeekStepReversibilityWhat could go wrong here
1–2Facade in. Reverse proxy in front of LEDGER. 100% pass-through. No functional change. Ship it and leave it alone. Trivial — remove the proxy. A client somewhere pins the origin's TLS certificate, or an internal caller bypasses the proxy by IP. You find both in week 1, which is the point.
3Read the traffic. Two weeks of proxy logs answer which endpoints are used, how often, and by whom. Statements turn out to be 31% of requests and almost entirely reads. N/A — observation only. You discover an endpoint nobody knew was live, called by a partner you thought had migrated in 2022.
4–7Build statement-service. Reads only, against a read replica of LEDGER's database. ACL at the edge translating LEDGER_STMT into a real domain model. Nothing is live. The ACL raises on three legacy status flags nobody can explain. Good — better now than in production.
8–9Shadow. Mirror 100% of statement reads to the new service, serve the monolith's answer, diff asynchronously. Free — stop mirroring. 0.4% of responses differ. Two thirds are rounding on a currency conversion; one third is the monolith returning a field in a legacy order that a client's parser depends on.
10Canary reads. 5% → 25% → 100% over the week, using the split rule from Pass 2. One routing weight. p99 latency doubles at 25%. The replica is under-provisioned. Caught at 25%, not at 100%.
11–13Own the store. Stand up the service's own database. Dual-write from the application: monolith commits first and stays authoritative, secondary write logged on failure. Stop dual-write; new store is disposable. The secondary write occasionally fails under load. The repair queue handles it — as designed. Resist the urge to make it transactional.
13–17Backfill. Seven years of statements, chunked by period, idempotent upserts, overnight only, resumable via high-water mark. Truncate and restart. Two periods in 2020 have duplicate keys the old schema tolerated and the new one doesn't. This is a data-quality discovery, and it is normal.
18–24Reconcile. Nightly diff: row counts, per-period checksums, field-level on a sample. Target: zero unexplained differences across two consecutive month-ends. Still free. Monolith is still the truth. Month-end reveals an adjustment posting path that writes statements via a stored procedure, bypassing the application layer entirely — so it never dual-wrote. This is the finding that justifies the whole reconciliation stage.
25Flip the source of truth. New store is authoritative. Dual-write continues into the old tables so legacy reports keep working. One-way door. Nothing, if weeks 18–24 were done honestly. Everything, if they weren't.
26–30Finish. Migrate the two reports that read statement tables. Stop the reverse dual-write. Drop the legacy tables. Delete the monolith code and its ACL. Update the routing table. Historical. The step that gets deferred forever. Put it in the same ticket as the flip, or it will not happen.
Read the calendar, not the code

Thirty weeks for one slice. Roughly seven weeks of building (4–7 and part of 11–13) and twenty-three weeks of proving, waiting, and cleaning up. That ratio is not a sign of a badly run project — it is what the pattern is. You are buying reversibility, and reversibility is bought with calendar time.

Two things get much faster after the first slice: the facade already exists, and the shadow/canary/ dual-write/reconcile machinery is now reusable infrastructure. This is Pave the Road. A realistic expectation is that slice two takes half as long as slice one, and slices three onward reach a steady state — which is precisely why estimating a strangler programme from the first slice overstates it badly, and why the first slice should be chosen for its teaching value rather than its business value.

Three cited examples worth knowing

Grounding · sources + current sources
  • Netscape, 1998 — the instructive failure. The rewrite of Navigator that produced no version 5, a broken version 6 three years later, and a lost market. a classic engineering essay's Things You Should Never Do, Part I is the canonical write-up, and Lou Montulli — one of Navigator's original engineers — corroborated it directly. It's worth reading not for the history but for the mechanism: the rewrite discarded years of accumulated bug fixes, each of which encoded a real edge case that nobody had documented anywhere else. Legacy code is ugly because it is correct.
    joelonsoftware.com — Things You Should Never Do, Part I
  • Netflix, Amazon, eBay, Uber — the successes, and what they share. The patterns source collects these in §10 and the common thread is more interesting than any individual case. Netflix rebuilt its video processing pipeline from a single monolithic media system into services partitioned by business capability, and explicitly reports that monitoring and logging were what made the transition survivable. Uber broke a monolith into hundreds of services during hypergrowth while continuing to run. eBay migrated incrementally while shipping features on a normal cadence. In every case the pattern was chosen because the business could not pause — not because it was architecturally elegant.
    the cloud application patterns catalog, "Strangle the Monolith" examples.
  • The 2026 twist: AI is changing the economics of the slow parts. The historically expensive phases of this pattern are discovery, dependency mapping, and generating tests for code with none — exactly the work now being automated. Airbnb migrated roughly 3,500 test files in six weeks against an original estimate of eighteen months, using an AI pipeline with validation gates rather than a blind find-and-replace. AWS reports Thomson Reuters modernizing 1.5 million lines of .NET monthly. What is striking is that these tools have reinforced incremental migration rather than enabling big-bang rewrites: the successful pipelines are file-by-file with test gates and human review, which is the strangler fig with a faster inner loop.
    Why big rewrites fail — case collection CIO Dive on AWS Transform, Oct 2025
S2·7Apply it
your context

Apply it — your stack, and one lab

Where this lands for a GenAI-infrastructure engineer

Your inference service is not a strangler-fig candidate, and understanding why is the lesson. A stateless container with externalised state has no monolith properties to decompose — nothing is entangled, so there is nothing to strangle. If you needed to replace it you would deploy the new version alongside, shift traffic, and delete the old one. That's a blue-green deploy, and the fact that it's trivially available to you is a direct consequence of the architecture, not of luck.

The fintech pipeline, if it were a legacy monolith, is the real target. And the slices would follow the same shape as the LEDGER walkthrough: find the reads, shadow them, own the store, dual-write, backfill, reconcile against a month-end. The finance domain has a specific hazard worth naming — every number is auditable, so a 0.4% response divergence that would be a shrug in a recommendation system is a blocking defect here. That's why the reconciliation gate in a financial strangler is two month-end cycles rather than two weeks.

The pattern you will actually use, though, is the facade. Model serving is heading the same way applications did: multiple model versions, multiple providers, and clients that must not know which is serving them. A routing layer in front of your endpoints — call it a gateway — that can shadow a new model against the current one, canary 5% of traffic, compare outputs offline, and roll back with one weight change is exactly the strangler facade with a different payload. The shadow-then-canary-then-commit sequence in the LEDGER table transfers to a model swap essentially unchanged. The one adaptation: your comparison step can't be an equality diff, because two model versions won't produce identical text, so the "reconciliation" becomes an eval-suite comparison with a quality threshold instead of a zero-difference gate.

Optional hands-on lab — build a working facade and strangle something

This runs entirely on your laptop with Docker. No cloud account, no cost, nothing to tear down — which is deliberate, because the concept is worth more than the console practice here.

Part A · 30 minutes
Two backends, one proxy, a moving weight

Stand up two trivial HTTP services — call them legacy and new — each returning its own name and a version. Put nginx in front with the split_clients rule from Pass 2, starting at 0%.

Then drive traffic in a loop and walk the weight: 0 → 5 → 25 → 100, reloading the proxy between each. Watch the ratio shift in your request log. Then set it back to 0 and confirm you're fully rolled back in one reload.

The thing to feel: how cheap the rollback is. That cheapness is the entire argument of this session.

Part B · 45 minutes
Add shadowing and find a divergence

Extend the proxy to mirror requests to new while still serving legacy's response (nginx's mirror directive, or a few lines in front of both). Log both responses and diff them.

Now introduce a deliberate subtle bug in new — round a number differently, or change a field's order. Confirm your diff catches it without any user having seen it.

Then adapt it: swap the two backends for two model endpoints — a local vLLM server and a smaller model, say — and replace the equality diff with an eval comparison. You've just built the model-rollout facade described above.

Guard rails — even for a local lab
  1. Keep it local. There is no reason to put this in a cloud account. If you do choose to run Part B against a GPU instance for the model variant, use the smallest GPU SKU available, use spot/preemptible, and set a budget alert first.
  2. Teardown for the GPU variant, in order: stop the inference containers → delete the instance or scale the node pool to zero → verify in the console that no GPU node is still running → delete any load balancer you created, since those bill hourly on their own and survive the instance that prompted them.
  3. The trap specific to this lab: a proxy or load balancer left running is the cheapest thing to forget and one of the more annoying line items to find later. If you created one, it goes on the teardown list before you close the terminal.
Bridge

You can now choose an R per application, sequence a portfolio into waves, and decompose a monolith incrementally with a working system at every step. All of it vendor-neutral, and all of it decided before anyone opened a console.

Session 3 is the machinery: what AWS, Azure and GCP actually give you to move VMs, databases and bulk data, which hybrid platform fits which shape of problem, and which product names in the materials died while you weren't looking.

S3·1Why this
session exists
Session 3 · Cloud migration tooling & hybrid · three clouds, fully grounded

You've decided the R. Now something has to actually move the bits.

This is the session where products appear — deliberately last, because a tool cannot rescue a bad sequencing decision, and every one of these tools assumes you already know which R you chose.

The tooling divides into five layers, and they map almost one-to-one onto the decisions from Session 1. Discovery and assessment feed the R decision. VM replication executes a rehost. Containerisation tools execute a replatform. Database migration services execute the data half of everything. Bulk transfer handles data gravity. And hybrid platforms handle the applications you decided to retain — or the period where some things have moved and some haven't.

Read this before the tables

None of your four sources has current migration tooling, and the AWS one is actively misleading: it teaches AWS Server Migration Service and CloudEndure as the primary rehost tools across §26, including in its practice questions. Both are retired. It never mentions MGN at all — the service that replaced them in 2021, and which has itself been renamed since. Every product name, capability and price below is grounded in vendor documentation and news from the last six months, with links. Two of the changes landed within the last two weeks and one within the last day.

The staleness problem, drawn What the materials say · what is true in July 2026 201920212023 202420252026 SMS + CloudEndure — retired what the AWS source teaches ▾ AWS MGN (2021) AWS Transform MGN — Jul 2026 Anthos — dissolved GKE Enterprise + GDC what your GCP brief assumed ▾ Snowball family shrinking EOL 31 Dec 2026
The lesson generalises beyond these three cases. Migration patterns — the R's, waves, strangler fig — have been stable for fifteen years. Migration products churn every eighteen months, because they're where vendors compete hardest for switching customers. Learn the patterns from sources; look up the products the week you need them.
S3·2Core concepts
▸ the five layers

The five layers of migration tooling

Pass 1 · intuition

A removals company doesn't sell you one product. There's the surveyor who walks the house and quotes (discovery and assessment). There's the van for furniture (VM migration). There's the specialist who dismantles and rebuilds the piano (containerisation). There's the separate service for the wine cellar, because bottles need temperature control and can't just go in a box (database migration). And there's the shipping container for the twenty tonnes of stuff going by sea because it won't fit in the van (bulk data transfer).

Then there's the storage unit you keep renting because some things aren't moving yet (hybrid). Every cloud sells all six. They differ in emphasis, not in the shape of the problem.

Pass 2 · mechanism · what each layer actually does
Each layer executes a specific R — the tool follows the decision, never the reverse 1 · Discovery & assessment Inventory, utilisation, dependency flows, right-sizing, business case, wave planning. feeds the R decision itself 2 · VM / server replication Agent installs on the source, block-level replication into a staging area, test launch, cutover. executes REHOST 3 · Containerisation Inspect a running app, generate a Dockerfile and deployment manifests, target Kubernetes or serverless. executes REPLATFORM 4 · Database migration Schema conversion, bulk load, then change data capture so the target tracks the source until cutover. REPLATFORM or REFACTOR 5 · Bulk data transfer Online managed copy, or a physical appliance, or a physical upload facility. Purely a gravity problem. serves every R Layer 6 — hybrid control planes — is different in kind: it exists for what you decided not to move. Covered separately below.
Diagnostic value: if you can't say which layer a tool belongs to, you don't yet know what problem you're solving. And if you're shopping in layer 2 for an application you decided to refactor, the decision and the tool have come apart.

Layer 1 — Discovery and assessment

CapabilityAWSAzureGoogle Cloud
Central hub AWS Migration Hub — tracks progress across AWS and partner tools in one dashboard Azure Migrate — discovery, assessment and server migration in one service Migration Center — the unified hub; replaced the older standalone assessment tooling
Inventory collection AWS Application Discovery Service — agentless connector for VMware, or agents for process-level detail Azure Migrate appliance (agentless for VMware/Hyper-V); plus Arc-based discovery preview for servers already Arc-enabled Migration Center discovery client, agentless vSphere collector, or import from a CSV/RVTools export
Dependency mapping Agentless network-level, or agent-based with process attribution Agentless and agent-based dependency analysis Dependency insight via the discovery client
Business case / TCO Migration Evaluator; assessment agent within AWS Transform Business case built into Azure Migrate, including an Arc business case preview Migration Center produces cost estimates and a business case; Google positions these as AI-assisted
Wave planning Documented in Prescriptive Guidance; AWS Transform's VMware agent performs dependency mapping and automated wave planning Wave Planning preview — an explicit console feature that breaks a migration into waves of workloads Grouping in Migration Center; no dedicated wave-planning product
Notable 2026 shift All three are pushing agentic AI into this layer. AWS Transform reached GA in May 2025 with agents for VMware, mainframe, Windows/.NET and assessment; at the New York Summit in 2026 AWS announced a continuous modernization capability in preview. Azure has Copilot guidance at points in the migration journey. Google markets Migration Center's toolsets as AI-powered. Treat the marketing sceptically and the direction seriously: discovery and planning is genuinely the part of migration best suited to automation.

Sources: What's new in Azure Migrate GCP Migration Center — migration tools AWS Transform

Layer 2 — VM and server replication (the rehost engine)

All three work the same way, and knowing the mechanism means you can reason about any of them: install a lightweight agent on the source machine; it replicates disk blocks continuously over an encrypted channel into a staging area in the target account; you launch test instances into an isolated network as often as you like without touching the source; and when you're satisfied you cut over, which stops the source and launches the real target from the latest replicated state. Because replication is continuous, the downtime at cutover is only the final delta — typically well under an hour.

 AWSAzureGoogle Cloud
Current name AWS Transform MGN renamed Jul 2026
formerly AWS Application Migration Service
Azure Migrate: Server Migration current Migrate to Virtual Machines current
formerly Migrate for Compute Engine, originally Velostrata
What it replaced AWS SMS retired and CloudEndure Migration retired — MGN is CloudEndure's technology, reengineered after AWS acquired the company in 2019 The older Azure Site Recovery–based migration path The Velostrata branding; the standalone Migrate for Compute Engine name
Sources supported Physical, VMware vSphere, Hyper-V, Nutanix, KVM, bare metal, EC2 across Regions/accounts, and other public clouds VMware, Hyper-V, physical, AWS and GCP instances VMware vSphere, Hyper-V, physical, AWS and Azure instances
Mechanism Continuous block-level replication via agent (agentless option available) into a staging subnet; automated machine conversion; test launch; orchestrated cutover Agentless replication for VMware, agent-based otherwise; test failover; cutover Replication of VM disks with a test-clone capability before cutover; CMEK supported
Typical downtime Most applications under one hour at cutover Minutes to an hour, depending on final delta Minutes to an hour
Cost of the tool Free for the first 90 days per source server; then replication charges. You always pay for target compute, storage and transfer. Replication free for 180 days per machine; you pay for target resources and storage No charge for the tool; you pay for target resources
2026 addition Two rehost paths. Self-directed through the MGN console, or agentic rehost via AWS Transform, where AI agents handle initialisation, IAM setup, launch templates, agent installation, inventory and network mapping per wave. Both use the same replication engine and you can switch between them mid-migration. Enterprise Linux (RHEL, SLES) migration supported with Azure Hybrid Benefit; Azure VMware Solution assessments extended with new host types Steady — no major 2026 repositioning

Sources: AWS Transform MGN product page (page updated 15 Jul 2026) AWS — sunsetting CloudEndure and SMS Azure Migrate release notes GCP migration tools

Correction to AWS notes §26

Sections 26.4 and 26.8 present AWS Server Migration Service and CloudEndure as the two rehost options, with instructions for wiring CloudEndure into Migration Hub, and both appear as answer options in the section's practice questions. Neither is orderable. AWS announced the sunsetting of both and named MGN the primary recommended service for lift-and-shift migrations; CloudEndure was withdrawn from commercial Regions at the end of 2022. If a practice question offers SMS or CloudEndure as the "correct" rehost tool, the current answer is AWS Transform MGN. The material's underlying concepts — Migration Hub as central tracking, Application Discovery Service for inventory, DMS for databases, the six-phase process — remain accurate.

Layer 3 — Containerisation (the replatform engine)

 AWSAzureGoogle Cloud
Tool AWS App2Container for Java/.NET; AWS Transform agents for full-stack Windows/.NET modernization Azure Migrate: App Containerization for ASP.NET and Java web apps Migrate to Containers — CLI-based
How it works Inspects a running application, generates container image and deployment artefacts, targets ECS, EKS or App Runner Discovers the app on a running server, builds an image, targets AKS or App Service Extracts the workload from a VM and generates artefacts you deploy to GKE or Cloud Run
Watch out Refactor Spaces is closed to new customers; AWS Transform is now the path for anything beyond a straight lift-and-shift Narrow language support — it is a web-application tool, not a general one The console UI, migctl and the processing-cluster CRDs were removed in May 2024. The CLI on your local machine is the only supported path now. Older tutorials will send you to a UI that no longer exists.
CostNo charge for the toolNo charge for the toolNo charge for the tool

Source: Migrate to Containers and its release notes; AWS migration tool landscape 2026

Layer 4 — Database migration

Two distinct jobs hide under one heading. Homogeneous migration — Oracle to Oracle, PostgreSQL to PostgreSQL — is mostly a data-movement problem. Heterogeneous — Oracle to PostgreSQL, SQL Server to Aurora — additionally requires schema and code conversion, and that second part is where the effort actually is. A heterogeneous database migration is a refactor wearing a replatform's clothes: stored procedures, triggers, proprietary SQL dialects and application data-access code all need changing.

 AWSAzureGoogle Cloud
Service AWS Database Migration Service (DMS) Azure Database Migration Service Database Migration Service
Schema conversion DMS Schema Conversion, and the downloadable Schema Conversion Tool Data Migration Assistant for assessment and schema work Conversion workspace within DMS, with AI-assisted conversion for Oracle sources
Near-zero-downtime mechanism Full load then change data capture; source stays live throughout Online migrations; for SQL Server, MI link distributed availability groups for real-time replication, or Log Replay Service via backup and restore Continuous replication for MySQL, PostgreSQL and Oracle sources into Cloud SQL and AlloyDB
Notable 2026 development Steady; DMS remains the workhorse and is correctly described in your AWS source The Arc-based SQL migration experience. Continuous migration assessment went GA in July 2025; the integrated workflow to Azure SQL Managed Instance followed; SQL Server on Azure VMs was added as a target in March 2026 and reached GA in July 2026. Assessment, provisioning, replication, cutover and monitoring now all sit on the Arc resource in one portal view. Steady
Failback Reverse replication can be configured, with effort Azure SQL MI Link supports failback for SQL Server 2022 and above — a genuinely differentiated capability, and directly relevant to the one-way-door problem from Session 2 Promote/demote semantics; failback requires manual setup

Sources: Microsoft — SQL migration to Azure VMs GA, July 2026 Accelerate SQL Server migration with Azure Arc GCP Database Migration Service docs

Layer 5 — Bulk data transfer, and the death of the appliance

 AWSAzureGoogle Cloud
Online, managed AWS DataSync — up to ~10 Gbps per task with an agent, ~5 Gbps without; integrity validation after every transfer; works with S3, EFS and the FSx family Azure Storage Mover, AzCopy, Azure Data Factory Storage Transfer Service — recommended for anything over 1 TB; scheduled and incremental transfers; resumes after errors; can now run over Cross-Cloud Interconnect rather than the public internet
Cloud-to-cloud DataSync supports other clouds as a source Storage Mover and Data Factory support S3 and GCS sources Native S3 and Azure Blob sources, including event-driven transfers triggered by Azure Event Grid
Offline appliance AWS Snowball Edge EOL 31 Dec 2026
210 TB Storage Optimized, existing customers only since 7 Nov 2025. Snowcone discontinued Nov 2024; Snowmobile retired early 2024.
Azure Data Box family — Data Box Disk (~7–8 TB), Data Box (~80 TB usable), Data Box Heavy (~770 TB). current Transfer Appliance — 100 TB and 480 TB models, recommended above 20 TB and up to about 1 PB. current
Physical upload site AWS Data Transfer Terminal — bring your own drives to a secure facility and upload at up to 400 Gbps. Ten locations as of Feb 2026: New York, Los Angeles, San Francisco Bay Area, Seattle, Phoenix, London, Paris, Munich, Sydney, Tokyo. Billed per port-hour during your reservation.
Private link AWS Direct Connect Azure ExpressRoute Cloud Interconnect — Dedicated at 10 or 100 Gbps, scaling to 8×10 Gbps or 2×100 Gbps per connection; Partner Interconnect from 50 Mbps to 10 Gbps

Sources: AWS Snowball — end of support notice (page updated 27 Jul 2026) AWS Data Transfer Terminal — six new locations, Feb 2026 GCP Transfer Appliance guidance Azure Data Box

Genuinely current — and it changes the standard advice

AWS is exiting the offline-appliance business. Snowmobile went in early 2024; Snowcone and the previous-generation Snowball devices in November 2024; the Snow Family closed to new customers on 7 November 2025; and AWS has now published an end-of-support notice for all Snowball devices in all commercial Regions on 31 December 2026, after which the Snow Console becomes inaccessible. AWS's stated reasoning is that improvements in network transfer made online migration faster and cheaper, and that customers strongly prefer it.

Which means the classic exam answer — "large dataset, poor connectivity, therefore Snowball" — is no longer correct on AWS. The current answers are DataSync over a Direct Connect link, or a Data Transfer Terminal if you can physically get drives to one of the ten cities. Azure and Google still sell appliances, so the appliance answer remains correct on those two. This is a real divergence between the three clouds, and it's about two weeks old at the level of the published notice.

Pass 3 · trade-offs across the layers

Agents are the hidden cost, in two senses. Financially, replication agents and replication tasks bill continuously while they exist — including for source servers you cut over weeks ago and forgot to disconnect. Organisationally, installing an agent on several hundred production servers is a change-management project in its own right, which is why agentless discovery exists and why most programmes use agentless broadly with agents only where they need process-level attribution.

Free tool, expensive migration. Every VM-replication and containerisation tool here is free or free-for-a-window. That is not generosity; it's the correct commercial strategy for a switching cost. What you pay for is the staging storage during replication, the target compute from the moment you launch a test instance, the data transfer, and — on the source side — egress if you're coming from another cloud. Budget the migration, not the tool.

The 90/180-day clocks are per source server, and they start at first replication. A programme that begins replicating in wave 1 and cuts over in wave 6 can quietly exhaust a free window on machines that sat replicating for months. Start replication close to the wave that needs it.

Tool coverage is not uniform, and the gaps are where the schedule slips. Every vendor's tooling is strongest for the mainstream case — a Linux or Windows VM running a common runtime — and thins out fast at the edges: unusual operating systems, appliances you don't control, licence-bound software, and anything with a kernel module. Assume the last 10% of the estate needs a bespoke approach and price it separately, because it will consume a disproportionate share of the calendar.

S3·3Core concepts
▸ hybrid

Hybrid: three genuinely different philosophies

Pass 1 · intuition

You've retained some applications on-premises. You still want one way of operating everything. Three companies have solved this and — unusually for cloud comparisons — they have solved it in three genuinely different ways, not three brands of the same thing.

AWS ships you their hardware. A rack arrives, it runs AWS services, you use the same APIs. Microsoft extends their control plane over your hardware. Nothing arrives; your existing servers get projected into Azure's management model and you govern them from there. Google gives you a Kubernetes fleet. Clusters anywhere — their cloud, your data centre, someone else's cloud — managed as one fleet with consistent config and policy.

Which is right depends entirely on what you're trying to make consistent: the infrastructure, the governance, or the workload.

Pass 2 · mechanism
Same problem, three different things made consistent AWS Outposts Extend the infrastructure AWS Region control plane your data centre AWS-owned rack, AWS APIs Consistent: the services and APIs. Requires: floor space, power, connectivity. Azure Arc Extend the control plane Azure Resource Manager policy · identity · monitoring your DCservers AWSinstances GCPK8s Consistent: governance and management. Requires: an agent. Your hardware stays yours. GKE Enterprise + GDC Extend the workload platform Fleet management Config Sync · Policy · Mesh GKEon GCP GDC onyour metal attachedclusters Consistent: the runtime the workload sees. Requires: everything to be containerised.
The choice is a question about your estate, not about vendors. If your workloads are already containers, the Google model is the least friction and the most portable. If your estate is heterogeneous and your problem is governance and audit, Arc is the only one of the three that manages resources in other clouds as first-class citizens. If you need AWS services with single-digit-millisecond latency to something physical in your building, Outposts is the only answer that actually does that.
 AWSAzureGoogle Cloud
Flagship AWS Outposts — AWS-managed racks and servers in your facility Azure Arc — projects servers, Kubernetes clusters and databases into Azure Resource Manager GKE Enterprise — fleet management, Config Sync, Policy Controller, Cloud Service Mesh
On-prem runtime Outposts racks and servers; ECS Anywhere / EKS Anywhere for containers on your own hardware Azure Local (formerly Azure Stack HCI); Azure Stack Hub for disconnected scenarios Google Distributed Cloud — software-only on bare metal or VMware, plus connected and air-gapped appliance form factors
Manages other clouds? No — AWS resources only Yes — AWS and GCP resources can be Arc-enabled and governed from Azure. This is Arc's genuine differentiator. Kubernetes only — GKE on AWS and Azure, plus attached clusters running any conformant Kubernetes distribution
Naming history you need to know Stable Azure Stack HCI → Azure Local Anthos → GKE Enterprise (late 2023). Anthos on-prem became Google Distributed Cloud Virtual, then simply Google Distributed Cloud. Anthos clusters on bare metal became GDC software-only for bare metal.
Cost model Capacity commitment — you buy hosts on a multi-year term, not instances Per-resource for the paid Arc capabilities; basic inventory and organisation is free Per-vCPU for the Enterprise tier; see the pricing note below
GPU / AI relevance Outposts can host GPU-enabled instance types for on-prem inference while training runs in-Region Arc-enabled Kubernetes gives you one policy and monitoring plane over GPU clusters wherever they are; Arc-enabled ML services extend the pattern GKE fleet management over GPU node pools in multiple locations; the most natural fit if your serving stack is already Kubernetes

Sources: Google Distributed Cloud software-only docs (naming history) GKE Enterprise release notes Azure Arc documentation

Correction — "Anthos" is not a thing you buy any more

Your brief asked about "the current state of Anthos / GKE Enterprise," and the answer is that the rebrand went further than a rename. Anthos launched in 2019 as a paid subscription that unlocked features including GKE On-Prem. In late 2023 Google folded it into GKE Enterprise. Since around September 2025, "Anthos" no longer names a tier or edition at all — most former Anthos capabilities are now included in base GKE, and what remains chargeable is a set of optional SKUs layered on standard GKE: Cloud Service Mesh, multi-cloud cluster management, Backup for GKE, extended support, and multi-cluster Gateway.

The practical consequence is a billing trap worth knowing about: a single-region, single-cluster team that enabled the GKE Enterprise tier "because Enterprise sounded right" can be paying a per-vCPU management fee for capabilities they never use. If you inherit a GKE estate, check whether the Enterprise API is enabled and whether anything actually depends on it. Meanwhile, GCP guidance's GCP source mentions Anthos exactly twice in passing and treats it as current — it isn't.

Pass 3 · trade-offs

Hybrid is a destination for some workloads and a phase for most. Applications you genuinely retained — sovereignty, physical dependency — are permanently hybrid, and a control plane is worth buying for them. But most hybrid connectivity exists because a migration is in progress, and that is a temporary condition you should be actively trying to end. A hybrid link that was supposed to last eighteen months and is still there at year five is a sign that the migration stalled — the infrastructure equivalent of the strangler fig that never finished.

Latency is the constraint nobody models. Splitting an application across the hybrid boundary is fine for an API edge and catastrophic for a chatty one, which is exactly the third component of data gravity from Session 1. A page render doing 200 database queries at 0.5 ms locally becomes 200 queries at 15 ms across a link — three seconds instead of a tenth of one. Measure the query count per request before you plan to split anything across the gap.

Consistency has three meanings and vendors conflate them. Consistent APIs (Outposts), consistent governance (Arc), and consistent runtime (GKE Enterprise) are different products solving different problems. Ask which one you actually need. Most enterprises discover they need governance consistency far more urgently than API consistency, which is a good part of why Arc has done as well as it has.

Hybrid is not multi-cloud, and multi-cloud is not portability. Running things on two clouds gives you redundancy and negotiating leverage and costs you a second set of everything. Actual portability requires designing for it — containers, open formats, no proprietary managed services in the critical path — and that design costs you the leverage of the managed services you didn't use. There is no free version of this trade-off; there is only being deliberate about which side you're on.

Decision tree · guard clauses
Which migration service for this source?
Answer in order. "No" falls through. The first "yes" exits right. Bottom-left is the default.
Q1Is this just data — files or objects with no compute attached?
yes ⟶
Bulk transfer pathDataSync / Storage Mover / Storage Transfer Service. Then run the crossover formula below to decide online versus physical.
no ↓
Q2Is it only a database, with the application either staying put or being rebuilt separately?
yes ⟶
Database migration serviceDMS / Azure DMS or the Arc experience / GCP DMS. Use CDC for near-zero downtime. If it's heterogeneous, budget for schema conversion as its own project.
no ↓
Q3Did you decide to retain it — sovereignty, physical dependency, or unmovable latency requirement?
yes ⟶
Hybrid platformOutposts if you need AWS services locally; Arc if you need governance consistency across a mixed estate; GKE Enterprise / GDC if the workload is containerised.
no ↓
Q4Is a whole virtualised estate moving together, where keeping vCenter and existing runbooks matters more than native instances?
yes ⟶
Relocate to a managed VMware serviceVMware Cloud on AWS or Amazon EVS; Azure VMware Solution; Google Cloud VMware Engine. Hypervisor-level, no per-VM conversion.
no ↓
Q5Can the application run in a container with no code changes — standard runtime, supported OS, no kernel dependencies?
yes ⟶
Containerisation toolApp2Container or AWS Transform; Azure Migrate App Containerization; Migrate to Containers CLI. Check language support first — coverage is narrower than the marketing suggests.
no ↓
Default — bottom left VM replication service AWS Transform MGN · Azure Migrate: Server Migration · Migrate to Virtual Machines. Agent on the source, continuous block-level replication, test-launch as many times as you like into an isolated subnet, then cut over. This is the default because rehost is the default — most of any real portfolio ends up here, and that's the correct outcome, not a failure of ambition.
S3·4Reality
check

Worked on paper: what it costs and takes to move 10 TB

This is the calculation that settles more architecture arguments than any other in this stage, and it takes two minutes. The dataset: 10 TB of model weights and training data. The question: network or appliance, and what does it cost?

Step 1 — transfer time on three different links

Work in decimal units. 10 TB = 10,000 GB = 80,000 gigabits. The formula from Session 1: days = TB ÷ (10.8 × Gbps × efficiency).

LinkEffective throughputTime for 10 TBVerdict
200 Mbps shared office line, 50% usable100 Mbps10 ÷ (10.8 × 0.2 × 0.5) = 9.3 daysPainful, and it saturates the link your business runs on
1 Gbps dedicated, 70% efficiency700 Mbps10 ÷ (10.8 × 1 × 0.7) = 1.3 daysFine. Start Friday evening, done by Sunday.
10 Gbps interconnect, 70% efficiency7 Gbps10 ÷ (10.8 × 10 × 0.7) = 3.2 hoursA coffee break

Step 2 — the appliance, and the crossover

An appliance's total elapsed time is not its transfer speed — the local copy is fast (Google quotes up to 40 Gbps onto a Transfer Appliance if your local network supports it). The elapsed time is the logistics: request the device, wait for shipping, load it, ship it back, wait for ingestion. Call it 7–10 days end to end, and Google's own guidance is that the appliance is for datasets above 20 TB or transfers that would take more than a week.

The crossover formula

Appliance wins when: TB > 10.8 × Gbps × efficiency × (appliance round-trip days)

With a 10-day round trip and 70% efficiency, that's roughly 75 TB on a 1 Gbps link, 7.5 TB on a 100 Mbps link, and 750 TB on a 10 Gbps link.

So for our 10 TB: network wins on everything except the shared office line, and even there it's close. The appliance is the wrong tool here, and this is exactly the trap — "10 TB" sounds like a lot, so people reach for the appliance without doing the arithmetic. Ten terabytes is a weekend on a decent link.

Elapsed days versus dataset size — where the lines cross is your decision dataset size ⟶ elapsed days ⟶ 10 TB50 TB100 TB 250 TB500 TB 5102040 appliance — flat ~10 days regardless of size 1 Gbps network 100 Mbps 10 Gbps interconnect crossover ~7.5 TB crossover ~75 TB network wins ◂ here
The appliance line is flat — that's the whole insight. Its elapsed time barely changes between 10 TB and 400 TB, because it's dominated by shipping. Network time scales linearly with size. So the appliance is not "the big-data option," it is "the slow-link option," and your link speed moves the crossover by an order of magnitude in either direction.

Step 3 — the cost side, which is where clouds diverge

Ingress is free on all three clouds. Egress is not, and it is charged by whoever you are leaving. At mid-2026 first-tier internet rates:

Moving 10 TB out of…AWSAzureGCP Premium Tier
Per-GB rate~$0.09~$0.087~$0.12
10 TB total~$900~$870~$1,140–1,200
Inter-region within the same cloudTypically ~$0.02/GB — cheaper than internet egress but not free. Cross-AZ transfer is around $0.01/GB each way and is the charge most people forget entirely.
Hidden multipliersNAT gateway data processing (~$0.045/GB on AWS) stacks on top of egress. A transfer routed through a NAT gateway costs roughly 50% more than the headline rate. Route bulk transfers through a gateway endpoint or a private link, not through NAT.
The regulatory change that will reshape this — and the fine print

Following the EU Data Act, all three hyperscalers introduced free egress for customers leaving the platform. Read the conditions, because they are narrower than the headlines: Google and Microsoft require you to terminate the account and complete the transfer within 60 days; AWS also uses a 60-day window but does not require you to close your account, though it applies additional scrutiny to repeat applications. None of these waivers apply to ordinary business egress — only to a genuine exit.

The bigger date is ahead: the EU Data Act bans cloud switching and egress charges outright from 12 January 2027, following a transition period that began in 2025. If you are modelling a cross-cloud migration for next year, that changes the economics materially, and it is worth checking the current state of implementation rather than assuming — this is exactly the sort of thing that shifts between when a page is written and when you read it.

Three cited examples worth knowing

Grounding · current sources, last six months
  • AWS is exiting offline data transfer — the most consequential news in this session. The Snow Family closed to new customers on 7 November 2025, and AWS has published an end-of-support notice for all Snowball devices in all commercial Regions on 31 December 2026, after which the Snow Console becomes inaccessible. AWS's stated reasoning is that network transfer improvements made online migration faster and cheaper and that customers strongly prefer it. The replacements are DataSync for online transfer, the Data Transfer Terminal for physical drop-off, and Outposts for edge compute. This is a genuine three-cloud divergence: Azure Data Box and Google Transfer Appliance remain fully available.
    aws.amazon.com/snowball — end of support notice, page updated 27 July 2026
  • Data gravity is inverting the standard architecture for AI workloads. The assumption that data moves to compute is breaking at AI scale — moving hundreds of terabytes across clouds can cost comparably to the compute itself, sovereignty rules increasingly forbid it, and open formats have made compute more portable than data. The emerging pattern is federated: keep raw data where it is, move only model weights and aggregates, and place compute next to the data. One published data-gravity calculator makes the economics concrete: at 50 TB, the gravity penalty against AWS compute at $0.09/GB egress works out around 20%, against GCP at $0.12/GB around 34%, and against a near-zero-egress GPU provider around 1%. Egress rate, not GPU hourly rate, dominates the placement decision at that scale.
    Data gravity calculator methodology, April 2026 VAST Data on multi-cloud data gravity, June 2026
  • Wave planning and dependency mapping became console features this year. Azure Migrate shipped Wave Planning in public preview alongside Arc-based discovery that can assess Arc-enabled servers without deploying additional infrastructure, generating business cases within an hour. AWS Transform's VMware agent orchestrates dependency mapping and intelligent wave planning as part of the migration workflow. The practice you learned in Session 1 by hand is now partially automated on two of the three clouds — which is a good reason to understand it by hand, because you will be reviewing what the tool proposes rather than producing it.
    What's new in Azure Migrate AWS Migration & Modernization announcements
S3·5Apply it
your context

Apply it — moving your own model-serving stack

Case A — Modal to GKE

This is the shape of migration everything in this stage says is easy, and it's worth walking through to see exactly which layers of tooling you don't need. You need none of layers 1 through 4. No discovery — you know what you have. No VM replication — there is no VM, and even if there were, you would not want a block-level copy of it. No containerisation tool — it's already a container. No database migration — there is no database.

What's actually involved: build or re-tag the vLLM image into Artifact Registry; write a KServe InferenceService or a plain Deployment plus Service; create a GPU node pool with the right accelerator, taints and tolerations; set the autoscaler bounds you had on Modal; move the weights into a GCS bucket in the same region as the node pool; and point the model path at it. The genuinely new work is the parts Modal was doing for you invisibly — scale-to-zero behaviour, cold-start handling, and request queueing — which now become explicit configuration. That's a replatform, and the difficulty is in the platform semantics you inherit, not in moving anything.

Layer 5 is the only one that applies at all, and only for the weights — which, as established in Session 1, have fake gravity. If they're on Hugging Face, don't migrate them; re-pull them at the destination. Migration is for data you cannot re-derive.

Case B — GCP to AWS, the harder direction

Cross-cloud is where the abstractions stop being free, and the interesting part is that the container is still the easy bit. Walk the layers:

  • The container is portable — GKE to EKS is a manifest translation, not a rebuild. The image runs unchanged.
  • The GPU is a real decision. Your L4 and T4 experience maps onto different AWS instance families with different memory, different interconnect and different spot dynamics. Re-benchmark rather than assuming equivalence — throughput per dollar is not portable even when the code is.
  • Identity does not port at all. GCP Workload Identity becomes IAM Roles for Service Accounts. Same concept, entirely different configuration, and this is reliably where a cross-cloud move actually stalls.
  • The data has to move, and you pay on the way out. This is where the arithmetic above earns its keep. Your irreplaceable data — fine-tuning sets, eval suites with golden outputs, request telemetry — is probably single-digit terabytes, so at GCP's ~$0.12/GB you're looking at low hundreds of dollars and a few hours on a decent link. If you were exiting GCP entirely you might qualify for the exit-egress waiver; for a partial move you pay list.
  • Spot/preemptible semantics differ. Your autoscaling 1–3 spot configuration has an AWS equivalent, but preemption notice periods and reclaim behaviour are not the same, and inference services care about that.

The honest summary: a week of work, most of it identity and benchmarking, none of it data migration in the sense this session has been describing. Compare that with LEDGER-CORE's thirty-week single-slice strangle in Session 2 and you have the clearest possible statement of what cloud-native architecture actually buys you. It is not performance and it is not cost — it is optionality, and migration is when you cash it in.

Optional hands-on lab — run one real migration end to end

One lab, one cloud, smallest possible everything. The goal is to feel the replication-and-cutover loop once, because reading about a test launch is not the same as doing one.

Option 1 · the rehost loop
Migrate one tiny VM with a replication service

Create a single minimal VM in cloud A — smallest burstable SKU, small disk, a static web page on it so you can tell it's the right machine. Then use cloud B's VM-replication service to migrate it: install the agent, watch replication complete, launch a test instance into an isolated subnet, verify the page, then cut over.

What you're there to observe: that the test launch costs nothing and can be repeated, and that the source keeps running the whole time. That property is the entire reason this class of tool exists.

Option 2 · the gravity loop
Calibrate the transfer formula against reality

Generate a few GB of files. Move them to a bucket with the managed transfer service rather than a plain CLI copy — you want to see the job semantics: scheduling, incremental re-runs, integrity validation, and resumption after you deliberately kill it mid-transfer.

Then compute your achieved throughput, plug it into the crossover formula as your real efficiency factor, and work out where your appliance crossover sits. That number is more useful to you than any published benchmark.

Cost guard rails and teardown — this lab bills in ways the others didn't
  1. Budget alert before anything else. A budget with an alert at a low threshold — single-digit dollars. Free on all three clouds, two minutes, non-negotiable for this lab specifically because replication tasks bill continuously and silently.
  2. Smallest SKU, free tier, no GPUs. Nothing here needs a GPU. A burstable micro/small instance with the minimum disk is enough. Stay in one region — cross-region transfer bills even between your own resources.
  3. Know what bills while you sleep: the replication agent and its staging storage; the staging-area volumes and any snapshots they leave behind; the target instance from the moment a test launch starts, not from cutover; any load balancer or public IP address you created; and data transfer out if you download anything back.
  4. Teardown, in this exact order — the order matters:
    Disconnect and delete the replication task or source server entry first, and uninstall the agent from the source. Deleting the target instance while replication is still configured leaves the task running and billing.
    ② Terminate every target instance, including test-launch instances — these are easy to miss because they live in a separate isolated subnet you stopped looking at.
    ③ Delete the staging-area volumes and snapshots. Replication services create these automatically and frequently do not remove them.
    ④ Delete load balancers, public IPs and NAT gateways. These bill hourly regardless of traffic and outlive the instance that prompted them.
    ⑤ Delete the source VM and the buckets.
    Check the bill 48 hours later, not the console. The console shows what exists; the bill shows what's charging. They disagree more often than they should.
  5. The specific trap in this lab: migration services are designed to be resilient and to keep trying. That is exactly the wrong property in a teardown. Remove the replication configuration before you remove anything it points at.
S3·6Stage
close

What you can now do

Trace the arc backwards and the shape of the stage is clear. You can look at an application and choose an R with reasons you can defend, and you know that the choice composes over time rather than being permanent. You can take a portfolio, map its dependencies, distinguish an API edge from a shared schema, and sequence it into waves where the heaviest dataset sets the pace and the first wave is a rehearsal. You can take a monolith you're not allowed to stop and shrink it one slice at a time with a facade, an anti-corruption layer, and a reconciliation gate before the one-way door. You can do the arithmetic on transfer time, egress cost, and the appliance crossover in your head. You know what AWS, Azure and Google actually sell at each of the five tooling layers, which three product names in the materials are dead, and that AWS is leaving the appliance business at the end of this year.

And you can explain — precisely, not vaguely — why your own serving stack is a week of work while LEDGER-CORE is thirty weeks per slice. Statelessness, externalised state, and containerisation are usually sold as operational properties. They are also, and perhaps more importantly, the properties that determine whether you are ever able to leave.

The one thing to carry forward

Every architectural decision you make from here has a migration cost attached to it, payable later, by someone who may be you. The managed service that saves you three weeks now is the thing that pins you in place in four years. That's not an argument against using managed services — it's an argument for knowing which ones you've chosen deliberately and which ones you drifted into. Portability is not a property you add at migration time. It is a property you either preserved or spent.

C9
complete

Commands available: "re-teach tab X" "go deeper on X" "more visual in tab X" "compare harder in tab X" "ground tab X" "fix file". Each returns the full updated file with all other tabs preserved.

Highest-value next moves for this stage specifically: "compare harder in tab 3" to expand the five comparison tables with more rows, or "go deeper on dual-write" — the data half of S2 is the part that most often gets underestimated in a real programme.

← C8The path
Next stage · C10 →genaipros · C9 · Migration & ModernizationAI for Everyone ↗