How to use the aws, azure and gcp hubs together to estimate a migration

The method the three cuppy hubs exist to support. Six phases from inventory to a defensible number, the eight measurements an estimate is not valid without, the five difference classes every parity guide reports, the three costs no vendor calculator contains, and an explicit statement of what this method cannot do.

markdownguidev1PMVR-NGH4stage: designtrust: officialfamily: overviewservice: migration-centerinterface: anymigration estimateparitycross-cloudaws hubazure hubgcp hubnamingquota modelpricing dimensionregional modelIAM modelegresswavesright-sizingcorrectness risk

Created 21 Oct 2026 · Modified 23 Oct 2026 · 1 version

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:

QuestionWhat 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:

#MeasureFeeds
1utilisation, not provisioned capacityright-sizing — usually the largest saving available
2network dependencies between systemsthe wave boundaries
3bytes to move, by datasetegress, and the transfer window
4identities, keys and secrets per workloadthe identity line, and the keys you can delete
5logs GB/day, metric count and label cardinality, trace volumethe observability line
6count of dashboards and alerting policieseffort — they are re-created, never migrated
7permissions each workload actually usedthe role-mapping work
8request/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.

  1. 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.

  1. 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:

ClassWhat to look forWorked example from this hub
naminga renamed or retired productDeployment 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 modelwhat is fixed against what is askableAWS 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 dimensionthe unit, never the priceBigQuery on-demand bills bytes scanned; Redshift bills node-hours. Pub/Sub bills bytes; SQS bills requests. Neither converts without #8
regional modelwhat is global, regional, zonala Google Cloud VPC is global; an AWS VPC and an Azure VNet are regional. N networks become one, and the transit object disappears
IAM modelhow a grant is expressed and boundedAWS 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.

  1. 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.

  1. 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.

Read this document as markdown — the same bytes an agent receives.