ALL CASE STUDIES

Cloud Migration

On-Prem to GCP Migration

Eight production workloads moved to GCP with zero data loss.

01

The plan is mostly about rollback

Migration planning looks like it is about the move. It is mostly about being able to undo the move. Each workload was sequenced so it could be validated independently and reversed independently — because the one that fails will not be the one you expected, and a batch cutover means the failure takes everything with it.

02

Sequence by blast radius, not by difficulty

The temptation is to start with the easy one. Better to start with something real but low-traffic, because the easy one teaches you nothing about your actual runbook. Order by what you can afford to have wrong for an hour, and let the early moves surface the gaps in your process while the stakes are small.

03

DNS is the rollback switch

Cutover is a DNS change, which means TTL is the real recovery time. Dropping TTL to 60 seconds days before the move — long enough for the old value to expire from every resolver — turns rollback from an hours-long propagation wait into a minute. Forgetting this is how a fifteen-minute problem becomes an afternoon.

dig +noall +answer +ttlid app.example.com
# days before cutover, drop it:
gcloud dns record-sets update app.example.com. --type=A --ttl=60 --zone=prod

Verify the low TTL has actually propagated before the window. Resolvers honour the TTL they cached, not the one you just set.

04

Validate the data, not the deployment

A workload that starts is not a workload that migrated. Row counts, checksums on critical tables, and a read-only comparison against the source before traffic moves. Zero data loss is a claim you should be able to evidence, not one you make because nothing errored.

psql -h old -c 'select count(*), md5(string_agg(id::text, "," order by id)) from orders'
psql -h new -c 'select count(*), md5(string_agg(id::text, "," order by id)) from orders'

Cheap, and it catches partial replication that row counts alone miss. Run it immediately before the cutover, not the night before.

05

What goes wrong

Hidden dependencies surface at the worst time — a cron job on a forgotten VM writing to the database you just moved, or a hardcoded IP in a config nobody owns. Egress cost surprises people: replicating data out of the old environment is billed, and at volume it can dominate the migration budget. And performance differences are real — different disk classes and network paths mean the same query can be measurably slower on identical-looking hardware, which is why validation has to include latency and not just correctness.

ss -tnp state established | awk '{print $4, $5}' | sort | uniq -c | sort -rn | head -20

Run on the source host before you move anything. Every established connection is a dependency, and this finds the ones that are not in the architecture diagram.

Tools, and why these ones

  • Migrate for Compute Engine

    DOCS ↗

    Google's lift-and-shift tooling: replicates a running VM into GCE and cuts over with minimal downtime.

    Why: Replication runs while the source stays live, so the downtime window is the cutover rather than the copy.

What it took

Phased cutover planning using Migrate for Compute Engine, sequenced so each workload could be validated and rolled back independently. Zero data loss, and under two hours of total downtime per service — the number that mattered to the business, not the number that looked good in a deck.

  • GCP
  • Migrate for Compute Engine
  • Linux
  • Networking

Outcome

8
workloads
zero
data loss
<2h
downtime / service

Next case study

Cloud Cost Reduction Programme