---
title: 'Cloud Migration Strategies'
source: 'https://academia.sh/en/courses/cloud-fundamentals/cloud-migration-strategies'
course: 'Cloud Fundamentals'
language: en
updated: '2026-09-13T05:07:33+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Compares three migration strategies against the same item set in terms of the decision handed over, migration days, and the provider-specific item'
    - 'Counts staging: the service moved per wave, how long the two systems run together, and the item left behind'
    - 'Measures the cost of not moving and computes the annual load of the case where the two systems never stop running together'
    - 'Derives the item each strategy fails to win and shows that a per-item choice beats uniform strategies'
---

# Cloud Migration Strategies

Comparing rehost, replatform, and refactor across the same ten-item set: the decision handed over, migration days, the provider-specific item that makes exit harder, the wave count and how long the two systems run together, the annual load of the item left behind, and the cost of a dual system that never ends.

The previous lesson measured the terms under which capacity is rented and found that
three different models won across three load profiles. All of those calculations were
made under one silent assumption: that the work to be moved is **already rented**. But
the fictional regional measurement network runs today in its own room.

Three paths are measured here. **Rehost** moves the item as-is onto a rented machine; the
code does not change. **Replatform** replaces some of the item's parts with managed
counterparts; the interface layer is rewritten. **Refactor** rewrites the item from
scratch around rented building blocks. The common migration frameworks also count
repurchasing an item as a bought service, retiring it, or leaving it where it is; this
lesson stays with the three because it compares three depths of moving the same item.
The wave mechanics of a staged rollout and the pattern of wrapping the old system piece
by piece were measured in earlier courses; what
is measured here is not the wave itself but the annual cost of the case where the waves
**never finish**.

## The Item Set and Three Strategies

- **CG25.** The item set is 10 services; each item's size (1–3), annual operating days,
  and annual change count are fictional.
- **CG26.** Strategy profiles are fixed per item and written in the model file: the
  decisions handed over are 3, 7, and 11, respectively.
- **CG27.** The decision horizon is 5 years; an item whose five-year net gain is not
  above zero is not moved.
- **CG28.** The team processes 20 migration days per wave; a wave takes 30 calendar days.
- **CG29.** As long as the two systems run together, 1.5 extra operating days accrue per
  month. If any item is left behind, this cost never ends.
- **CG30.** On the mixed path, each item gets the strategy that gives the highest
  five-year net.

```js
// migration/model.mjs — migration is a MODEL: the fictional measurement network's ten items and three
// strategy profiles. There is no real migration tool, provider, or calendar; every number is fictional.
// name, size (1-3), annual operating days, annual change count
export const ITEM = [
  ["read-collector", 3, 22, 30], ["validator", 2, 14, 18], ["billing", 3, 18, 12],
  ["work-order-service", 2, 10, 9], ["subscriber-portal", 2, 12, 24], ["nightly-batch-job", 1, 8, 4],
  ["read-store", 3, 20, 3], ["tariff-store", 1, 6, 2], ["report-endpoint", 1, 3, 1],
  ["identity-directory", 1, 5, 2],
];

// handoff: decisions handed over per item; drop: share dropped from operating load; delivery: days gained
// per change; days: migration days per unit size; specific: number of provider-specific items per item
export const STRATEGY = {
  rehost: { handoff: 3, drop: 0.15, delivery: 0.05, days: 2, specific: 1, rewrite: "unchanged" },
  replatform: { handoff: 7, drop: 0.55, delivery: 0.20, days: 9, specific: 3, rewrite: "partial" },
  refactor: { handoff: 11, drop: 0.80, delivery: 0.70, days: 34, specific: 5, rewrite: "full" },
};
export const NAME = Object.keys(STRATEGY);
export const HORIZON = 5, WAVE_CAP = 20, WAVE_DAYS = 30, DUAL_MONTH = 1.5;  // fictional

export const migrationDays = (k, s) => STRATEGY[s].days * k[1];
export const gain = (k, s) => k[2] * STRATEGY[s].drop + k[3] * STRATEGY[s].delivery;
export const net = (k, s) => gain(k, s) * HORIZON - migrationDays(k, s);
export const best = (k) => NAME.reduce((a, s) => (net(k, s) > net(k, a) ? s : a), NAME[0]);

// One path: one strategy per item. An item whose net gain stays below zero is not moved.
export function run(pick) {
  const moved = ITEM.filter((k) => net(k, pick(k)) > 0);
  const left = ITEM.filter((k) => net(k, pick(k)) <= 0);
  const sum = (f) => moved.reduce((a, k) => a + f(k), 0);
  const days = sum((k) => migrationDays(k, pick(k)));
  const waves = Math.ceil(days / WAVE_CAP), together = waves * WAVE_DAYS;
  const transition = (together / 30) * DUAL_MONTH;
  const persistent = left.length ? DUAL_MONTH * 12 : 0;
  const annual = sum((k) => gain(k, pick(k))) - persistent;
  return {
    moved: moved.length, left: left.length, days, waves, together, transition, persistent, annual,
    handoff: sum((k) => STRATEGY[pick(k)].handoff),
    specific: sum((k) => STRATEGY[pick(k)].specific),
    remainingLoad: sum((k) => k[2] * (1 - STRATEGY[pick(k)].drop)) + left.reduce((a, k) => a + k[2], 0),
    leftLoad: left.reduce((a, k) => a + k[2], 0),
    net5: annual * HORIZON - days - transition,
  };
}
```

## Three Strategies on the Same Set

```js
// migration/strategy.mjs — three strategies on the same item set: decisions handed over,
// item rewritten, migration days, and the provider-specific item that makes exit harder
import { ITEM, STRATEGY, NAME, HORIZON, run, net, best } from "./model.mjs";

const s = (x, n) => String(x).padStart(n);
const y = (x, n = 1) => x.toFixed(n);
const SHORT = { rehost: "rehost", replatform: "replatform",
  refactor: "refactor" };
const R = Object.fromEntries(NAME.map((a) => [a, run(() => a)]));
R.mixed = run(best);
const PATH = [...NAME, "mixed"];

console.log(`${ITEM.length} items, decision horizon ${HORIZON} years; every number is FICTIONAL ` +
  `and in "operating days" and "migration days".`);
console.log();
console.log("measure                           | rehost      | replatform   | refactor   | mixed  ");
console.log("----------------------------------|-------------|--------------|------------|--------");
for (const [name, f] of [
  ["items moved", (r) => `${r.moved}/${ITEM.length}`],
  ["decisions handed over", (r) => r.handoff],
  ["item rewritten", (r, a) => (a === "mixed" ? "mixed" : STRATEGY[a].rewrite)],
  ["migration days (total)", (r) => r.days],
  ["provider-specific items (exit)", (r) => r.specific],
  ["annual gain (operating days)", (r) => y(r.annual)],
  ["remaining annual operating load", (r) => y(r.remainingLoad)]])
  console.log(`${name.padEnd(33)} | ${s(f(R[PATH[0]], PATH[0]), 11)} | ${s(f(R[PATH[1]], PATH[1]), 12)} | ` +
    `${s(f(R[PATH[2]], PATH[2]), 10)} | ${s(f(R.mixed, "mixed"), 7)}`);

console.log();
console.log(`${HORIZON}-year net gain per item (operating days; the highest is chosen)`);
console.log("item                 | size     | load   | change   | rehost     | replatform   | refactor   | choice      ");
console.log("---------------------|----------|--------|----------|------------|--------------|------------|-------------");
for (const k of ITEM) {
  const n = NAME.map((a) => net(k, a));
  console.log(`${k[0].padEnd(20)} | ${s(k[1], 8)} | ${s(k[2], 6)} | ${s(k[3], 8)} | ` +
    `${s(y(n[0]), 10)} | ${s(y(n[1]), 12)} | ${s(y(n[2]), 10)} | ${SHORT[best(k)]}`);
}
const count = (a) => ITEM.filter((k) => best(k) === a).length;
console.log(`choice distribution: ` + NAME.map((a) => `${a} ${count(a)}`).join(", ") +
  `; all three strategies win on at least one item.`);
```

```
10 items, decision horizon 5 years; every number is FICTIONAL and in "operating days" and "migration days".

measure                           | rehost      | replatform   | refactor   | mixed  
----------------------------------|-------------|--------------|------------|--------
items moved                       |       10/10 |        10/10 |       6/10 |   10/10
decisions handed over             |          30 |           70 |         66 |      78
item rewritten                    |   unchanged |      partial |       full |   mixed
migration days (total)            |          38 |          171 |        442 |     339
provider-specific items (exit)    |          10 |           30 |         30 |      34
annual gain (operating days)      |        22.9 |         85.9 |      117.1 |   132.6
remaining annual operating load   |       100.3 |         53.1 |       50.8 |    42.3

5-year net gain per item (operating days; the highest is chosen)
item                 | size     | load   | change   | rehost     | replatform   | refactor   | choice      
---------------------|----------|--------|----------|------------|--------------|------------|-------------
read-collector       |        3 |     22 |       30 |       18.0 |         63.5 |       91.0 | refactor
validator            |        2 |     14 |       18 |       11.0 |         38.5 |       51.0 | refactor
billing              |        3 |     18 |       12 |       10.5 |         34.5 |       12.0 | replatform
work-order-service   |        2 |     10 |        9 |        5.8 |         18.5 |        3.5 | replatform
subscriber-portal    |        2 |     12 |       24 |       11.0 |         39.0 |       64.0 | refactor
nightly-batch-job    |        1 |      8 |        4 |        5.0 |         17.0 |       12.0 | replatform
read-store           |        3 |     20 |        3 |        9.8 |         31.0 |      -11.5 | replatform
tariff-store         |        1 |      6 |        2 |        3.0 |          9.5 |       -3.0 | replatform
report-endpoint      |        1 |      3 |        1 |        0.5 |          0.3 |      -18.5 | rehost
identity-directory   |        1 |      5 |        2 |        2.3 |          6.8 |       -7.0 | replatform
choice distribution: rehost 1, replatform 6, refactor 3; all three strategies win on at least one item.
```

The decisions handed over are 30, 70, and 66. Refactor's 66 is not a saving but a
**shortfall**: it hands over 11 decisions per item, yet can only move six of the ten
items. Migration days climb from 38 to 171 and to 442, and the provider-specific items
that make exit harder rise from 10 to 30. Rehost gains the least (22.9 operating days
annually) but is the path that harms exit the least.

The second table shows where this gain comes from. What the three items refactor wins
have in common is not load but **change** count: 30, 18, and 24. The read store, which
changes only 3 times a year, is the second-heaviest item by load (20 annual days), yet
nets **-11.5** under refactor; the payoff of rewriting comes not from operating load but
from **cheaper changes**. The report endpoint is the extreme case: size 1, load 3, change
1, and **-18.5** under refactor — **on a small, static service, refactor never pays back
within five years**; the best choice there is rehost, at 0.5. The choice distribution is
1, 6, and 3: all three strategies win on at least one item.

## Staging and the Cost of Not Moving

```js
// migration/wave.mjs — staging and the cost of not moving: service per wave, how long the
// two systems run together, the annual load left behind, and the dual system that never ends
import { NAME, WAVE_CAP, WAVE_DAYS, DUAL_MONTH, run, best } from "./model.mjs";

const s = (x, n) => String(x).padStart(n);
const y = (x, n = 1) => x.toFixed(n);
const R = { ...Object.fromEntries(NAME.map((a) => [a, run(() => a)])), mixed: run(best) };
const PATH = [["rehost", NAME[0]], ["replatform", NAME[1]], ["refactor", NAME[2]], ["mixed", "mixed"]];

console.log(`wave capacity ${WAVE_CAP} migration days, wave duration ${WAVE_DAYS} calendar days; ` +
  `as long as the two systems run together, ${DUAL_MONTH} extra operating days accrue per month (fictional).`);
console.log();
console.log("path         | migration days   | waves   | items/wave   | together   | left   | dual system   | 5-year net  ");
console.log("-------------|------------------|---------|--------------|------------|--------|---------------|-------------");
for (const [name, v] of PATH) {
  const r = R[v];
  console.log(`${name.padEnd(12)} | ${s(r.days, 16)} | ${s(r.waves, 7)} | ${s(y(r.moved / r.waves), 12)} | ` +
    `${s(`${r.together} d`, 10)} | ${s(r.left, 6)} | ` +
    `${s(r.persistent ? `${y(r.persistent)}/yr` : "ends", 13)} | ${s(y(r.net5), 12)}`);
}
const m = R[NAME[2]];
console.log(`transition cost (one-time): ` + PATH.map(([a, v]) => `${a} ${y(R[v].transition)}`).join(", ") + ".");
console.log(`refactor leaves ${m.left} items behind; their annual load of ${y(m.leftLoad)} days ` +
  `and the dual system at ${y(m.persistent)} days/yr never end.`);
```

```
wave capacity 20 migration days, wave duration 30 calendar days; as long as the two systems run together, 1.5 extra operating days accrue per month (fictional).

path         | migration days   | waves   | items/wave   | together   | left   | dual system   | 5-year net  
-------------|------------------|---------|--------------|------------|--------|---------------|-------------
rehost       |               38 |       2 |          5.0 |       60 d |      0 |          ends |         73.7
replatform   |              171 |       9 |          1.1 |      270 d |      0 |          ends |        245.0
refactor     |              442 |      23 |          0.3 |      690 d |      4 |       18.0/yr |        109.0
mixed        |              339 |      17 |          0.6 |      510 d |      0 |          ends |        298.3
transition cost (one-time): rehost 3.0, replatform 13.5, refactor 34.5, mixed 25.5.
refactor leaves 4 items behind; their annual load of 34.0 days and the dual system at 18.0 days/yr never end.
```

Staging converts the wave count into a calendar. Rehost finishes in 2 waves and moves
**5.0 services per wave**; replatform falls to 1.1, and refactor to **0.3 services** —
most waves cannot even finish a single service. The two systems run together for 60,
270, and **690 days**, and the transition cost that accrues over that time is 3.0, 13.5,
and 34.5 operating days.

The real item is in the last two columns. For rehost and replatform, the dual system
**ends**; for refactor it does not, because four items are never moved. Those four
items' annual operating load of **34.0 days** stays as it is, and on top of it, the dual
system adds **18.0 days/year** permanently. Not moving is not a saving; it is an
unending subscription: the path that is second in annual gain (117.1) drops to third in
the five-year net, at **109.0**, while replatform posts 245.0.

The mixed path beats them all: 339 migration days, 17 waves, **0** left behind, and a
five-year net of **298.3** — the cost of applying a single strategy to the whole set is
53.3 operating days relative to the best uniform path.

## Summary

- The three strategies hand over 30, 70, and 66 decisions across the same ten items;
  migration days are 38, 171, and 442, and provider-specific items are 10, 30, and 30.
  Refactor is second in annual gain (117.1 days) but third in the five-year net (109.0
  against 245.0).
- The payoff of rewriting comes from change count, not operating load: the three items it
  wins have annual changes of 30, 18, and 24, while the read store, which changes only 3
  times a year, nets -11.5. It posts -18.5 on the small, static report endpoint; the best
  choice there is rehost (0.5).
- Staging moves 5.0, 1.1, and 0.3 services per wave; the two systems run together for 60,
  270, and 690 days, and the transition cost is 3.0, 13.5, and 34.5 operating days.
- Not moving is an unending cost: the 34.0-day annual load of the four items left behind
  does not shrink, and the dual system does not end at 18.0 days/year. The mixed path,
  choosing per item, leaves nothing behind and posts 298.3 in the five-year net.

## Course Wrap-Up

| Lesson | Decision Handed Over | Received in Exchange | Cannot Carry at Exit |
|---|---|---|---|
| What Is Cloud Computing | 3 decisions (purchase, quantity, placement) | wait 30.0 → 1.0 days | 4 of 8 items |
| Service Models | 5 / 23 / 25 of 26 | touch 91 → 82 / 19 / 4 | embedded 2 / 8 / 17 decisions |
| Deployment Models | 16/24 of the checks | elasticity window 21.0 → 1.0 days | 16 check items, 6 boundary bindings |
| Comparison with On-Premises | ownership, 8-unit upfront purchase | hidden share 64% → 13% | 250 fu exit fee |
| Shared Responsibility Model | 6 / 16 / 20 of 24 | left with the customer 18 → 8 → 4 | negotiable 6 / 16 / 20 items |
| Regions and Availability Zones | placement of 6 of 13 items | 0 extra capacity cost | distribution definition of 6 items |
| Edge Locations | 3 decisions (location, routing, eviction) | latency drop 21.0% | warmed-up cache, +30.5% load |
| The Pillars of the Design Framework | 8 of 12 decisions | operations +0.63, security +1.00 | 6 of 8 handoffs (43.75%) |
| Pricing Models | 0 / 1 / 2 decisions | on-demand 61.3% more expensive in the flat profile | remaining commitment 2,083.20 units |
| Cloud Migration Strategies | 30 / 70 / 66 decisions | annual 22.9 / 85.9 / 117.1 days | provider-specific 10 / 30 / 30 |

The course's rule is the same across all ten rows: **leasing is handing over a decision;
every decision handed over carries a gain and an exit cost.** Without the middle column,
the left column is a list of losses; without the right column, the middle column is a
sales pitch.

The last column, across ten rows, comes down to four families. A **decision embedded in
the service** recurs across four lessons (service models, shared responsibility,
pillars, migration strategies): the item moves, the decision that configures it does
not. A **distribution operated by the provider and never visible** appears in two
lessons (deployment models, regions): something that cannot be tested has no definition
to carry either. **State accumulated over time** appears in two lessons (performance
history, warmed-up cache). The **remaining liability the contract writes down** appears
in two lessons (exit fee, remaining commitment) and, of the four, is the only family
that is visible up front. The remaining three are discovered only at the moment of exit,
unless they are measured beforehand.

The decision to lease was made, its depth and pattern were chosen, the responsibility
boundary was drawn, its geography and price were set, and the path of moving it was
measured. Yet the **most concrete thing** being rented was never taken up in these ten
lessons: the machine itself, and the network that connects those machines to one
another. Capacity was always counted as an abstract "unit," the network always as a
"latency." **M23/K02 Compute and Networking in the Cloud** opens up those two
abstractions: what the difference between rented machine types is measured by, what
items a network is built from, and how many decisions the path between two machines
carries.
