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), not philosophy — just the practical 2026 state of what works, what breaks, and what the failure mode looks like when it does break.
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:fsandnode:fs/promises— full compatibility, Bun’s file I/O is actually fasternode:path,node:url,node:os— completenode:httpandnode:https— implemented and compatible with Express, Fastify, and most HTTP frameworksnode:crypto— mostly complete; some edge cases remain around specific cipher suites and legacy methodsnode:stream— largely implemented; occasional edge cases with transform streams in unusual configurationsnode:buffer— full compatibilitynode:process— complete, includingprocess.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. Usebcryptjs(pure JavaScript drop-in) or Bun’s built-inBun.passwordAPI insteadcanvas— native addon, broken on Bun. No clean workaround if you need full canvas supportbetter-sqlite3— native addon, but Bun has a built-in SQLite API (bun:sqlite) that is faster and requires no native bindings at allsharp— 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:
// 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:
# 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 — Bun will flag them.
Specific 2026 status for commonly used packages
| 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.
# 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 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.
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.
# 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.
curl -fsSL https://bun.sh/install | bash
# or: npm install -g bun
Step 2: Run bun install and read the output
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
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
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
# 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 has the numbers. This article is the compatibility map; that one is the performance case. Read both before you decide.