ARM64 Migration in 2026: Graviton5 Costs 9% More and Still Undercuts x86
I have moved enough workloads between x86 and ARM to know the instance swap is the easy part. The hard part is the one Dockerfile that downloads a linux-amd64 tarball, or the monitoring agent that never shipped an arm64 build. This post covers where an arm64 migration stands in late 2026. AWS Graviton5 went GA in June, Google's Axion N4A in January, and Azure's Cobalt 200 is still rolling out. I compare what each vendor claims with what the price lists say, list what breaks when you move, and show how I would run a mixed amd64/arm64 Kubernetes cluster without paging myself at 3 AM.
What changed for ARM in the cloud in 2026?
Three things, roughly in order of how much they matter to an operator.
Graviton5 shipped. AWS announced it at re:Invent in December 2025 and made M9g and M9gd generally available on 10 June 2026, first in four regions. In September it added Ireland, Singapore, Sydney and Tokyo. The chip has 192 cores and runs at 3.3 GHz on Arm Neoverse V3 cores (Armv9.2), up from Graviton4's Neoverse V2 at 2.8 GHz, according to the AWS Graviton Technical Guide. AWS claims up to 25% better compute performance than Graviton4, up to 35% faster web applications and ML inference, and up to 30% faster databases. Those are vendor numbers, labelled "up to", and you should treat them that way.
Google filled out its Axion line. C4A (the first Axion series, October 2024) was joined by N4A, generally available since 27 January 2026. It is built on Neoverse N3 cores, scales to 64 vCPUs and 512 GB, and is aimed at cheap scale-out work rather than peak single-thread speed.
Azure is between generations. The Cobalt 100 Dpsv6 series runs at 3.4 GHz with a full physical core per vCPU, up to 96 vCPUs. Cobalt 200 moves to Neoverse V3 on TSMC 3 nm and up to 128 vCPUs. Microsoft claims up to 50% better performance than Cobalt 100. In June it was in early access preview in eight regions, and I could not find a general availability announcement as of today.
The adoption signal is also clear. AWS says more than half of new CPU capacity it added has been Graviton for three years running, and that 98% of its top 1,000 EC2 customers have used Graviton (Amazon press release). ARM in the cloud is no longer a side project. It is the default capacity AWS is building.
Graviton vs x86 price-performance: what do the price lists say?
Vendor slides compare price-performance, which mixes a benchmark they chose with a price. The price half you can check yourself. I pulled AWS's public on-demand price file for US East (N. Virginia), Linux, published 29 October 2026, and compared the 4 vCPU / 16 GiB general-purpose sizes:
| Instance (xlarge) | CPU | On-demand $/hr | vs m8i | Source |
|---|---|---|---|---|
| m7g | Graviton3 | 0.1632 | 23% cheaper | AWS price list, us-east-1 |
| m8g | Graviton4 | 0.1795 | 15% cheaper | AWS price list, us-east-1 |
| m9g | Graviton5 | 0.1957 | 8% cheaper | AWS price list, us-east-1 |
| m7i | Intel Sapphire Rapids | 0.2016 | 5% cheaper | AWS price list, us-east-1 |
| m8i | Intel Granite Rapids | 0.2117 | baseline | AWS price list, us-east-1 |
| m7a | AMD EPYC Genoa | 0.2318 | 10% dearer | AWS price list, us-east-1 |
| m8a | AMD EPYC Turin | 0.2434 | 15% dearer | AWS price list, us-east-1 |
Two things stand out. First, m9g costs 9% more per hour than m8g. If AWS's "up to 25%" holds for your workload, you still come out ahead per unit of work. If you run a fixed node count and do not right-size, you just pay 9% more. Second, every Graviton generation is still cheaper per hour than every current x86 option in the same shape. That matches the Graviton page's "up to 20% less" claim.
Also count the cores. A Graviton vCPU is a physical core: Graviton has no SMT, which is why the CPU options docs list it among the instances where you cannot change threads per core. On SMT x86 instances, each vCPU is one hardware thread, so an m5.xlarge is two cores with two threads each (EC2 CPU options docs). Some x86 families, such as AMD's M7a, also run one thread per core. So "4 vCPUs" does not mean the same hardware across rows. This is why CPU-bound services often need fewer Graviton vCPUs, and also why a benchmark on one 4 vCPU instance tells you little about a different family.
Google Axion and Azure Cobalt: how do the claims compare?
Google's N4A claims are the boldest: up to 2x better price-performance and 80% better performance per watt than comparable current x86 VMs. Read the breakdown, though. It is up to 105% for compute-bound work, 90% for web serving, 85% for Java and only 20% for general-purpose databases, based on estimated SPEC numbers as of October 2025 (Google Cloud blog). The database figure is the one I would plan around, because databases are where most of the bill usually sits.
The best independent check I found is DoiT's N4A benchmark, which used sysbench, 7-Zip and OpenSSL. N4A beat C4A by 13.7% and AWS M8g by 21.7% on sysbench CPU. It listed at $0.0385 an hour per vCPU with 4 GB in us-central1, against $0.0449 for C4A. Microbenchmarks are not your application, but they agree on the direction.
Azure publishes the least comparable data. The Cobalt 200 post lists workload uplifts over Cobalt 100: up to 135% for cloud databases, 80% for caching and 40% for web serving. It gives no x86 comparison and no prices. Until Cobalt 200 is GA in your region, Dpsv6 on Cobalt 100 is what you can actually buy.
| Provider | Current ARM chip | Core | Status (Oct 2026) | Headline vendor claim | Source |
|---|---|---|---|---|---|
| AWS | Graviton5 (M9g, M9gd) | Neoverse V3, 192 cores | GA since 10 Jun 2026, 8 regions | Up to 25% faster than Graviton4 | AWS News Blog |
| AWS | Graviton4 (C8g, M8g, R8g, X8g, I8g) | Neoverse V2 | GA, broad | Up to 20% lower cost than x86 | AWS Graviton |
| Axion N4A | Neoverse N3, up to 64 vCPU | GA since 27 Jan 2026 | Up to 2x price-performance vs x86 | Google Cloud blog | |
| Axion C4A | Axion | GA since Oct 2024 | Up to 100 Gbps networking, Titanium SSD | Google Cloud blog | |
| Azure | Cobalt 100 (Dpsv6) | 3.4 GHz, up to 96 vCPU | GA | Physical core per vCPU | Microsoft Learn |
| Azure | Cobalt 200 (Dpsv7 and others) | Neoverse V3, up to 128 vCPU | Early access preview (June) | Up to 50% faster than Cobalt 100 | Azure blog |
What breaks when you migrate to Graviton or any arm64 target?
In my experience the compiler is rarely the problem. The build and dependency chain is. Here is what fails, roughly in order of how often:
- Images with no arm64 variant. A tag that is a single-platform amd64 manifest fails on an arm64 node with
exec format error(the process starts and dies, so the pod shows up as CrashLoopBackOff). It can also fail at pull time withno match for platform in manifest. Check base images, sidecars, init containers and DaemonSets. The vendor security agent is usually the last one to support arm64. - Hard-coded architecture in Dockerfiles.
curl .../kubectl/linux/amd64/kubectlor-x86_64.tar.gzworks fine on your laptop until your laptop is a Mac. The fix is to use BuildKit'sTARGETARCHargument, which I walk through in the companion guide on building multi-arch Docker images with buildx. - Native extensions. Python packages need
aarch64manylinux wheels, or pip compiles from source and needs a toolchain. Node addons need prebuiltlinux-arm64binaries. Java apps with JNI libraries need an arm64.so. AWS's guide notes that pip 19.3 or later is required to install wheel binaries on Graviton. - x86-only code paths. Hand-written AVX intrinsics,
-march=x86-64-v3in build flags, and assembly in old crypto or compression libraries. The Graviton Technical Guide keeps a table of minimum versions worth upgrading to. For example, it recommends zlib-ng 2.3.3 or later, because stock zlib has no Arm optimisations. - 32-bit Arm binaries. Graviton4 and Graviton5 have no 32-bit backward compatibility, even in userspace. Graviton2 and 3 did, according to the guide's processor table. If something in your image is
armv7, it will not run. - Old runtimes. Older JDKs, .NET versions and interpreters have weaker arm64 code generation. The guide recommends .NET 8 as a minimum and .NET 10 for new projects, and PostgreSQL 15 or later for its Arm spin-lock work.
None of this is exotic. Before you migrate anything, run an inventory of every image a cluster actually runs and check which ones publish arm64:
#!/usr/bin/env bash
# Audit: which running images lack a linux/arm64 variant?
# Needs kubectl, docker buildx (v0.38.1 tested for imagetools) and jq 1.7+.
set -euo pipefail
kubectl get pods -A -o json \
| jq -r '.items[].spec | (.containers + (.initContainers // []))[].image' \
| sort -u \
| while read -r img; do
# --raw prints the index/manifest JSON; a plain manifest has no .manifests
platforms=$(docker buildx imagetools inspect --raw "$img" 2>/dev/null \
| jq -r '[.manifests[]?.platform | select(.os=="linux") | .architecture] | join(",")')
case ",$platforms," in
*,arm64,*) echo "ok $img" ;;
",,") echo "SINGLE $img (not an index: check its config architecture)" ;;
*) echo "MISSING $img ($platforms)" ;;
esac
done
Every MISSING line is a ticket. Every SINGLE line means someone pushed a single-platform image, and you need to know which platform it was before you schedule it anywhere new.
How do you run a mixed amd64 and arm64 Kubernetes cluster?
Kubernetes already handles most of this. Every node gets the well-known kubernetes.io/arch label, and a container runtime pulls the matching entry from a multi-arch image index. So a mixed cluster is safe exactly when every image is multi-arch. The danger is the one image that is not.
The providers differ in their defaults. In Standard clusters, GKE places a kubernetes.io/arch=arm64:NoSchedule taint on all Arm nodes, and adds the toleration automatically when a workload selects kubernetes.io/arch: arm64. So nothing lands on Arm nodes by accident. That is a sensible default. On EKS with Karpenter, a NodePool that allows both architectures will pick whichever is cheapest for pending pods, and that is often Graviton. You get the savings only if your images can follow:
# Karpenter v1.15.1 (karpenter.sh/v1). One NodePool for both architectures.
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: general
spec:
template:
metadata:
labels:
workload-tier: general
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: kubernetes.io/arch
operator: In
values: ["arm64", "amd64"] # Karpenter picks the cheapest fit
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand", "spot"]
---
# Pin anything you have NOT verified on arm64 until the audit says otherwise.
apiVersion: apps/v1
kind: Deployment
metadata:
name: legacy-reporting
spec:
replicas: 2
selector:
matchLabels: { app: legacy-reporting }
template:
metadata:
labels: { app: legacy-reporting }
spec:
nodeSelector:
kubernetes.io/arch: amd64
containers:
- name: app
image: registry.example.com/legacy-reporting:4.2.0
I prefer the inverse of GKE's default when I am rolling out: keep the existing x86 NodePool, add an arm64 NodePool with a taint, and move services one at a time by adding a toleration. That gives you a per-service rollback switch, which is worth more than getting the savings a week sooner. For the autoscaling side, see my explainer on Kubernetes autoscaling with HPA, VPA, KEDA and Karpenter.
DaemonSets need special attention. A logging or security agent without an arm64 build will be scheduled onto the new nodes and crash there. That leaves you with nodes that look healthy and send no logs. That is the kind of silent failure that platform discipline exists to catch, whether the next pull request came from a human or a coding agent.
Is Graviton5 worth it over Graviton4, and where is ARM still a bad fit?
For new capacity, go with the newest generation available in your region. That is M9g for general-purpose work where it exists, and C8g or R8g for compute- or memory-heavy shapes until Graviton5 versions of those arrive. For existing M8g fleets, the 9% price rise means you should benchmark before switching. AWS's published customer results (ClickHouse and Honeycomb each report around 36%) come from the same launch post that sells the chip. They are encouraging, but they are not neutral.
ARM is still the wrong first move for:
- Commercial software licensed per x86 core or not built for arm64. Check the vendor's support matrix, not the GitHub issue thread.
- Workloads tied to x86 accelerators or instruction sets, such as AVX-512-tuned numeric code you do not control.
- Small, idle services. The 10 to 20% discount on a t4g instance doing nothing (t4g.medium lists 19% below t3.medium and 11% below t3a.medium in us-east-1) is real but small. Fix utilisation first. My piece on Kubernetes cost optimisation and the 8% CPU problem is the bigger lever.
Serverless is the cheapest place to start. Lambda's arm64 duration price is 20% lower than x86, and AWS claims up to 34% better price-performance (AWS Graviton guide, Lambda section). Pure Python or Node functions with no native dependencies often move with a one-line architecture change.
FAQ
Is AWS Graviton cheaper than x86 in 2026?
Yes, per hour. In us-east-1 on-demand pricing (October 2026), an m8g.xlarge costs about 15% less than an m8i.xlarge, and the newer m9g.xlarge about 8% less. Whether it is cheaper per request depends on your workload, so measure throughput on both before committing to Savings Plans.
Will my Docker images run on ARM64?
Only if they publish a linux/arm64 variant in a multi-arch image index, or are built natively for arm64. Most official base images do. Your own images need building with docker buildx build --platform linux/amd64,linux/arm64, and third-party sidecars and agents need checking one by one.
Can a Kubernetes cluster mix amd64 and arm64 nodes?
Yes. Nodes carry the kubernetes.io/arch label and runtimes pull the matching image variant automatically. Use taints or node selectors to keep unverified workloads on amd64 until each image is confirmed multi-arch. GKE Standard clusters do this by default by tainting Arm nodes.
Is Graviton5 faster than Graviton4?
AWS claims up to 25% better compute performance, up to 35% for web and ML inference, and up to 30% for databases. The m9g price per hour is 9% higher than m8g, so the net gain depends on whether your workload sees the upper end of that range.
This quarter, I would run the image audit script against every cluster, fix the Dockerfiles that hard-code amd64, and turn on multi-arch builds in CI for everything we own, even before a single ARM node exists. Then I would add one tainted arm64 NodePool, move the three most CPU-hungry stateless services onto it, and compare cost per request for a month before touching anything else. The CPUs are ready. The question is whether your supply chain of images is.
Related: Docker in 2026: Engine 29, containerd 2.3 LTS, Podman 6 and the AI Push, How to Reduce Docker Image Size: Multi-Stage Builds Guide (2026) and Is Kubernetes Still Worth It in 2026? v1.37, 82% in Production, Real Costs.
I'm Ajay Kumar — I build and operate PandaStack, an open-source Firecracker microVM cloud for AI agents, and write about the infrastructure and tooling around it.
Need this kind of infrastructure work? See what I do or email hello@ajayk.sh.
Related
Amazon EKS in 2026: 1.37, $0.60 Extended Support and Auto Mode Explained
Amazon EKS in October 2026: Kubernetes 1.34 to 1.37 in standard support at $0.10 an hour, 1.31 to 1.33 in extended support at $0.60, what the Auto Mode fee buys, Pod Identity vs IRSA, Hybrid Nodes pricing, the new 7-day rollback, and when EKS is the right choice.
13 minOct 31, 2026Amazon S3 Explained (2026): Storage Classes, Real Prices and Egress
Amazon S3 in 2026 explained for engineers: every storage class with current us-east-1 prices, request and egress costs, Intelligent-Tiering break-even, Express One Zone, S3 Tables, Vectors and Files, security defaults, and how S3 compares with Cloudflare R2 and Google Cloud Storage.
13 minOct 31, 2026AWS VPC Explained (2026): Subnets, NAT Gateways, Endpoints and Costs
AWS VPC explained in plain English for 2026: CIDRs and the 5 reserved IPs, public vs private subnets, NAT gateway pricing ($0.045/hour and per GB) and the new regional NAT, security groups vs NACLs, endpoints, peering vs Transit Gateway vs Cloud WAN, and the IPv4 charge.
13 min