GCP Migration Methodology — Tools, Timelines, and a Worked Example
from-aws.md is the mental-model bridge — resource hierarchy, additive IAM, global VPC. This is the other half: the actual tooling Google ships for moving workloads onto that model. If from-aws.md answers "how do I think about GCP," this answers "how do I get 40 EC2 instances, an RDS database, and a few terabytes of S3 objects there without a weekend of downtime."
1. The migration strategies Google actually documents
Every cloud vendor's blog reduces this to "the 4 R's," but Google's own Architecture Center guide (Migrate to Google Cloud: Get started) currently defines six named strategies, not four — and it's worth being precise here, because "rebuild" vs. "retire/retain" get confused across vendors constantly. Google's docs don't use "retire" or "retain" at all; those belong to Gartner's 5R/6R framing and various consultancy blogs, not Google's own taxonomy.
Google's six, in the order the guide presents them: Rehost (minor/no modification), Replatform (lift, then optimize for the cloud), Refactor (modify to exploit cloud capabilities, not just to run), Re-architect (refactor's deeper cousin — changes how the code functions, e.g. splitting a monolith), Rebuild (decommission and rewrite as fully cloud-optimized), and Repurchase (swap a purchased on-prem product for its SaaS equivalent).
Collapsed to the popular "4 R's" shorthand, Google's guide groups re-architect under refactor and repurchase under rebuild — so the four planning buckets are Rehost / Replatform / Refactor / Rebuild. The fourth bucket beyond the first three is Rebuild, not "retire" or "retain."
Decision table — workload characteristic → strategy
| Workload characteristic | Strategy | Why |
|---|---|---|
| No active dev team, tight timeline, hard-to-reproduce OS/license combo | Rehost | No code changes wanted; goal is closing a data center, not modernizing |
| Self-managed DB/queue/cache underneath an app you don't want to touch | Replatform | Managed services remove operational burden without touching app code |
| Hitting real scaling/cost ceilings the architecture itself can't solve | Refactor / Re-architect | The architecture is the bottleneck, not just where it runs |
| On-prem data warehouse (Teradata, Netezza) with years of SQL and ETL | Refactor via BigQuery Migration Service | Warehouse workloads rarely rehost cleanly |
| Purchased on-prem product (CRM, ticketing, ERP) with a mature SaaS equivalent | Repurchase | Cheaper than migrating and operating the old product |
| Chronically broken codebase blocking every roadmap item | Rebuild | Migration effort would prop up something you're about to replace |
A team says they're doing a "replatform" because they're moving their app's self-managed MySQL to Cloud SQL for MySQL while leaving the application code completely untouched. Is that actually a replatform, or is it a rehost?
2. Migrate to Virtual Machines — agentless VM rehost
Formerly "Migrate for Compute Engine," this is Google's dedicated rehost engine: agentless replication of running VMs — from on-prem vSphere, AWS, or Azure — directly into Compute Engine, with almost no cutover downtime.
The mechanism, not just the pitch: a Migrate Connector sits outside the VM being migrated — a small appliance for on-prem vSphere, or a connection through the source cloud's own APIs for AWS/Azure. Nothing installs inside the guest OS. It runs continuous block-level disk replication: reading changed disk blocks from the source volumes and streaming them into a GCP staging area in the background, while the source keeps serving production traffic untouched. No shell access, no in-guest credentials, no maintenance window just to start replicating — that's what "zero-touch" means here.
Because the source is never paused, replication has a useful side effect: test clones. Once enough data has replicated, spin up a real Compute Engine instance from the currently-replicated data — a point-in-time clone to boot and validate in isolation, without touching the source or the ongoing replication. A bad clone just means fixing the target config and cutting a fresh one — the source was never at risk because it was never touched.
Google names six lifecycle stages:
graph LR
classDef src fill:#e67e22,stroke:#ba6018,color:#fff
classDef repl fill:#4285f4,stroke:#2a56c6,color:#fff
classDef tgt fill:#2ecc71,stroke:#27ae60,color:#fff
SRC["Source VM<br/>on-prem vSphere, AWS EC2, or Azure"]:::src -->|"continuous block-level<br/>disk replication"| CONN["Migrate Connector<br/>agentless, no in-guest install"]:::repl
CONN -->|"replicated disk data"| STAGE["GCP staging area"]:::repl
STAGE -->|"instantiate anytime,<br/>source keeps running"| CLONE["Test clone<br/>Compute Engine instance"]:::tgt
STAGE -->|"final delta sync<br/>at cutover"| PROD["Production<br/>Compute Engine instance"]:::tgt
When this beats a manual re-provision: any time you'd otherwise hand-build a Compute Engine image and hope it matches production closely enough. A manual re-provision (build an image, run config management, cut a VM) is fine for one or two clean, scripted VMs — but it re-derives the machine from a recipe, so anything that drifted from that recipe in production silently doesn't make the trip. This tool moves the actual disk bytes instead, so whatever the VM really is comes across intact — the right call for fleets of VMs, unclear configuration, tight cutover windows, or licensing/OS combos too painful to reproduce from a script.
Why can Migrate to Virtual Machines replicate an EC2 instance into Compute Engine without installing any agent inside the source VM's guest OS?
3. Database Migration Service (DMS)
DMS handles the database tier specifically, and the mechanism differs sharply depending on whether the source and target are the same database engine or not.
Either way, you choose a cutover approach: a one-time dump/restore (snapshot, restore, done — downtime equals restore time) or continuous replication (an initial full load establishes a baseline, then CDC or native replication keeps the target chasing the source in real time, so the cutover window shrinks to seconds or minutes).
You're migrating a 40 GB internal reporting database that can tolerate a 2-hour maintenance window once a quarter. Why might a one-time dump/restore be a perfectly reasonable choice here, instead of setting up continuous CDC replication?
4. BigQuery Migration Service
This is the analytics-warehouse-specific migration path — moving an existing warehouse (Teradata, Redshift, Snowflake, Netezza, Hive) into BigQuery. It's a different problem from OLTP database migration: the goal isn't replicating rows continuously, it's translating years of accumulated SQL, stored procedures, and scheduled ETL into BigQuery's dialect and execution model.
Don't confuse it with BigQuery Data Transfer Service — a separate, narrower product for scheduling recurring loads from SaaS sources (Google Ads, YouTube, Cloud Storage). BigQuery Migration Service is the warehouse toolchain: assessment, SQL translation, transfer orchestration, and validation.
SELECT/JOIN logic translates close to automatically — the hard part has always been procedural extensions with no direct BigQuery equivalent (Teradata BTEQ macros, stored procedures), which is where Gemini-assisted translation targets improving automation coverage.
A migration assessment flags 200 simple reporting views as "low effort" and 15 Teradata BTEQ macros as "high effort." Why would 15 objects out of 215 dominate the migration timeline?
5. Storage Transfer Service + Transfer Appliance
Both move bytes into Cloud Storage — the choice between them comes down to data volume against available network bandwidth, not preference.
The math that decides it: moving 100 TB over a shared 1 Gbps link, even at generous sustained throughput, takes on the order of 10+ days of that link doing nothing but the transfer — and real enterprise links are rarely free for that long without disrupting everything else on them. At hundreds of terabytes to petabytes on a constrained link, "ship a box" is both faster and stops competing with production traffic. Rule of thumb: if the transfer would take longer than roughly a week given genuinely available bandwidth, that's the point to reach for Transfer Appliance instead.
Why would you choose Transfer Appliance over Storage Transfer Service for a migration, given that Storage Transfer Service is simpler to set up (no physical hardware, no shipping)?
6. Anthos / GKE Enterprise for phased hybrid migration
Every tool so far assumes a hard cutover eventually happens: replicate, then flip. GKE Enterprise (formerly Anthos) exists for when you deliberately don't want that — when workloads need to run on-prem and in GCP simultaneously, for weeks or months, while you migrate one service at a time.
The mechanism is Config Sync (part of GKE Enterprise's Config Management): a Git repository becomes the single source of truth for Kubernetes manifests, applied by Config Sync to every cluster in the fleet — on-prem, other clouds, and GKE clusters in GCP alike. Because the Kubernetes API surface is identical everywhere, the same manifests running a workload on-prem today apply unmodified to a GKE cluster in GCP tomorrow.
That's what this unlocks: you don't migrate everything at once. A stateless service deploys to a GCP cluster from the same Git-managed manifests already running it on-prem, gets validated with a slice of production traffic (multi-cluster ingress or a service mesh split), and only fully cuts over once proven — everything else keeps running exactly where it was, under the same guardrails, the whole time.
A platform team migrating a Kubernetes-based system to GCP considers Anthos Config Management specifically because it avoids one thing a Migrate-to-Virtual-Machines-style rehost inherently involves. What is it?
7. Worked example: a 3-tier AWS app moving to GCP
Take a concrete, common stack: an EC2 Auto Scaling Group running a stateless web/app tier, an RDS for MySQL primary database, and an S3 bucket holding static assets and backups. No Kubernetes here — the plain-VM case, also the most common in practice. Here's the wave plan, using the tools above in the order that actually minimizes risk:
graph TD
subgraph WAVE0["Wave 0 — Assessment"]
MC["Migration Center<br/>inventory + rightsizing"]
end
subgraph WAVE1["Wave 1 — Static assets, lowest risk"]
S3["AWS S3<br/>static assets + backups"] -->|"Storage Transfer Service<br/>continuous sync"| GCS["Cloud Storage bucket"]
end
subgraph WAVE2["Wave 2 — Compute tier, rehost"]
EC2["EC2 Auto Scaling Group<br/>stateless app and web tier"] -->|"Migrate to Virtual Machines<br/>replicate, test clone, cutover"| GCE["Compute Engine<br/>Managed Instance Group"]
end
subgraph WAVE3["Wave 3 — Database, homogeneous DMS"]
RDS["RDS for MySQL<br/>primary"] -->|"Database Migration Service<br/>full load then binlog CDC"| CSQL["Cloud SQL for MySQL"]
end
subgraph WAVE4["Wave 4 — Traffic cutover"]
LB["DNS and load balancer<br/>flip to GCP"]
end
MC --> S3
MC --> EC2
MC --> RDS
GCS --> LB
GCE --> LB
CSQL --> LB
LB -->|"bake period, then decommission"| DECOM["Decommission AWS stack"]
Walking through why this specific order:
-
Wave 0 — Assessment. Migration Center inventories the AWS estate (utilization, sizing, cost) so the EC2 fleet gets right-sized machine types instead of a 1:1 copy out of habit.
-
Wave 1 — S3 → Cloud Storage first. Lowest-risk wave: static, mostly-immutable objects, no live transactional dependency. Storage Transfer Service's continuous sync keeps both buckets current — the app keeps reading/writing S3 right up until it's repointed at GCS.
-
Wave 2 — EC2 → Compute Engine, while the database stays on RDS. Migrate to Virtual Machines replicates the instances continuously; test clones validate the app boots correctly against the still-on-AWS database before committing — validating the compute tier in isolation from the database migration's own risk.
-
Wave 3 — RDS → Cloud SQL last, the highest-consequence wave. The app tier is already proven, so the only remaining variable is the database. DMS does an initial full load, catches up via binlog CDC while production keeps writing to RDS, and only during the cutover window does anyone briefly pause writes to drain the last sliver of lag before promoting Cloud SQL.
-
Wave 4 — Flip traffic, keep AWS warm. DNS/load balancer changes route users to GCP. AWS resources stay running, untouched, for a bake period — days to weeks — as a rollback path, before decommissioning.
If this app's tier had already run as containers on EKS, GKE Enterprise would slot into Wave 2 instead: register a GKE cluster into the fleet, apply the existing manifests via Config Sync, and canary traffic service-by-service — no VM replication needed, because the workload was already portable at the Kubernetes API level.
In the wave plan above, why does the database migrate last, even though RDS and S3 could technically both start on day one?