Native arm64 is the default now

Every Apple silicon Mac has an arm64 CPU. A Mac app compiled for arm64 runs on it directly, and so does a Linux guest with an arm64 kernel and userland, which is what the Virtualization framework boots (see the VM fundamentals post). That's the fast, unremarkable path: native code on native silicon. The rest of this post is about what happens when the software you need wasn't built for it.

Rosetta 2 for Mac apps, and why it's not Rosetta for Linux

The name covers two different mechanisms. Rosetta 2 for Mac apps is the system-wide translation layer that lets an Intel-only Mac app run on Apple silicon the moment you open it, with no setup. Rosetta for Linux, covered in Rosetta 2 in Linux VMs, works inside a guest: Velo Workspaces shares it into a Linux VM over VirtioFS, you register it once with binfmt, and it translates x86-64 binaries you run there. Same name, same Apple technology, different integration and different limits, so don't assume a fact about one applies to the other.

Universal binaries are why well-maintained Mac apps don't need Rosetta at all. One app bundle can carry both arm64 and x86_64 code, and macOS picks the right one at launch. An app that's still Intel-only just hasn't shipped the second half yet; that's a build setting, not a platform limit.

Package managers: two install prefixes, on purpose

Homebrew makes the split visible. On Apple silicon it installs to /opt/homebrew; on an Intel Mac, or a Homebrew run under Rosetta with arch -x86_64, it uses /usr/local. Two prefixes let both trees live side by side without one quietly shadowing the other. The same problem shows up one level down inside a Linux guest, where a distribution's arm64 repository doesn't always carry every amd64 package; the compatibility triage post covers what to do about it.

Containers: one name, several images

A multi-arch container image is really a manifest list pointing at separate arm64 and amd64 builds, and the registry serves whichever matches the machine pulling it. That's why docker pull behaves the same on an Apple silicon Mac and an x86 CI server for a well-maintained image. Ask for the architecture you don't have, with --platform linux/amd64, and Docker falls back to QEMU's software emulation (the TCG mechanism in the Virtualization.framework vs. QEMU post). It works, but it's emulated and noticeably slower for CPU-heavy work. Running x86 Docker images on an Apple Silicon Mac has a faster path if you run Docker inside a Linux VM with Rosetta set up.

CI: check what your runner is

This changed recently enough to state plainly. GitHub Actions' macos-26 label, the current default macOS runner, runs on Apple silicon (arm64), with a separate macos-26-intel label for x64, and Intel macOS runners are being phased out by August 2027. If your build matrix assumes "the macOS runner" means x86-64, it's testing an architecture fewer and fewer of your users run. Matching the runner to what ships is a small check, not an edge case.

The practical version

Architecture mismatches bite in a few predictable places: a dependency that only ships x86-64 binaries, a container image with no multi-arch manifest, a CI runner on the wrong architecture, or a Linux package your distribution never built for arm64. None of that is Apple silicon being difficult. It's the ordinary tail of a platform transition that's several years in and mostly finished.

Related reading: what a VM on Apple Silicon is, Rosetta in Linux VMs, Virtualization.framework vs. QEMU, and why Arch Linux has no official arm64 build. Or download Velo Workspaces and try it yourself.