Skip to main content
Bun is designed to be a drop-in replacement for Node.js. Popular frameworks like Next.js, Express, and millions of npm packages intended for Node.js work with Bun without changes. To validate this, Bun runs thousands of tests from Node.js’s own test suite before every release.
If a package works in Node.js but doesn’t work in Bun, that’s a bug in Bun. Open an issue and it will be fixed.
The compatibility information on this page reflects Bun’s support for Node.js v23 APIs.

Module system

Bun supports both CommonJS and ES modules. You can use require() and import in the same project, and Bun handles the interop automatically.
import { readFileSync } from "node:fs";
const contents = readFileSync("./file.txt", "utf8");
require() is fully implemented, including require.main, require.cache, and require.resolve.

npm packages

npm packages install and run with Bun without any changes. Bun reads package.json, resolves dependencies from node_modules, and handles both CJS and ESM packages.
bun install        # reads package.json, installs deps
bun run index.ts   # runs your code with full npm resolution

Node.js globals

Bun exposes the same globals Node.js does. These are available without any imports.
GlobalStatusNotes
processMostly implementedprocess.binding partially implemented; process.title is a no-op on macOS and Linux
BufferFully implemented
__dirnameFully implemented
__filenameFully implemented
globalFully implementedObject containing all globals in the global namespace
globalThisFully implementedAliases to global
moduleFully implemented
exportsFully implemented
require()Fully implemented

process

process is available globally without importing node:process. Most properties and methods are implemented.
console.log(process.version);     // e.g. "v23.0.0"
console.log(process.platform);    // "linux", "darwin", "win32"
console.log(process.env.HOME);    // reads environment variables
process.exit(0);
process.binding (used by some packages to access Node.js internals) is partially implemented. getActiveResourcesInfo, setActiveResourcesInfo, getActiveResources, and setSourceMapsEnabled are stubs. process.loadEnvFile and process.getBuiltinModule are not yet implemented.

Buffer

Buffer is a global subclass of Uint8Array, identical to Node.js.
const buf = Buffer.from("hello world", "utf8");
console.log(buf.toString("hex"));
console.log(buf.toString("base64"));

Built-in modules

Fully implemented

These modules pass 90–100% of Node.js’s own test suite.

node:assert

Fully implemented.

node:buffer

Fully implemented.

node:console

Fully implemented.

node:dgram

Fully implemented. Over 90% of Node.js’s test suite passes.

node:diagnostics_channel

Fully implemented.

node:dns

Fully implemented. Over 90% of Node.js’s test suite passes.

node:events

Fully implemented. 100% of Node.js’s test suite passes. EventEmitterAsyncResource uses AsyncResource underneath.

node:fs

Fully implemented. 92% of Node.js’s test suite passes.

node:http

Fully implemented. Outgoing client request body is currently buffered instead of streamed.

node:https

APIs are implemented; Agent is not always used yet.

node:net

Fully implemented.

node:os

Fully implemented. 100% of Node.js’s test suite passes.

node:path

Fully implemented. 100% of Node.js’s test suite passes.

node:querystring

Fully implemented. 100% of Node.js’s test suite passes.

node:readline

Fully implemented.

node:stream

Fully implemented.

node:string_decoder

Fully implemented. 100% of Node.js’s test suite passes.

node:timers

Fully implemented. Prefer the global setTimeout and setInterval directly.

node:tty

Fully implemented.

node:url

Fully implemented.

node:zlib

Fully implemented. 98% of Node.js’s test suite passes.

Partially implemented

These modules work for most use cases but have some gaps compared to Node.js.
ModuleStatus
node:async_hooksAsyncLocalStorage and AsyncResource are implemented. V8 promise hooks are not called.
node:child_processMissing proc.gid, proc.uid. Stream class not exported. IPC cannot send socket handles. Node.js ↔ Bun IPC works with JSON serialization.
node:clusterHandles and file descriptors cannot be passed between workers. Load-balancing HTTP across processes is only supported on Linux (via SO_REUSEPORT).
node:cryptoMissing secureHeapUsed, setEngine, setFips.
node:domainMissing Domain, active.
node:http2Client and server implemented (95.25% of gRPC’s test suite passes). Missing options.allowHTTP1, options.enableConnectProtocol, ALTSVC extension, and http2stream.pushStream.
node:inspectorProfiler API is supported. Other inspector APIs are not yet implemented.
node:moduleMissing syncBuiltinESMExports, Module#load(). module.register is not implemented — use Bun.plugin instead.
node:perf_hooksAPIs implemented but Node.js test suite does not pass yet.
node:processSee process global.
node:testPartially implemented. Missing mocks, snapshots, timers. Use bun:test instead.
node:tlsMissing tls.createSecurePair.
node:utilMissing getCallSite, getCallSites, getSystemErrorMap, getSystemErrorMessage, transferableAbortSignal, transferableAbortController.
node:v8writeHeapSnapshot and getHeapSnapshot implemented. serialize and deserialize use JavaScriptCore’s wire format, not V8’s. Use bun:jsc for profiling.
node:vmCore functionality and ES modules are implemented. Missing vm.measureMemory and some cachedData functionality.
node:wasiPartially implemented.
node:worker_threadsWorker doesn’t support stdin, stdout, stderr, trackedUnmanagedFds, resourceLimits. Missing markAsUntransferable, moveMessagePortToContext.

Not yet implemented

ModuleNotes
node:replNot implemented.
node:sqliteNot implemented. Use bun:sqlite instead.
node:trace_eventsNot implemented.

N-API (native addons)

Bun implements approximately 95% of the Node-API (N-API) interface. Most existing native addons built for Node.js work with Bun out of the box.
// .node files can be required directly
const napi = require("./my-node-module.node");

// Or loaded via process.dlopen
let mod = { exports: {} };
process.dlopen(mod, "./my-node-module.node");
For building new native addons, writing a Node-API (NAPI) module is the most stable way to interact with native code from Bun. bun:ffi is available but experimental.

JavaScriptCore vs V8

Bun uses JavaScriptCore (JSC), the engine from WebKit, rather than V8. This means:
  • Standard JavaScript behavior is identical — all ECMAScript-compliant code runs the same way.
  • V8-specific internal APIs (such as v8.serialize wire format) may differ.
  • node:v8’s serialize and deserialize use JSC’s wire format, not V8’s.
  • The --inspect protocol is compatible but Bun’s debugger integration is distinct.
For most application code and npm packages, the difference is invisible. Packages that rely on V8 internals directly (e.g. some profiling tools) may require updates.

Build docs developers (and LLMs) love