Google Cloud offers a spectrum from more control to less to manage. Pick the most managed option that still meets the workload’s needs.
flowchart TB CE["Compute Engine<br/>VMs, full OS control"] --> GKE["GKE<br/>Kubernetes, many services"] GKE --> CR["Cloud Run<br/>containers, scale to zero"] CR --> FN["Cloud Run functions<br/>event glue code"] AE["App Engine<br/>legacy PaaS"] -. "migrate new work" .-> CR %% step CE: Compute Engine gives you the OS: any software, licences, lift-and-shift, special hardware. %% step GKE: GKE runs container platforms with many services, Kubernetes tooling and portability. %% step CR: Cloud Run runs stateless containers and jobs with no cluster to manage and per-use billing. %% step FN: Functions run small handlers for single events with the least code and operations. %% step AE: App Engine still runs existing apps, but Google steers new apps to Cloud Run.
Decision table
| Question | If yes |
|---|---|
| Needs a specific OS, kernel, licence, or is a lift-and-shift of VMs? | Compute Engine (MIGs for scale) |
| Many microservices, a platform team, Helm/operators, multi-cloud portability? | GKE (Autopilot by default) |
| Stateless HTTP/gRPC service, worker or job in a container? | Cloud Run |
| A few lines reacting to an upload, message or audit event? | Cloud Run functions |
| Existing App Engine app? | Keep it running; plan a move to Cloud Run for new features |
| Large batch on VMs (HPC, rendering)? | Batch service with Spot VMs |
| AI agents built with ADK? | Agent Runtime on Gemini Enterprise Agent Platform (module 10) |
Comparing operations and cost
| Compute Engine | GKE Autopilot | Cloud Run | |
|---|---|---|---|
| You patch | OS and app | App (and container base image) | App (and base image) |
| Scale to zero | No | No (cluster fee) | Yes |
| Billing unit | VM per second | Pod requests + cluster fee | vCPU/memory per use (or per instance) |
| Long-running background work | Yes | Yes | Jobs, worker pools or instance-based billing |
| Stateful workloads | Yes (disks) | Yes (PVCs, StatefulSets) | No local state; use managed databases |
App Engine in one paragraph
App Engine standard runs code in language sandboxes and scales to zero; flexible runs containers on VMs. An app is created once per project in a region that cannot be changed later; versions and traffic splitting work much like Cloud Run revisions. It is still supported, but it is no longer the default choice for new work.
The same container everywhere
Build a standard container image, store it in Artifact Registry, and you can run it on Cloud Run today and GKE tomorrow. Cloud Run even accepts Knative-style service YAML.
gcloud run deploy web --source=. --region=asia-southeast1 # build with buildpacks and deploy
gcloud run services describe web --region=asia-southeast1 --format="value(status.url)"
| Command | Meaning |
|---|---|
gcloud app deploy app.yaml |
Deploy an App Engine version |
gcloud batch jobs submit render --location=… --config=job.json |
Batch job |
Traps: choosing GKE for one small API adds a platform to run; Cloud Run is a poor fit for software that needs a fixed OS or local disk state; App Engine’s region cannot be changed after creation.