os.arch()

Returns the CPU architecture the Node.js binary was compiled for, such as 'x64' or 'arm64'.

Signature
os.arch()
  • Added in Node.js v0.5.0

Return value

stringThe operating system CPU architecture the Node.js binary was compiled for. Possible values are 'arm', 'arm64', 'ia32', 'loong64', 'mips', 'mipsel', 'ppc64', 'riscv64', 's390x' and 'x64'.

os.arch() reports the CPU architecture that the Node binary was built for, not necessarily the one the hardware could run. It is identical to process.arch and fixed at compile time.

When to reach for it

Almost always alongside os.platform(), to name a build artifact. Prebuilt native modules, downloaded toolchains and release tarballs are keyed on the platform-arch pair — darwin-arm64, linux-x64, win32-ia32 — so a helper that joins the two is the usual reason to call it.

What trips people up

The distinction between the binary and the machine. On an Apple Silicon Mac, an x64 Node running under Rosetta 2 returns 'x64', because that is what it was compiled for; the hardware is arm64. The same happens with a 32-bit Node on 64-bit Windows, which returns 'ia32'. If you use os.arch() to pick a native .node addon this is the behaviour you want, since the addon must match the Node process. If you are reporting hardware, it will mislead you.

Also note 'ia32', not 'x86', and 'arm64', not 'aarch64' — the Node names differ from what uname -m prints.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Build the platform-arch key used to download a prebuilt native module
  • Pick the right architecture-specific asset name in a release script
  • Include the architecture in a crash report so a native module mismatch is visible

Frequently asked questions

How do I tell if Node.js is running on Apple Silicon?

Check os.arch() === 'arm64' together with os.platform() === 'darwin'. Be aware that an x64 Node under Rosetta 2 on the same hardware reports 'x64', so cross-check os.cpus()[0].model for an "Apple M" string if you need to know what the machine really is.

What is the difference between os.arch() and uname -m?

They describe different things and use different names. uname -m reports the machine's hardware architecture, while os.arch() reports what the Node binary was compiled for — and Node writes 'arm64' where uname says 'aarch64', and 'ia32' where uname says 'i686'.

Which values can os.arch() return?

'arm', 'arm64', 'ia32', 'loong64', 'mips', 'mipsel', 'ppc64', 'riscv64', 's390x' and 'x64'. In practice only x64 and arm64 matter for most deployments, but treat anything outside your allow-list as a fall-back-to-source case rather than an error.

More examples

Name a prebuilt artifact

The generated filenames are the naming convention almost every prebuild-hosting package follows. The ABI and N-API version lines matter too: a native addon must match the module ABI as well as the platform and architecture, which is why a working .node file for linux-x64 still fails across major Node versions.

Example · javascript
const os = require('node:os');

function artifactName(pkg, version) {
  const ext = os.platform() === 'win32' ? '.zip' : '.tar.gz';
  return `${pkg}-v${version}-${os.platform()}-${os.arch()}${ext}`;
}

console.log(artifactName('sharp', '0.33.2'));
console.log(artifactName('esbuild', '0.20.0'));
console.log('abi version:', process.versions.modules);
console.log('napi versions:', process.versions.napi);

Detect Rosetta translation on macOS

On a native arm64 Node the else branch prints. Under Rosetta, os.arch() says x64 while the CPU model still reads "Apple M", and that mismatch is the tell — it explains both the performance loss and why arm64 prebuilt addons refuse to load.

Example · javascript
const os = require('node:os');

// os.arch() describes the binary; the CPU model hints at the real hardware.
const arch = os.arch();
const model = os.cpus()[0]?.model ?? '';
const appleSiliconHardware = /Apple M\d/.test(model);

console.log('node built for:', arch);
console.log('cpu model suggests Apple Silicon:', appleSiliconHardware);

if (os.platform() === 'darwin' && arch === 'x64' && appleSiliconHardware) {
  console.log('likely running under Rosetta 2 — install an arm64 Node for full speed');
} else {
  console.log('architecture and hardware agree');
}

Guard a build script against unsupported targets

An explicit allow-list turns an obscure runtime failure into a clear message at install time. The value of printing every supported target is that someone on linux-ppc64 immediately sees their platform is not in the set, instead of debugging a missing .node file.

Example · javascript
const os = require('node:os');

const SUPPORTED = new Set(['linux-x64', 'linux-arm64', 'darwin-x64', 'darwin-arm64', 'win32-x64']);

const target = `${os.platform()}-${os.arch()}`;

console.log('target:', target);
console.log('supported:', SUPPORTED.has(target));

if (!SUPPORTED.has(target)) {
  console.log('no prebuilt binary — falling back to compiling from source');
} else {
  console.log('prebuilt binary available');
}

console.log('all supported targets:', [...SUPPORTED].join(', '));

Discussion

  • Be the first to comment on this lesson.