# Bun Compatibility in 2026: What Actually Works, What Does Not, and When to Switch

"Is Bun production ready?" is the wrong question. The right question is ready for what. This is the compatibility map by Node.js API, npm package type, and Next.js use case so you can make a real decision for your specific stack.

Tags: nodejs, javascript, typescript
Published: 2026-03-11 (updated 2026-10-22)


Bun hit v1.0 in September 2023. It is now well into its production era. And yet "is Bun production ready 2026" is still a common search because "ready" means completely different things depending on your stack.

Ready for a CLI tool written in TypeScript? Absolutely, day one. Ready as a Next.js runtime for an app that uses sharp and bcrypt? The answer is more complicated and it changes by package.

This article is the compatibility map. Not benchmarks (that is covered in the [Bun vs Node.js deep dive](/blog/bun-vs-nodejs-is-it-time-to-switch-in-2026/)), not philosophy, just the practical 2026 state of what works, what breaks, and what the failure mode looks like when it does break.

**Is Bun compatible with Node.js?** Mostly. Bun implements most Node.js built-ins (`fs`, `http`, `crypto`, `stream` and more) and runs most pure-JavaScript npm packages unchanged. Problems cluster around native addons, a few Node internals and some frameworks that assume Node-specific behavior. The package table below was checked when I wrote this post in March 2026, so re-test native addons against your own versions before you switch.

---

## Node.js API Compatibility: The Current State

Bun implements the Node.js API surface, but not all of it, and some parts behave slightly differently. Here is where things stand in 2026.

### The core built-ins: solid

The APIs you use every day work:

- `node:fs` and `node:fs/promises` full compatibility, Bun's file I/O is actually faster
- `node:path`, `node:url`, `node:os` complete
- `node:http` and `node:https` implemented and compatible with Express, Fastify, and most HTTP frameworks
- `node:crypto` mostly complete; some edge cases remain around specific cipher suites and legacy methods
- `node:stream` largely implemented; occasional edge cases with transform streams in unusual configurations
- `node:buffer` full compatibility
- `node:process` complete, including `process.env`, `process.argv`, `process.exit`

For the vast majority of Node.js code, you can run it on Bun unchanged.

### The more specialized APIs: mixed

**`node:worker_threads`** implemented and usable. Performance characteristics differ because Bun uses JavaScriptCore instead of V8. For CPU-bound parallelism, worker threads work. Test your specific workload rather than assuming the behavior is identical.

**`node:cluster`** partial support as of 2026. Basic cluster forking works, but some of the more advanced cluster coordination patterns have edge cases. If your production server relies heavily on Node.js cluster for multi-process load balancing, test carefully before switching.

**`node:child_process`** solid. `spawn`, `exec`, `execFile`, and `fork` all work. The `fork` method has some nuances in how it communicates with child processes, but for most use cases it is fine.

**`node:vm`** partial and fragile. If you are using `vm.Script` or `vm.runInNewContext` for sandboxing or dynamic code evaluation, this is an area to verify specifically.

### Native addons: the main real-world blocker

This is where Bun compatibility actually breaks down, and it is worth understanding why.

Node.js native addons are C/C++ extensions compiled to binary using node-gyp or N-API. They produce `.node` files that V8 loads directly. Bun uses JavaScriptCore, not V8, so these binaries are incompatible at a fundamental level they are compiled against V8's internal structures.

Packages this affects:

- **`bcrypt`** uses native bindings, does not work. Use `bcryptjs` (pure JavaScript drop-in) or Bun's built-in `Bun.password` API instead
- **`canvas`** native addon, broken on Bun. No clean workaround if you need full canvas support
- **`better-sqlite3`** native addon, but Bun has a built-in SQLite API (`bun:sqlite`) that is faster and requires no native bindings at all
- **`sharp`** this one improved significantly. Sharp added libvips-based builds that work through WebAssembly fallback, so it works on Bun in 2026 in most configurations. Verify your platform and version.
- **`argon2`** native addon; similar to bcrypt, check for a pure-JS or Bun-native alternative

The practical check: search `your-package node-gyp` or look at the package's `binding.gyp` file. If it has one, it is a native addon and Bun will not run it.

### Bun's own APIs: the portability tradeoff

Bun ships fast native replacements for common operations:

```typescript
// Bun-native file reading faster than fs.readFile
const file = Bun.file('./data.json');
const data = await file.json();

// Bun-native HTTP server outperforms http.createServer significantly
Bun.serve({
  port: 3000,
  fetch(req) {
    return new Response('ok');
  },
});
```

These are genuinely fast. The tradeoff is portability code using `Bun.serve` or `Bun.file` does not run on Node.js without changes. Whether that matters depends on whether you ever need to deploy to a Node.js environment or whether Bun is your permanent runtime choice.

---

## npm Package Compatibility: the Practical Picture

The install story is mostly a non-story now. `bun install` reads your `package.json`, installs from the npm registry, and is dramatically faster than npm. The compatibility question is not about installation it is about what happens at runtime.

### Pure JavaScript and TypeScript packages: just works

If a package is pure JavaScript or TypeScript (no native bindings), it runs on Bun. This covers the overwhelming majority of the npm ecosystem:

- React, Vue, Svelte yes
- Zod, Valibot, TypeBox yes
- Lodash, date-fns, Ramda yes
- Axios, got, ky, node-fetch yes
- Prisma Client yes (Prisma works well on Bun since v5.4; the generated client is pure JavaScript)
- Drizzle ORM yes
- Express, Fastify, Hono, Elysia yes
- Jest (sort of Bun has its own test runner, but jest itself can run)
- TypeScript itself, ts-node, tsx yes, and largely unnecessary since Bun runs TypeScript natively

### Packages with postinstall scripts: sometimes messy

Some packages run scripts after installation to download platform-specific binaries or perform setup. These usually work, but occasionally fail if the script assumes Node.js behaviors. The failure is almost always visible during `bun install` as a warning or error it does not silently break.

`puppeteer` and `playwright` are common examples. They download browser binaries in postinstall. These generally work but can be slow or require manual intervention in certain CI environments.

### Packages using node-gyp or native compilation

Covered above under Node.js API compatibility. These are the packages to audit before committing to Bun.

A quick way to check your project's exposure:

```bash
# List packages with native bindings in your dependency tree
bun pm ls | xargs -I{} sh -c 'ls node_modules/{}/binding.gyp 2>/dev/null && echo {}'
```

Or just run `bun install` and look for gyp-related warnings, since Bun will flag them.

### Specific 2026 status for commonly used packages

This table reflects March 2026. Native-addon support changes fast, and Bun now also ships built-in alternatives (`Bun.password`, `bun:sqlite`, and `argon2` in `node:crypto`), so check the package's issue tracker and Bun's compatibility docs before ruling something out.

| Package | Status | Notes |
|---|---|---|
| Prisma | Works | Pure JS client, works since v5.4 |
| Drizzle ORM | Works | No native deps |
| sharp | Works (mostly) | WebAssembly fallback; verify your build target |
| bcrypt | Broken | Use `bcryptjs` or `Bun.password` |
| better-sqlite3 | Not needed | Use `bun:sqlite` instead |
| canvas | Broken | No practical workaround |
| argon2 | Broken | Native addon; use `argon2-browser` or alternatives |
| pg (node-postgres) | Works | Pure JS driver |
| mysql2 | Works | Pure JS driver |

---

## Next.js + Bun: the Compatibility Story

This is the question people search most specifically, and the answer has two distinct parts that are easy to conflate.

### Bun as the package manager for Next.js: yes, works great

Using `bun install` instead of `npm install` or `yarn` for a Next.js project is a straightforward win. Install times drop dramatically. Your `node_modules` are the same. Next.js does not know or care about what installed its packages.

```bash
# Works perfectly just replace npm with bun for installs
bun install
bun add some-package
bun remove old-package
```

This is the low-risk first step for any Next.js project. No compatibility concerns, instant improvement in install speed.

### Bun as the runtime for Next.js: more nuanced

Can you run `bun next dev` and `bun next build`? Yes. Does it work for most projects? Also yes. Does it work for all Next.js features? Not quite.

The key clarification first: Next.js compiles and runs through its own build pipeline. When you run `bun next dev`, Bun is executing the Next.js CLI, which then handles module loading and server-side rendering using its own bundler. You are not replacing the entire runtime with Bun's HTTP server.

**What works reliably with Bun runtime + Next.js:**
- App Router and Pages Router
- Server Components
- API Routes (both App Router route handlers and Pages API)
- Static generation and ISR
- Middleware (with caveats see below)
- Most npm packages in the Next.js context

**Known gaps and caveats as of 2026:**

Next.js Middleware runs on an edge-compatible runtime by default. When running through Bun, the edge runtime sandbox behavior can produce subtle differences from running on Node.js. If your middleware uses anything beyond basic request/response manipulation, test it explicitly.

Some `@next/` packages and plugins that assume Node.js internals can behave differently. The main one to check is `next-auth` version 5 (Auth.js) works, but older v4 installations with certain adapters can hit edge cases.

**Turbopack vs Bun's bundler clarifying the confusion**

People sometimes search "Bun vs Turbopack" as if they are competing. They are not really alternatives in the Next.js context. Turbopack is Next.js's own incremental bundler for development (`next dev --turbopack`). Bun has its own bundler (`bun build`) for general JavaScript bundling outside of frameworks.

When you run Next.js with Bun, Turbopack is still handling the bundling if you enable it. Bun is handling the process execution and module resolution. They can coexist.

**The practical recommendation:**

For most Next.js projects in 2026, using Bun as the package manager is a safe, low-effort win. Using Bun as the full runtime is worth doing if you have tested your specific package set and want the startup time and performance improvements. The safe path is: `bun install` for package management, `node` for production runtime until you have explicitly validated your project.

For the TypeScript angle on running without a build step, the [native type stripping in Node.js article](/blog/typescript-without-a-build-step-native-type-stripping-in-nodejs/) covers how Node.js is closing this gap, which changes the calculus on Bun adoption for TypeScript projects specifically.

---

## Where Bun Genuinely Wins in Production Today

There are categories where Bun is not just "ready" it is the better choice.

**Standalone API servers and microservices without native addons.** If you are building an HTTP API in TypeScript using Prisma, Drizzle, or a pure-JS database client, Bun is excellent. The startup time, memory footprint, and HTTP throughput are all better than Node.js. Hono on Bun is a particularly good pairing if you are evaluating Hono as your framework, the [Hono.js vs Express comparison](/blog/honojs-vs-express-2026/) covers whether the switch makes sense for your project.

**Scripts, CLIs, and build tooling.** This is where Bun's startup speed advantage is most tangible. A script that starts in 40ms instead of 180ms feels snappy. Bun's native TypeScript execution means no compilation step for these tools. If you write any internal tooling, dev scripts, or CLI utilities in TypeScript, Bun should be your first choice.

**Bun's test runner in CI.** `bun test` is fast, Jest-compatible for basic assertions, and requires no configuration for TypeScript. For most projects, you can replace Jest with `bun test` and cut CI test times noticeably. The runner is mature enough for production CI pipelines.

```bash
# Drop-in for most Jest setups
bun test

# Watch mode for development
bun test --watch

# Run a specific file
bun test src/utils/helpers.test.ts
```

**Monorepo workspace management.** Bun's workspace support has improved significantly. If you have a monorepo and are tired of waiting for npm or yarn installs across a large dependency graph, Bun's install speed is a genuine production-grade improvement.

---

## Where You Should Still Stay on Node.js

Be honest with yourself about your project's needs.

**You have native addon dependencies that do not have alternatives.** If you are using `canvas`, certain image processing libraries, or any package where `node-gyp` is non-negotiable and there is no pure-JS equivalent, stay on Node.js. The workarounds are painful and not worth it.

**Long-running production servers where you have years of operational knowledge.** Node.js has a decade of production behavior that teams understand deeply. If your monitoring, profiling tools, and incident response playbooks are built around Node.js behavior, the cognitive overhead of switching a critical production service is a real cost.

**Teams with limited capacity to debug surprises.** Bun is not perfect. When it breaks, the error messages are sometimes less helpful than Node.js equivalents, and Stack Overflow coverage is thinner. If your team cannot absorb debugging time, the safe choice is still Node.js.

**Anything relying on specific V8 behaviors.** Bun uses JavaScriptCore. For 99% of code this is invisible. But there are edge cases around garbage collection timing, specific regex behaviors, and certain micro-benchmarking patterns that differ. If you have code that implicitly relies on V8's behavior (unusual but possible), Bun will surprise you.

---

## How to Test Your Project's Bun Readiness

Do not decide based on general advice. Test your actual project. This takes about 30 minutes.

**Step 1: Install Bun alongside Node.js**

Bun and Node.js coexist without conflict. You keep your Node.js installation.

```bash
curl -fsSL https://bun.sh/install | bash
# or: npm install -g bun
```

**Step 2: Run bun install and read the output**

```bash
bun install
```

Look for gyp warnings, native compilation failures, and postinstall script errors. These are your blockers. Everything else is cosmetic.

**Step 3: Run your test suite**

```bash
bun test
```

If you are using Jest, it will likely work directly. If some tests fail, look at whether the failures are genuine bugs or compatibility differences they usually fall into one of the patterns described above.

**Step 4: Start your dev server**

```bash
bun run dev
```

Check that your routes work, your database connections initialize correctly, and your middleware behaves as expected. For Next.js, click through the main flows of your app.

**Step 5: Check your postinstall scripts manually**

Look in your `package.json` and each package's scripts for `postinstall` entries. If any download platform binaries or run build steps, verify they completed correctly.

**Step 6: Run a quick native addon audit**

```bash
# Find packages with binding.gyp in your node_modules
find node_modules -name "binding.gyp" -maxdepth 3 | sed 's|/binding.gyp||' | sed 's|node_modules/||'
```

This gives you the list of native addon packages to evaluate individually.

---

## The Verdict

The blanket "is Bun production ready" answer is: it depends on your stack, and now you have the map to check your specific case.

**Use Bun today, confidently:**
- New TypeScript projects with no native addon requirements
- CLI tools and internal scripts
- Standalone APIs using Prisma, Drizzle, or pg
- Monorepo package management
- CI test runner replacement

**Use Bun as the package manager, Node.js as the runtime:**
- Existing Next.js apps you want to migrate gradually
- Projects where you have not audited the full dependency tree yet
- Teams that want the install speed win without the runtime risk

**Stay on Node.js for now:**
- Projects with hard native addon dependencies (canvas, argon2 without alternatives)
- Production servers where operational stability is the top priority
- Teams without bandwidth to debug compatibility surprises

For the performance side of this decision startup time, HTTP throughput, real-world benchmarks the [Bun vs Node.js comparison](/blog/bun-vs-nodejs-is-it-time-to-switch-in-2026/) has the numbers. This article is the compatibility map; that one is the performance case. Read both before you decide.

For the head-to-head performance and migration view, read [Bun vs Node.js](/blog/bun-vs-nodejs-is-it-time-to-switch-in-2026/). If you are choosing a web framework for the runtime, see [Hono.js vs Express](/blog/honojs-vs-express-2026/). For a full-stack React framework that is not Next.js, see [TanStack Start vs Next.js](/blog/tanstack-start-vs-nextjs-2026/).

## Frequently Asked

**Is Bun production ready?** For new TypeScript projects, CLI tools, standalone APIs and package management, yes. For apps that depend on native addons or Node-specific internals, test first or use Bun only as the package manager.

**Does Next.js work with Bun?** You can use Bun as the package manager for Next.js with little risk. Running Next.js on the Bun runtime depends on your dependencies, so audit native packages first.

**Which npm packages break on Bun?** Historically packages with native addons, such as `canvas` and some password hashing libraries. Check current status, because built-in replacements like `Bun.password` exist.

**Can I use Bun only as a package manager?** Yes. `bun install` works alongside Node.js as the runtime and is a low-risk first step.
