# How to Run GitHub Actions on ARM (and Whether You Should)

> ARM runners are cheaper per minute across every provider. What actually breaks when you switch, how to build multi-arch images, and when to stay on x64.

Source: https://latchkey.dev/learn/optimize-ci/how-to-run-github-actions-on-arm  
Updated: 2026-08-20

Every provider prices ARM below x64, frequently by 25 to 40%. It is the largest unclaimed CI saving available, and the reason most teams skip it is a compatibility fear that is mostly out of date.

ARM is cheaper on every runner price list. GitHub lists Linux arm64 2-core at $0.005/min against $0.006 for x64; Blacksmith lists $0.0025 against $0.004; WarpBuild lists arm64 25% below its own x64 rates at every size.

The historical objection was that the ecosystem was not ready. For most interpreted and JIT languages that has not been true for some time. The remaining risk is concentrated in native dependencies and prebuilt binaries, which is testable in an afternoon.

## What the saving actually is

| Provider | Linux x64, 2 vCPU | Linux arm64, 2 vCPU | Difference |
| --- | --- | --- | --- |
| GitHub-hosted | $0.006/min | $0.005/min | 17% |
| Blacksmith | $0.004/min | $0.0025/min | 38% |
| WarpBuild | $0.004/min | $0.003/min | 25% |
| Semaphore | $0.0075/min | $0.003/min | 60% |

## Switch and see what breaks

```.github/workflows/ci.yml
jobs:
  test:
    runs-on: ubuntu-24.04-arm    # GitHub-hosted ARM
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npm ci && npm test
```

> Run this on one job for a week before migrating anything else. Failures will be concentrated in native modules and downloaded binaries, and they surface immediately rather than subtly.

## What actually breaks

- **Native modules without ARM prebuilds.** They fall back to compiling from source, which needs a toolchain present and is slower. Usually it works; occasionally it fails outright.
- **Downloaded binaries with a hardcoded architecture.** Any script fetching an `x86_64` release asset breaks. Detect the architecture rather than assuming it.
- **Docker images without an arm64 variant.** A single-arch base image fails to pull, or silently runs under emulation and is dramatically slower.
- **Anything vendored as a compiled artifact** where you never controlled the build.

## Building multi-arch images

```.github/workflows/ci.yml
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
  with:
    platforms: linux/amd64,linux/arm64
    push: true
    tags: ghcr.io/${{ github.repository }}:latest
    cache-from: type=gha
    cache-to: type=gha,mode=max
```

> QEMU emulation is correct but slow, often several times slower than native. If multi-arch builds matter, build each architecture on a native runner of that architecture and merge the manifest, rather than emulating one on the other.

## Measure before you optimise

Pipeline optimisation usually targets the step people assume is slow. Get the real per-step timings first, because the answer is frequently dependency install or a cold cache rather than the build itself.

```Terminal
# per-job timings for the last 20 runs
gh run list --limit 20 --json databaseId,conclusion,createdAt,updatedAt \
  --jq '.[] | "\(.conclusion)\t\(.createdAt)\t\(.updatedAt)"'

# per-step timing inside one run
gh run view <run-id> --log | grep -E "^\S+\s+.*Run |##\[group\]" | head -40
```

> Compare a cold-cache run against a warm one. If most of the difference is install time, caching is the win; if it is not, caching will change nothing and the build itself needs the attention.

## FAQ

### Are ARM runners cheaper?

Yes, on every provider that publishes both. GitHub-hosted arm64 is $0.005/min against $0.006 for x64; Blacksmith is $0.0025 against $0.004; Semaphore is $0.003 against $0.0075. It is usually the largest unclaimed saving in a CI budget.

### Will my build work on ARM?

For most interpreted and JIT languages, yes, with no changes. Risk is concentrated in native modules without ARM prebuilds, scripts that download x86_64 binaries, and Docker base images with no arm64 variant. Test one job for a week; failures surface immediately.

### Is ARM slower than x64?

Not inherently, and modern ARM server cores are competitive or better per clock. It is dramatically slower if you accidentally run x64 images under QEMU emulation, which is the usual cause of an "ARM is slow" conclusion.

### How do I build images for both architectures?

Use buildx with `platforms: linux/amd64,linux/arm64`. For speed, build each architecture on a native runner and merge the manifest rather than emulating, since QEMU is several times slower than native.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
