Comparing VM Offerings Across AWS, GCP, and Azure
EC2, Compute Engine and Azure VMs side by side: naming, families, disks, maintenance, stop billing, Spot, discounts and SLAs, and how to choose.
A virtual machine is the most portable thing you can buy from a cloud provider. A Linux server with four vCPUs and 16 GB of memory runs the same code on Amazon EC2, Google Compute Engine and Azure Virtual Machines. What differs is everything around it: how sizes are named, what happens during host maintenance, what “stopped” costs you, how discounts work, and what the provider promises about uptime. Those differences decide your bill and your on-call experience far more than raw CPU speed.
This article puts the three side by side. It assumes you’ve met each one on its own, in Deep Dive into AWS EC2 Instances, Exploring GCP Compute Engine Instances and Understanding Azure Virtual Machines. If you’re choosing a provider for reasons beyond VMs, start with AWS vs. GCP vs. Azure: Core Differences.
The same building blocks, different names
All three clouds assemble a VM from the same parts: an image, a size, a block storage disk, a network interface in a private network, and firewall rules. The vocabulary is the first obstacle when you move between them.
flowchart LR
subgraph AWS
A1["AMI"] --> A2["EC2 instance"]
A3["Instance type"] --> A2
A2 --> A4["EBS volume"]
A2 --> A5["ENI in a VPC subnet"]
A5 --> A6["Security group"]
end
subgraph GCP
G1["Image"] --> G2["Compute Engine instance"]
G3["Machine type"] --> G2
G2 --> G4["Persistent Disk or Hyperdisk"]
G2 --> G5["vNIC in a VPC subnet"]
G5 --> G6["VPC firewall rules"]
end
subgraph Azure
Z1["Image"] --> Z2["Virtual machine"]
Z3["VM size"] --> Z2
Z2 --> Z4["Managed disk"]
Z2 --> Z5["NIC in a VNet subnet"]
Z5 --> Z6["Network security group"]
end
| Concept | AWS | Google Cloud | Azure |
|---|---|---|---|
| The VM | EC2 instance | Compute Engine instance | Virtual machine |
| Size | Instance type | Machine type | VM size |
| Boot image | AMI | Image (public or custom) | Image (Marketplace or Compute Gallery) |
| Block storage | EBS volume | Persistent Disk or Hyperdisk | Managed disk |
| Local scratch disk | Instance store | Local SSD | Temporary disk |
| Private network | VPC (regional) | VPC (global, subnets are regional) | Virtual network (regional) |
| Firewall | Security group | VPC firewall rules and policies | Network security group |
| Group of identical VMs | Auto Scaling group | Managed instance group | Virtual Machine Scale Sets |
| Launch blueprint | Launch template | Instance template | Scale set model |
| Startup script | User data | Startup script in metadata | Custom data or Custom Script Extension |
Two rows deserve a second look. Google’s VPC is a global resource, so one network can hold subnets in many regions without peering, while AWS VPCs and Azure VNets live in one region each. And the local scratch disks in the “Local scratch disk” row are all ephemeral: their contents don’t survive the VM moving to another host. Treat them as cache, never as storage.
Reading size names
Every provider encodes the family, generation, processor and size into the name. Once you can read one, the others follow the same idea with different punctuation.
| Example | Provider | How to read it |
|---|---|---|
m7i.xlarge | AWS | Family m (general purpose), generation 7, i for Intel, size xlarge (4 vCPUs) |
m7g.xlarge | AWS | Same family and generation, g for Graviton (Arm) |
n2-standard-4 | GCP | Series n2, memory profile standard (4 GB per vCPU), 4 vCPUs |
c4a-highcpu-8 | GCP | Series c4a (Axion, Arm), highcpu profile, 8 vCPUs |
Standard_D4s_v5 | Azure | Family D (general purpose), 4 vCPUs, s for premium storage, version 5 |
Standard_D4ps_v6 | Azure | Same family, p for Arm (Cobalt), version 6 |
The big structural difference is where the vCPU count lives. AWS hides it behind a T-shirt size (large, xlarge, 2xlarge), so you need a table to know that xlarge means 4 vCPUs. Google and Azure put the number in the name. Google also puts the memory ratio in the name (highcpu, standard, highmem), where AWS and Azure use a different family letter for each ratio.
One more trap: a vCPU is usually one hardware thread, not a full core, on x86 instances with simultaneous multithreading. On Arm instances (Graviton, Axion, Cobalt) each vCPU is a full physical core. That makes a straight vCPU-for-vCPU price comparison between x86 and Arm misleading. Benchmark your own workload instead.
Which of these names does NOT state its vCPU count directly?
Correct! AWS uses T-shirt sizes, so you need to look up that xlarge means 4 vCPUs.
Families line up closely
The families map almost one to one, because all three providers buy similar chips and serve similar workloads. Each now also offers its own Arm processor: AWS Graviton, Google Axion and Azure Cobalt.
| Workload | AWS | Google Cloud | Azure |
|---|---|---|---|
| Burstable, mostly idle | T (t3, t4g) | E2 shared-core (e2-micro, e2-small) | B-series |
| General purpose | M (m7i, m7g) | E2, N2, N4, C4 | D-series |
| Compute optimized | C (c7i, c7g) | C2, C2D; H3 and H4D for HPC | F-series |
| Memory optimized | R, X (r7i, x2idn) | M-series, highmem shapes | E-series, M-series |
| Storage optimized | I, D (i4i) | Z3 | L-series |
| GPU and AI | P, G (g6) | A-series, G-series | N-series |
| Own Arm chip | Graviton (m7g, c7g) | Axion (C4A, N4A) | Cobalt (Dpsv6, Epsv6) |
Two capabilities stand out:
- Custom shapes. Compute Engine lets you create a custom machine type on several series, including N2 and E2, picking the exact vCPU count and memory. AWS and Azure sell fixed sizes only. AWS lets you reduce the active core count and threads per core at launch (CPU options), and Azure offers constrained-vCPU sizes such as
Standard_E8-4s_v5, mainly to cut per-core software licensing costs. - Breadth of choice. AWS has the largest catalogue of instance types. That’s useful for specialised hardware and annoying when you just want a sensible default. Google’s catalogue is smaller and Azure’s sits in between.
Availability varies by region on every cloud. Before you design around a size, check that it’s offered where you need it:
# AWS: which Availability Zones in ca-central-1 offer m7g.large?
aws ec2 describe-instance-type-offerings --region ca-central-1 \
--location-type availability-zone \
--filters Name=instance-type,Values=m7g.large --output table
# GCP: which zones offer n2-standard-4?
gcloud compute machine-types list --filter="name=n2-standard-4" \
--format="table(name,zone)"
# Azure: which sizes can this subscription use in Canada Central?
az vm list-skus --location canadacentral --resource-type virtualMachines \
--size Standard_D --output table
Disks and the scratch-disk trap
Block storage follows the same pattern everywhere: a network-attached disk that outlives the VM, sold in tiers that trade price for IOPS and throughput.
| AWS EBS | GCP Persistent Disk and Hyperdisk | Azure managed disks | |
|---|---|---|---|
| Everyday SSD | gp3 | Balanced Persistent Disk, Hyperdisk Balanced | Standard SSD, Premium SSD |
| Tune IOPS separately from size | gp3, io2 | Hyperdisk | Premium SSD v2, Ultra Disk |
| Highest performance | io2 Block Express | Hyperdisk Extreme | Ultra Disk |
| Low-cost HDD | st1, sc1 | Standard Persistent Disk | Standard HDD |
| Zone-redundant option | No (single AZ) | Regional Persistent Disk, Hyperdisk Balanced High Availability | ZRS disks |
The last row matters for single-VM designs. An EBS volume lives in one Availability Zone, so surviving a zone failure on AWS means snapshots or replication at the application layer. Google and Azure can synchronously replicate a disk across two or more zones, letting you restart a VM in another zone with its data intact.
Google is moving its newer machine series to Hyperdisk, and some of them don’t support the older Persistent Disk types at all. Check the disk compatibility table for a series before you pick it.
Host maintenance: the biggest hidden difference
Every provider has to patch and replace physical hosts. How they handle your VM while that happens is one of the least visible and most important differences.
flowchart TB
M["Host needs maintenance"] --> Q1{"Which cloud?"}
Q1 -->|"Google Cloud"| G["Live migrate to a new host by default"]
G --> G2["VM keeps running, brief slowdown"]
Q1 -->|"Azure"| Z["Most updates pause the VM briefly in place"]
Z --> Z2["Scheduled Events warn the guest"]
Q1 -->|"AWS"| A["Scheduled event: retirement, reboot or maintenance"]
A --> A2["You stop and start before the deadline, or AWS does it"]
- Google Cloud live migrates most VMs by default: the running VM is moved to another host with its memory, disks and network connections intact. The exceptions are important. Spot and preemptible VMs, and VMs with GPUs or TPUs attached, can’t live migrate and are stopped instead. GPU VMs get advance notice, 60 minutes for most GPU types.
- Azure uses in-place updates for most host maintenance, which pause the VM briefly, and live migration in some cases. When a reboot really is needed, you get notice through Scheduled Events and the portal.
- AWS tells you about scheduled events such as instance retirement or a system reboot through the console, the Health Dashboard and EventBridge. For a retirement on an EBS-backed instance, stopping and starting it moves it to new hardware on your schedule instead of AWS’s.
In practice this means a single VM on Google Cloud tends to ride through maintenance without you noticing, while on AWS you should expect to handle the occasional retirement notice. On all three, the real fix is the same: don’t run anything important on a single VM.
On Google Cloud, which VM is stopped rather than live migrated during host maintenance?
Correct! VMs with GPUs or TPUs attached can't live migrate, so they're stopped, with advance notice.
What “stopped” costs you
All three let you stop a VM and stop paying for its compute, but the wording differs, and Azure has a trap.
| AWS | Google Cloud | Azure | |
|---|---|---|---|
| Compute billing increment | Per second, 60-second minimum, for most Linux and Windows instances | Per second after a 1-minute minimum | See the Azure pricing page for your OS |
| Stop and pay no compute | Stop (state stopped) | Stop (state TERMINATED) | Stop in the portal or az vm deallocate (state “Stopped (deallocated)”) |
| Stopped but still billed for compute | Not applicable | Not applicable | Shut down from inside the OS or az vm stop (state “Stopped”) |
| Save memory to disk and stop | Hibernate | Suspend | Hibernate |
| Still billed while stopped | EBS volumes, Elastic IPs | Disks, static IPs | Managed disks, static public IPs |
Google’s naming is the confusing one: a stopped Compute Engine VM shows the status TERMINATED, even though it’s only stopped and you can start it again. Deleting is a separate action.
Azure’s is the costly one. Shutting the OS down from inside the VM leaves it allocated on its host, and you keep paying for compute. Use the portal’s Stop button or az vm deallocate.
Spot capacity
All three sell spare capacity at a steep discount in exchange for the right to take it back. The mechanics differ in ways that matter to your code.
| AWS Spot Instances | GCP Spot VMs | Azure Spot VMs | |
|---|---|---|---|
| Warning before reclaim | 2 minutes, via instance metadata and EventBridge | Shutdown period of up to 30 seconds, best effort | Up to about 30 seconds via Scheduled Events, best effort |
| Early hint | Rebalance recommendation | None by default | None |
| What happens to the VM | Terminate, stop or hibernate (your choice) | Stop or delete (your choice) | Deallocate or delete (your choice) |
| Price cap | Optional maximum price | No bidding | Optional maximum price, or -1 for no cap |
| Maximum runtime | None | None unless you set one | None |
AWS gives by far the longest warning. On Google Cloud and Azure, assume there’s effectively no warning: checkpoint work often, keep state off the VM, and let a managed group replace lost capacity. Our EC2 launch walkthrough and Compute Engine launch walkthrough show where the Spot option sits in each console.
Discounts for steady workloads
The commitment models look similar but behave differently. A later article in this series compares them in depth; here’s the shape.
| AWS | Google Cloud | Azure | |
|---|---|---|---|
| Automatic discount, no commitment | None | Sustained use discounts on some older series (such as N1, N2, N2D) | None |
| Commit to a specific shape | Reserved Instances, EC2 Instance Savings Plans | Resource-based committed use discounts | Reservations |
| Commit to an hourly spend | Compute Savings Plans | Spend-based (flexible) committed use discounts | Savings plan for compute |
| Bring your own licences | BYOL on Dedicated Hosts | Sole-tenant nodes for BYOL | Azure Hybrid Benefit |
| Terms | 1 or 3 years | 1 or 3 years | 1 or 3 years |
Google’s sustained use discounts are the odd one out. They apply automatically when a VM on an eligible series runs for more than a quarter of the month, so a server left running all month on N2 gets cheaper with no action from you. Newer series such as E2, N4 and C4 don’t get them, so compare effective prices rather than list prices.
Azure Hybrid Benefit is the other outlier. If your organisation already owns Windows Server or SQL Server licences with Software Assurance, Azure can be the cheapest place to run Windows VMs by a wide margin. That’s a licensing question, not a hardware one.
Never trust a price in a blog post, including this one. Use the AWS Pricing Calculator, the Google Cloud Pricing Calculator and the Azure pricing calculator with your real region, size and hours.
Which discount applies without any commitment or sign-up?
Correct! Sustained use discounts apply automatically to eligible Compute Engine series that run for more than 25 percent of the month.
Uptime promises
Each provider publishes a VM SLA with a higher target for VMs spread across zones than for a single VM. The SLA is a promise of service credits, not a guarantee of uptime, but the gap between the tiers tells you what the providers expect you to build.
| Deployment | AWS | Google Cloud | Azure |
|---|---|---|---|
| Single VM | 99.5% | 99.9% for most families | 99.9% with Premium SSD or Ultra Disk on every disk |
| Spread within one datacenter | No separate tier | No separate tier | 99.95% with an availability set |
| Two or more zones | 99.99% | 99.99% in most regions | 99.99% |
Check the current Amazon Compute SLA, Compute Engine SLA and Azure SLA for Virtual Machines for exact definitions and exceptions. The pattern holds everywhere: two VMs in two zones behind a load balancer is the baseline for anything that matters, and the managed group in each cloud (Auto Scaling group, managed instance group, Virtual Machine Scale Sets) is how you keep it that way. Scaling those groups is the subject of the last article in this series.
The same VM on all three clouds
Here’s a small Linux VM created from each CLI. The commands are deliberately close to each other so you can see what lines up.
# AWS: Amazon Linux 2023 on t3.micro, latest AMI resolved from SSM
aws ec2 run-instances --region ca-central-1 \
--image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 \
--instance-type t3.micro \
--key-name my-key \
--security-group-ids sg-0123456789abcdef0 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=vm-demo}]'
# GCP: Debian 12 on e2-small
gcloud compute instances create vm-demo \
--zone=northamerica-northeast1-a \
--machine-type=e2-small \
--image-family=debian-12 --image-project=debian-cloud
# Azure: Ubuntu 22.04 on Standard_B2s
az group create --name rg-vm-demo --location canadacentral
az vm create --resource-group rg-vm-demo --name vm-demo \
--image Ubuntu2204 --size Standard_B2s \
--admin-username azureuser --generate-ssh-keys
Notice what each one asks for. AWS needs a key pair and a security group that already exist. Google creates the VM in the default network and handles SSH keys when you connect with gcloud compute ssh. Azure creates the network, NIC, public IP and security group for you, inside a resource group you can delete in one command. Clean up afterwards with aws ec2 terminate-instances, gcloud compute instances delete and az group delete.
How to choose
Most teams don’t choose a cloud for its VMs. They choose it for their existing contracts, identity system, data services or team skills, and the VMs come along. Our article on Choosing a Cloud Provider: One Cloud or Several covers that bigger decision. When the VM layer really is the deciding factor, these are the questions that separate the three.
flowchart TB
S["What matters most for these VMs?"] --> W{"Mostly Windows Server or SQL Server with existing licences?"}
W -->|"Yes"| AZ["Azure, with Azure Hybrid Benefit"]
W -->|"No"| H{"Need unusual hardware or the widest instance choice?"}
H -->|"Yes"| AW["AWS"]
H -->|"No"| L{"Long-running single VMs, odd CPU-to-memory ratios?"}
L -->|"Yes"| GC["Google Cloud: live migration, custom machine types"]
L -->|"No"| ANY["Any of the three: decide on platform fit and price"]
| If you need | Lean towards | Why |
|---|---|---|
| Windows and SQL Server with owned licences | Azure | Azure Hybrid Benefit and deep Windows integration |
| The widest catalogue, including niche hardware | AWS | The largest range of instance types and sizes |
| Exact vCPU and memory shapes | Google Cloud | Custom machine types |
| Single VMs that ride through host maintenance | Google Cloud | Live migration by default |
| The longest Spot interruption warning | AWS | 2 minutes plus rebalance recommendations |
| A discount without committing | Google Cloud | Sustained use discounts on eligible series |
| Zone-redundant disks for a single VM | Google Cloud or Azure | Regional Persistent Disk, Hyperdisk HA, ZRS disks |
If you’re still learning, open all three free accounts (Setting Up Free Accounts on AWS, GCP, and Azure) and run the same small VM on each for an afternoon. The differences in this article make much more sense once you’ve seen them in a console.
Further reading
- Amazon EC2 instance types
- Compute Engine machine families resource and comparison guide
- Sizes for virtual machines in Azure
- Compute Engine host maintenance overview
- EC2 Spot Instance interruption notices
- Azure maintenance for virtual machines
Key takeaways
- The three VM services share the same building blocks: image, size, block disk, network interface and firewall. Learn the name mapping once and the rest transfers.
- AWS hides vCPU counts behind T-shirt sizes; Google and Azure put the count in the name. On Arm, a vCPU is a full core, so compare by benchmark, not vCPU count.
- Families line up almost one to one, and each cloud now has its own Arm chip: Graviton, Axion and Cobalt. Only Google offers custom machine types.
- EBS volumes are tied to one zone; Google and Azure offer zone-redundant disks. Local scratch disks are ephemeral on all three.
- Google live migrates most VMs during maintenance, Azure mostly pauses them briefly, and AWS sends scheduled events you may need to act on.
- A stopped Compute Engine VM shows
TERMINATED, and an Azure VM shut down from inside the OS still bills for compute until it’s deallocated. - Spot warnings are 2 minutes on AWS and up to about 30 seconds on Google Cloud and Azure. Design for no warning at all.
- For anything important, run at least two VMs across zones in a managed group. That’s where the 99.99% SLA tier starts on all three clouds.
Part 4 of 4 · Virtual Machines