Skip to main content
workerd provides Node.js compatibility to help you run applications and packages originally designed for Node.js. This best-effort implementation enables you to use familiar Node.js APIs in your Workers.

What is Node.js compatibility?

Node.js compatibility is a layer that implements a subset of the Node.js API in workerd. When you enable the nodejs_compat flag, you can import Node.js built-in modules using the node: prefix:
import { Buffer } from 'node:buffer';
import crypto from 'node:crypto';
import path from 'node:path';

Enable Node.js compatibility

You enable Node.js compatibility using compatibility flags in your configuration:
compatibilityFlags = ["nodejs_compat"],

Compatibility flags

The nodejs_compat_v2 flag implies nodejs_compat and adds additional features like global Buffer and process objects.
workerd provides two primary Node.js compatibility flags:
  • nodejs_compat: Enables Node.js module imports with the node: prefix
  • nodejs_compat_v2: Extends nodejs_compat with:
    • Imports without the node: prefix (for example, import { Buffer } from 'buffer')
    • Global Buffer and process objects available everywhere
For projects with modern compatibility dates (after 2024-09-23), nodejs_compat automatically implies nodejs_compat_v2.

AsyncLocalStorage

You can enable AsyncLocalStorage independently of full Node.js compatibility:
compatibilityFlags = ["nodejs_als"],
This provides access to node:async_hooks for context management without enabling all Node.js APIs.

Architecture

Node.js compatibility in workerd consists of two layers:

C++ implementation layer

Located in src/workerd/api/node/, this layer provides:
  • Native implementations of performance-critical APIs (buffer operations, crypto, zlib)
  • Low-level bindings to system libraries (BoringSSL for crypto, zlib for compression)
  • Integration with workerd’s runtime primitives
C++ modules are registered via the NODEJS_MODULES macro in node.h and exposed as node-internal:* specifiers.

TypeScript implementation layer

Located in src/node/, this layer provides:
  • Public node:* module exports that you import in your code
  • JavaScript implementations of Node.js APIs built on C++ primitives
  • Compatibility shims and feature detection
The TypeScript layer imports from node-internal:* modules and re-exports them as standardized node:* APIs.

Compatibility philosophy

Node.js compatibility is best-effort. Some APIs have limitations or differences from Node.js due to workerd’s runtime environment.
workerd follows these principles for Node.js compatibility:
  1. Best-effort implementation: workerd implements a subset of the Node.js API as closely as possible, but does not aim for 100% compatibility
  2. Web standards take precedence: When Node.js implements Web Platform Standard APIs differently, workerd follows the standard specification first
  3. Backwards compatibility: Changes to Node.js compatibility require explicit opt-in through compatibility flags to avoid breaking existing Workers
  4. Runtime constraints: Some Node.js APIs cannot be implemented in workerd due to architectural differences (for example, filesystem access, child processes)
  5. Incremental improvements: Partial implementations can be merged and evolved over time, with compatibility flags protecting against breaking changes

Module gating

Many Node.js modules are gated behind specific compatibility flags. For example:
  • node:http and node:https require enable_nodejs_http_modules
  • node:fs requires enable_nodejs_fs_module
  • node:os requires enable_nodejs_os_module
When you set a compatibility date with nodejs_compat enabled, workerd automatically enables flags based on that date. Check the supported APIs page for module availability.

Next steps

Supported APIs

View the complete list of supported Node.js modules and APIs

Differences from Node.js

Learn about key differences and limitations

Build docs developers (and LLMs) love