---
cuppy_hub: gcp
cuppy_path: guides/parity-and-migration-method.md
cuppy_section: docs
cuppy_doc: PMVR-NGH4
cuppy_doc_uuid: 6359dd4c-e8b7-4825-8512-a76dcbbee152
cuppy_permalink: https://cuppy.io/gcp/d/PMVR-NGH4
cuppy_version: 1
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/gcp/docs/guides/parity-and-migration-method
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: 7aa8e4b6ed074cd946f931e3a0638ee98e44dd69658c63e0e80ee102a7d6dd89
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# Using the three hubs for one estimate

cuppy serves three vendor hubs — **`aws`**, **`azure`** and **`gcp`** — and each is written to the same
shape: a reference per service, an error catalogue per family, guides per intent. This hub adds one thing the
other two do not yet have: **a parity guide per family**, whose job is not to list counterpart names but to
list the **documented differences that change an estimate**.

This document is the method those guides serve.

## Phase 0 — decide what question you are answering

Three different questions get called "a migration estimate", and they need different work:

| Question | What it needs |
|---|---|
| **"roughly, what would this cost over there?"** | phases 1 and 4. Hours |
| **"what would it cost, and what would we have to change?"** | phases 1 to 4. Days |
| **"commit to a number and a date"** | all six phases, plus one wave actually executed. Weeks |

Answering the third with the first one's work is the most common failure, and it is not a technical one.

## Phase 1 — inventory and **measure**

Use the destination cloud's own assessment tool — on Google Cloud, **Migration Center**, which explicitly
covers "on-premises or **other cloud** environments". Run it **once per candidate destination**: the inventory
is the same, the pricing and the technical-fit analysis are the target's own, and two runs is how you compare
two destinations honestly.

The eight measurements, each with the estimate line it feeds:

| # | Measure | Feeds |
|---|---|---|
| 1 | **utilisation**, not provisioned capacity | right-sizing — usually the largest saving available |
| 2 | **network dependencies** between systems | the **wave** boundaries |
| 3 | **bytes to move**, by dataset | egress, and the transfer window |
| 4 | **identities, keys and secrets** per workload | the identity line, and the keys you can delete |
| 5 | **logs GB/day, metric count and label cardinality, trace volume** | the observability line |
| 6 | **count of dashboards and alerting policies** | effort — they are re-created, never migrated |
| 7 | **permissions each workload actually used** | the role-mapping work |
| 8 | **request/query profile** (bytes scanned, RU/s, average message size, requests per second) | every service whose billing dimension differs from the source's |

**An estimate missing #1, #2 or #3 is not an estimate.** Full detail and the failure mode of skipping each:
`guides/migration/assess-before-you-move.md`.

## Phase 2 — map the names, then stop trusting the map

Open the parity guide for each family in scope — `guides/parity/identity.md`, `.../iac.md`, `.../storage.md`,
`.../compute.md`, `.../networking.md`, `.../databases.md`, `.../messaging.md`, `.../data.md`,
`.../observability.md`, `.../migration.md` — and take §1 of each, the name table.

Three rules, each learned from a published table being misleading rather than wrong:

1. **Prefer a product page to a mapping table.** Microsoft's table pairs Cloud Deployment Manager with Azure
   Resource Manager; Deployment Manager reached **end of support on 31 March 2026**. Google's own table is
   dated **December 2024**.
2. **A one-to-many row is a finding, not a formatting problem.** Microsoft maps **Pub/Sub to three** Azure
   services and **Spanner to two**. One-to-many means the source product's jobs are *divided* on the target, and
   the division is per topic, per database, per workload — triage work that belongs in the estimate.
3. **A name match is not a capability match.** Both tables map **Bigtable to Azure Table Storage**. Treat
   every row as a starting point for phase 3, never as a conclusion.

## Phase 3 — price the **differences**, in five classes

Every parity guide in this hub reports the same five classes, because these are the five that move a number:

| Class | What to look for | Worked example from this hub |
|---|---|---|
| **naming** | a renamed or retired product | Deployment Manager is out of support; "Cloud Functions" is now **Cloud Run functions**; the Dataproc overview is now titled **Managed Service for Apache Spark** |
| **quota and limit model** | what is fixed against what is askable | AWS publishes an **auto-approved increase table**; Google Cloud and Azure publish **fixed** identity ceilings. A design that leans on raising a limit works on one cloud and not the others |
| **pricing dimension** | the **unit**, never the price | BigQuery on-demand bills **bytes scanned**; Redshift bills **node-hours**. Pub/Sub bills **bytes**; SQS bills **requests**. Neither converts without #8 |
| **regional model** | what is global, regional, zonal | a Google Cloud **VPC is global**; an AWS VPC and an Azure VNet are regional. `N` networks become **one**, and the transit object disappears |
| **IAM model** | how a grant is expressed and bounded | AWS **policy JSON** decomposes into a Google Cloud **binding + condition + deny policy + PAB policy**. Budget per policy document, not per role |

And one class that is not a cost at all, which this hub reports anyway because it is worse than a cost:

> **Correctness risk.** AWS Lambda runs **one request per execution environment**; Cloud Run functions run
> **up to 1000 concurrent requests per instance**. Code that was safe under the first assumption races under
> the second. A migration that treats this as a performance tuning note ships a bug.
> Also: adding a second **Bigtable** cluster silently changes the instance from strongly to **eventually
> consistent**.

Write these out per workload. **This list — not the cost table — is the migration's actual scope.**

## Phase 4 — the three costs no calculator contains

1. **Source-side egress.** Billed by the cloud you are leaving. Absent from the destination's calculator. On a
   large estate it can exceed a year of the destination's storage bill. Size it from #3, and note that
   event-driven mirroring means it is charged over the **whole** migration window.
2. **The work in phase 3.** Policy decomposition, schema conversion, re-instrumentation, dashboard
   re-creation, consumer idempotency. All of it is labour, none of it is on a price list.
3. **The destination's own commitments.** Minimum storage durations start on arrival — Cloud Storage
   `ARCHIVE` commits **365 days**, against 180 on the other two clouds. Landing a migration straight into a
   cold class starts that clock on data you have not validated yet.

## Phase 5 — sequence from the dependency graph, not from the org chart

Waves come from measurement #2. Two systems that talk to each other **move together**, or their traffic
crosses clouds at egress rates for as long as the wave gap lasts.

Then pre-flight each wave: **destination quotas**, per project and per region, requested in advance. A wave
that fails half-done leaves the source drained and the target incomplete, which is the worst available state
(`reference/migration/errors.md` §3).

## Phase 6 — execute one wave, then re-estimate

Pick the smallest wave with a real dependency in it. Execute it. Then **re-run phase 1** against the result.

One executed wave replaces more assumptions than any amount of further analysis, and it converts the estimate
from a model into a measurement. If a number has to be committed, commit it after this phase and not before.

## What this method cannot do

- **It cannot tell you whether a predefined role grants the same operations as its counterpart.** No published
  table claims it does. Measurement #7 is the only honest route.
- **It cannot tell you whether your SQL, your stored procedures or your dialect port.** That is assessment
  work, per schema.
- **It cannot tell you whether the application behaves the same afterwards.** The observability baseline
  (#5, #6) is what makes that a measurable question instead of an argument.
- **It cannot decide whether to migrate.** This hub documents and never acts: it narrows the unknowns in the
  decision and takes no part in it.

## Keeping the three hubs honest

Every claim in a parity guide cites a page with a **read date**, and the hub states absences explicitly —
"the page does not say" is written out rather than filled in from memory. When a vendor page has moved on,
file a drift report: `guides/when-the-docs-have-changed.md`.


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 91 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/gcp/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
