Compute parity — Compute Engine, GKE, Cloud Run and functions against EC2/EKS/Fargate/Lambda and VMs/AKS/Container Apps/Functions
Counterpart names for the compute family, then the four differences that change an estimate: the function concurrency model, the function timeout ceiling, what a managed Kubernetes mode bills you for, and whether arbitrary VM shapes are available.
markdownguidev15T4B-VDFZstage: designtrust: officialfamily: computeservice: cloud-runinterface: anycompute paritycompute engineEC2azure virtual machinesGKEEKSAKScloud runfargateapp runnerazure container appscloud run functionslambdaazure functionsconcurrencytimeoutautopilot billing
Compute parity
1. The names
| Google Cloud | AWS | Azure |
|---|---|---|
| Compute Engine | Amazon EC2 | Azure Virtual Machines |
| managed instance groups + autoscaler | EC2 Auto Scaling groups | virtual machine scale sets, Azure Autoscale |
| sole-tenant nodes | Dedicated Hosts | Azure Dedicated Host |
| GKE (Autopilot / Standard) | Amazon EKS | AKS |
| Cloud Run | AWS Fargate, App Runner, and Lambda | Azure Container Apps, Container Instances |
| Cloud Run functions | AWS Lambda | Azure Functions |
| Artifact Registry | Amazon ECR | Azure Container Registry |
| VMware Engine | — | Azure VMware Solution |
The Cloud Run row is one-to-three, and that is the point. Google's own table maps Cloud Run onto Fargate,
App Runner and Lambda, because Cloud Run's four resource types
(reference/compute/cloud-run.md §1) cover territory those three divide between them. Microsoft maps it to
Azure Container Apps, described as "a managed serverless container service built on Kubernetes and KEDA that
supports event-driven applications, scale-to-zero, and microservices without managing clusters".
Estimate consequence. Moving to Google Cloud, several source services collapse into one — fewer platforms to learn, fewer pipelines, one IAM surface. Moving from Google Cloud, one Cloud Run estate fans out into two or three target services, and the split is per workload, by shape: request-driven, task-driven, background, singleton.
2. Functions — the concurrency model is the row that changes the bill and the code
| Google Cloud (Cloud Run functions) | AWS (Lambda) | Azure (Functions) | |
|---|---|---|---|
| requests per instance | "Up to 1000 concurrent requests per function instance" | an execution environment serves one request at a time; the synchronous invocation ceiling is stated as 10 requests per second per environment, i.e. ten times the concurrency limit | per-instance concurrency varies by plan and host |
| maximum duration | 60 minutes (HTTP), 9 minutes (event-driven) | 900 seconds (15 minutes); 5,400 seconds (90 minutes) only for Lambda Managed Instances on asynchronous and event-source-mapping invocations | varies by plan |
| scaling ceiling | Cloud Run's maximum instances | concurrent executions: 1,000 by default, increasable to "tens of thousands" | plan-dependent |
| 1st gen equivalent | 1st gen: one request per instance, 9 minutes | — | — |
Two readings, and they are the most valuable rows in this guide.
- Concurrency. Lambda gives one request per execution environment; Cloud Run functions give up to 1,000 per
instance. So Lambda code is written for single-request isolation, and that assumption is unsafe on Google Cloud. Module-level mutable state, a single shared database connection without pooling, a temp file at a fixed path: all fine on Lambda, all races on Cloud Run functions. Audit for shared mutable state before a Lambda-to-Google-Cloud move, not after. Going the other way, instance counts rise and the per-instance cost model changes with them.
- Duration. Google Cloud's 60-minute HTTP ceiling against Lambda's 15 minutes is a capability difference,
not a tuning one. A 40-minute job runs as an HTTP-triggered function on Google Cloud and cannot run as a standard Lambda invocation — on AWS it becomes Step Functions, ECS or a Managed Instances async invocation. That is an architecture line item in the AWS direction and a simplification in the Google Cloud direction.
Note also: AWS raises new accounts' Lambda quotas automatically based on usage, so a new-account benchmark understates AWS's ceiling. Nothing equivalent is documented for Cloud Run in the pages read here.
3. Managed Kubernetes — the billing dimension, not the price
| Google Cloud | AWS | Azure | |
|---|---|---|---|
| the modes | Autopilot (recommended) and Standard | EKS, with EKS Auto Mode | AKS, with node pools |
| what Autopilot bills | provisioned compute resources your workloads request | — | — |
| what Standard bills | the node infrastructure you create | the nodes you create, plus the cluster fee | the nodes you create |
| privileged workloads | Autopilot "prevents privileged Pods" | permitted on self-managed nodes | permitted |
Estimate consequence. Autopilot bills on requests, which makes every over-generous
resources.requests in a migrated manifest a line on the invoice. Standard, EKS and AKS all bill on nodes,
where the same over-request is absorbed by idle headroom you were already paying for. So a manifest estate
moving onto Autopilot needs a requests-tuning pass, and that pass is usually the largest single saving in a
Kubernetes migration onto Google Cloud. Moving the other way, the saving disappears and node bin-packing
becomes your job again.
The privileged-Pod constraint is the capability gate: node agents, some CSI/CNI add-ons and several
third-party security products do not run on Autopilot. Check those specs first
(reference/compute/gke-cluster-modes.md §3).
4. VM shapes — arbitrary sizes are available in fewer places than people assume
Google Cloud's custom machine types exist only for the N and E series in the general-purpose family, and "cost slightly more to use compared to an equivalent predefined machine type". Everything compute-, memory-, storage- or accelerator-optimised must fit a predefined shape.
Estimate consequence. A right-sizing model that assumes arbitrary vCPU/memory pairs is implicitly assuming
a general-purpose series. On every other family the real figure is the next predefined shape up, and the
difference between "what we need" and "what we can buy" is pure rounding waste. Compute the estimate against
the actual shape list (gcloud compute machine-types list --zones=...), per zone, because availability is
zonal.
5. Pricing dimension (never a price)
| Google Cloud | AWS | Azure | |
|---|---|---|---|
| VMs | per-second use by machine type, with committed-use and sustained-use style discounts | per-second/hour by instance type, with Savings Plans and Reserved Instances | per-second by VM size, with reservations and savings plans |
| managed Kubernetes | Autopilot: requested resources. Standard: nodes (plus any cluster fee) | nodes plus cluster fee | nodes (control plane free on the standard tier) |
| serverless containers | request count, and allocated CPU/memory while serving | Fargate: vCPU/memory-seconds. Lambda: GB-seconds plus requests | vCPU/memory-seconds plus requests |
| functions | the Cloud Run dimensions, since a function is a Cloud Run service | GB-seconds plus requests | execution count plus GB-seconds, by plan |
The structural difference worth carrying: because a Cloud Run function is a Cloud Run service, Google Cloud has one serverless-container pricing model where AWS has two (Fargate and Lambda) with different units. A cost model built per-platform on AWS collapses to one on Google Cloud, which makes it easier to compare — and easier to get wrong by comparing GB-seconds to a request count.
6. What this guide cannot tell you
Whether a given instance type has a performance equivalent on the target. Nothing published maps a VM shape
across clouds in a way a benchmark would agree with, and no table here tries. Size from the workload's own
measurements: guides/parity-and-migration-method.md.