GitHub Actions supports both x64 and ARM64 runner environments, giving teams more options for building and testing modern applications.
At first glance, moving a workflow from an x64 runner to ARM64 may look as simple as changing:
runs-on: ubuntu-latest
to an ARM64 runner label.
In practice, the processor architecture affects more than the operating system. Native binaries, Docker images, package managers, language runtimes, third-party tools, and compiled dependencies can all behave differently when the architecture changes.
GitHub provides ARM64 hosted runners for supported plans and repositories, including Ubuntu ARM64 environments. GitHub's runner documentation also distinguishes standard x64 and Arm64 runner images and their supported labels.
This article explains what developers should check before moving GitHub Actions workflows to ARM64 runners and how to test the migration safely.
What Is an ARM64 Runner?
ARM64, also called AArch64, is a 64-bit processor architecture based on the ARM instruction set.
Traditional GitHub-hosted Linux CI environments have commonly used x86-64 processors.
The architecture difference can be represented as:
x64
|
+-- Intel/AMD instruction set
|
+-- x86-64 binaries
|
+-- x64 container images
ARM64
|
+-- ARM instruction set
|
+-- ARM64 binaries
|
+-- ARM64 container images
Your application code may not care about this difference.
Native dependencies often do.
For example, a managed .NET application may run on both architectures, while a native library loaded by that application may only have an x64 binary.
That is where migration problems usually appear.
Why Use ARM64 in GitHub Actions?
ARM64 runners can be useful when your production infrastructure or development environments already use ARM-based systems.
Typical examples include:
ARM-based cloud infrastructure
ARM64 container deployments
multi-architecture Docker images
cross-platform application testing
software distributed for both x64 and ARM64
workloads that specifically require ARM64 validation
There is also an important testing benefit.
If your application is eventually deployed to ARM64 infrastructure, testing only on x64 can leave architecture-specific problems undiscovered until later.
Check Runner Availability First
Before modifying a workflow, verify that the ARM64 runner type you want is available for your GitHub plan and repository.
GitHub-hosted runner availability differs by account type and operating system. GitHub also documents separate labels and specifications for Arm64 runners.
Do not assume that every workflow using:
runs-on: ubuntu-latest
can simply be changed to an ARM64 equivalent.
First confirm:
The required ARM64 hosted runner is available.
The repository is eligible to use it.
The required operating system is supported.
Your workflow actions support the architecture.
Your application dependencies support ARM64.
Step 1: Identify Architecture-Specific Dependencies
Start by searching your repository for native dependencies.
Look for:
.dll
.so
.dylib
.exe
and package references that include architecture-specific binaries.
For example, a .NET application may contain:
runtimes/
├── linux-x64/
└── linux-arm64/
This is a good sign because the package explicitly provides architecture-specific assets.
However, if you find only:
runtimes/
└── linux-x64/
you should investigate before switching the CI runner.
A managed application can compile successfully while failing at runtime when it attempts to load an x64 native library on ARM64.
Step 2: Check Your .NET Runtime Configuration
For .NET applications, inspect the runtime identifiers used by the project.
For example:
<PropertyGroup>
<RuntimeIdentifiers>
linux-x64;linux-arm64
</RuntimeIdentifiers>
</PropertyGroup>
This tells the build system that both runtime environments are supported.
If the project only contains:
<PropertyGroup>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
</PropertyGroup>
do not assume ARM64 compatibility.
You may need to update the project configuration and verify every native dependency.
Step 3: Check GitHub Actions Used by the Workflow
Your application is not the only component that needs ARM64 support.
The workflow itself may use third-party actions.
For example:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
- uses: third-party/action@v1
The first two actions may support ARM64, but that does not automatically mean the third-party action does.
An action can contain:
JavaScript
Docker
compiled binaries
shell scripts
platform-specific executables
Actions that package native binaries require particular attention.
Before migration, check whether each important action supports ARM64.
JavaScript Actions vs Docker Actions
GitHub Actions can be implemented in different ways.
A JavaScript action may be relatively portable if it relies only on architecture-independent Node.js functionality.
A Docker-based action can be more complicated.
For example:
- uses: vendor/security-scan@v1
The action may internally use:
Docker image
|
+-- x64 binary
If the image does not have an ARM64 variant, the action may fail on an ARM64 runner.
This is why checking the action's implementation and supported platforms is important.
Step 4: Check Docker Images
Docker is one of the biggest areas to validate when moving to ARM64.
Consider:
- name: Build container
run: docker build -t sample-api .
Your Dockerfile may look perfectly normal:
FROM mcr.microsoft.com/dotnet/aspnet:10.0
WORKDIR /app
COPY . .
ENTRYPOINT ["dotnet", "SampleApi.dll"]
But the base image must support the architecture on which you are building.
Modern container registries commonly publish multi-platform images.
Conceptually:
sample-api:latest
|
+-- linux/amd64
|
+-- linux/arm64
If the image provides only:
linux/amd64
you cannot assume it will work natively on an ARM64 runner.
Check the Image Architecture
Docker can inspect an image manifest.
For example:
docker buildx imagetools inspect \
mcr.microsoft.com/dotnet/aspnet:10.0
The output can show which platforms are available.
Look for entries such as:
linux/amd64
linux/arm64
If both are present, the image is published for both architectures.
This is especially important for:
base images
database images
testing services
observability tools
security scanners
local development containers
Step 5: Check Multi-Architecture Builds
If your workflow publishes Docker images, ARM64 migration may actually be an opportunity to improve the pipeline.
For example:
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
platforms: linux/amd64,linux/arm64
push: true
tags: example/app:latest
Here, the final image can target multiple architectures.
However, building a multi-platform image is not the same thing as proving that the application works correctly on both architectures.
You should still test the application on ARM64.
Step 6: Check Package Managers
Language package managers can also expose architecture problems.
For Node.js:
npm install
For Python:
pip install -r requirements.txt
For .NET:
dotnet restore
Most popular packages work across architectures, but native packages can behave differently.
For example, a Node.js package may contain native bindings.
Python packages may depend on native libraries or require compilation.
.NET packages may contain architecture-specific runtime assets.
If installation suddenly attempts to compile something from source, the ARM64 environment may expose a dependency that was hidden on x64.
Step 7: Check Native Build Tools
ARM64 builds may require native compilation.
Check whether your workflow installs tools such as:
gcc
g++
make
cmake
clang
pkg-config
For example:
Join the conversation! Your thoughts help the community grow.