Bun Never Promised to Replace Node.js 100% — Is That Good or Bad?
Bun Never Promised to Replace Node.js 100% — Is That Good or Bad?
TL;DR: Bun aims for 90% Node.js compatibility, not 100%. It works well for simple APIs with Express/Hono, CLIs, and new projects. Friction points: Next.js works as a package manager but the runtime has edge cases in production; Prisma requires Node.js installed for the CLI; Playwright/Puppeteer problematic on Windows; crypto 10-14x slower. Audit your stack before migrating—regressions between versions are real.
If you’ve been following the JavaScript ecosystem in recent years, you’ve probably heard that Bun is “the Node.js replacement.” Faster, more modern, all-in-one. The promise sounds irresistible: swap node for bun and your application flies.
But there’s a problem. That promise never existed exactly like that.
In this article, we’ll investigate what Bun actually promised, what the current compatibility status is, and—most importantly—whether you can trust it for your specific stack. Spoiler: the answer depends heavily on what you’re building.
The Promise That Never Existed
Since its launch in 2022, Bun positioned itself as a “drop-in replacement” for Node.js. Jarred Sumner, its creator, described it this way in an interview with JavaScript Jabber:
“It’s designed as a drop-in replacement for Node.js. We’re not at 100% yet. We’re basically reimplementing all of Node.js’s APIs from scratch. It’s a mountain of work. But we’ve made a lot of progress.”
The key word here is “yet”. Bun never promised total compatibility from day one—it promised to work toward it. But here’s the detail many miss: according to Bun’s official roadmap, the goal is 90% compatibility, not 100%.
Why 90%? Because some Node.js APIs simply don’t make sense in Bun’s architecture. node:v8 is the obvious example—Bun uses JavaScriptCore (Safari’s engine), not V8.
The Silent Shift in Focus
If you observe Bun’s evolution, you’ll notice something interesting. While the community expected each release to close more Node.js compatibility gaps, Bun started building completely new things:
- Bun.sql: Native PostgreSQL, MySQL, and SQLite client (introduced in v1.2, expanded in v1.3)
- Bun.s3: Native S3 client (5x faster than
@aws-sdk/client-s3) - Bun.redis: Native Redis/Valkey client (introduced in v1.2.9, highlighted in v1.3)
- HTML Imports: A feature Node.js doesn’t have (experimental in v1.1.44, official in v1.2)
- Built-in hot reloading: No need for nodemon (improved in v1.3)
This isn’t necessarily bad. But it does reveal an uncomfortable truth: Bun isn’t trying to be “Node.js but faster”—it’s building something different.
The Anthropic Factor
In December 2025, Anthropic acquired Bun. Jarred Sumner explained that Bun now powers Claude Code, Claude Agent SDK, and other AI products.
The post-acquisition promises:
- Bun remains open-source and MIT
- The same team continues development
- The roadmap maintains focus on Node.js compatibility
But now there’s a stakeholder with specific interests. Anthropic needs speed, stability, and yes—Node.js compatibility. That could be good for everyone. Or it could mean priorities align more with AI product needs than with the general ecosystem.
The Real State of Compatibility
Let’s leave the headlines and look at the numbers. Bun runs Node.js’s test suite before every release. According to the official compatibility documentation, these are the results by module:
High Compatibility Modules (>95%)
| Module | Test Suite Pass Rate |
|---|---|
node:events | 100% |
node:os | 100% |
node:path | 100% |
node:zlib | 98% |
node:http2 | 95.25% (gRPC test suite) |
node:dns | >90% |
node:dgram | >90% |
Note: gRPC (Google Remote Procedure Call) is a service-to-service communication framework that heavily depends on HTTP/2. Bun uses the gRPC test suite as a benchmark to validate its node:http2 implementation because it represents real-world and demanding protocol use cases.
Medium Compatibility Modules (80-95%)
| Module | Test Suite Pass Rate | Notes |
|---|---|---|
node:fs | 92% | Missing fs.openAsBlob in some versions |
node:streams | 82% | Different edge-case behavior |
node:http | ~85% | Request body is buffered instead of streamed |
Note: fs.openAsBlob allows reading files directly as Blob objects, useful for uploading files to web APIs or processing them with Web Streams without fully loading them into memory.
What’s Completely Missing
These modules are not implemented, and even if you don’t use them directly, some dependency in your project probably does:
-
node:inspector: Not implemented. Bun has its own debugger with WebKit Inspector Protocol (--inspect), but the Node.js API isn’t available.- Affected packages: Sentry (error monitoring), elastic-apm-node (Elastic APM), and other monitoring tools that depend on this module for profiling.
-
node:repl: Not implemented. Bun has its own basic REPL (bun repl), but doesn’t expose Node.js’s programmatic API.- Affected packages: Vorpal (interactive CLI framework), and tools that create custom REPL interfaces.
-
node:sqlite: Ironic given that Bun has native SQLite (bun:sqlite), but the Node.js API isn’t implemented.- Affected packages: better-sqlite3 has ABI incompatibility issues—the module was compiled against a different Node.js version. Workaround: install with
npm installinstead ofbun install, or migrate tobun:sqlitedirectly.
- Affected packages: better-sqlite3 has ABI incompatibility issues—the module was compiled against a different Node.js version. Workaround: install with
-
node:trace_events: Not implemented. Only an empty stub exists—functions that exist so code doesn’t fail when importing the module, but they don’t do anything. This prevents “module not found” errors but tracing simply doesn’t work.- Affected packages: dd-trace (Datadog APM) and other distributed tracing tools. Workaround: use OpenTelemetry as an alternative to send traces to Datadog.
Critical Limitations in Partial Modules
node:cluster (documentation)
- Load-balancing only works on Linux via
SO_REUSEPORT - On macOS and Windows, connections aren’t distributed correctly between workers—this is an operating system limitation, not Bun’s
node:child_process (Issue #6743)
- Cannot send socket handles via IPC—the
sendHandleargument isundefined - This breaks common multi-process architecture patterns where the parent distributes connections to workers
node:http2 (documentation)
- Client and server implemented (95.25% of gRPC test suite passes)
- Missing
http2stream.pushStream(HTTP/2 Server Push) - Missing ALTSVC extension support
- Missing
options.allowHTTP1andoptions.enableConnectProtocol
node:crypto — The Elephant in the Room
Crypto functions in Bun are significantly slower than in Node.js. Multiple issues document the problem:
- AES-128-GCM 10x slower: Benchmark of 1000 encryption operations
- PBKDF2 13x slower: 237ms in Node vs 3189ms in Bun (600,000 rounds)
- RSA 14x slower: privateEncrypt/publicDecrypt takes ~1s in Node vs ~14.5s in Bun
If your application does intensive hashing, encryption, or any heavy cryptographic work—don’t use Bun.
The Litmus Test: Does Your Stack Work?
Test suite numbers are fine, but what really matters is: do the packages I use every day work?
I investigated 14 popular packages across different industries. Here’s the verdict:
Web Frameworks
Express
| Metric | Result |
|---|---|
| Does it work? | ✅ Yes |
| Performance | 3x faster than Node.js |
| Memory | ~2x more RAM usage |
Fastify
| Metric | Result |
|---|---|
| Does it work? | ✅ Yes, but… |
| Performance | Slower than Node.js in some benchmarks |
| Recommendation | Use Bun.serve() directly (3-4x faster) |
Jarred Sumner said it directly:
“Fastify isn’t fast on Bun. Bun.serve() is 3x-4x faster.”
NestJS — Officially Supported, But With Nuances
Jarred Sumner opened issue #1641 to track NestJS compatibility. That issue is closed as COMPLETED, meaning Bun considers it has the necessary compatibility to run NestJS.
| Feature | Does it work? | Details |
|---|---|---|
| Decorators | ✅ Yes | Since Bun 1.0.3 |
| Core features | ✅ Yes | Official issue closed as completed |
| TypeORM integration | ⚠️ Variable | require('module').globalPaths caused issues (fixed in canary builds) |
| Production under load | ⚠️ Mixed reports | Crashes reported in some cases |
Important context: The NestJS team has not declared official support for Bun. This means if you find bugs, neither team may prioritize them. However, the community has reported success in production projects.
Hono
| Feature | Does it work? | Details |
|---|---|---|
| Everything | ✅ Yes | Designed for Bun |
Next.js — The Most Complex Case
The Next.js situation has changed significantly. In January 2025, Bun removed the incompatibility warning that said “Next.js App Router is incompatible with Bun”.
| Use | Does it work? | Details |
|---|---|---|
| Package manager | ✅ Yes | bun install, bun run build work perfectly |
| Runtime (development) | ⚠️ Variable | Inconsistent hot reload reported |
| Runtime (production) | ⚠️ With issues | Meta tags in <body> on refresh (Next 15.4+) |
| Native Bun APIs | ⚠️ Limited | import { S3Client } from "bun" doesn’t work with Turbopack (fix merged in PR #77616) |
| Streaming responses | ⚠️ Problems | ”ReadableStream is locked” in Next 16 + Bun 1.3.2 |
The reality: Bun as a package manager for Next.js works great. Bun as a runtime still has problematic edge cases. The official Bun documentation now includes App Router guides, but in production many developers report that Node.js remains more stable.
Recommendation: Use bun install and bun run build, but consider node for the production server if you encounter issues.
Real-time and Queues
Socket.IO
| Setup | Does it work? | Details |
|---|---|---|
| Direct | ⚠️ Limited | Requires special configuration |
With @socket.io/bun-engine | ✅ Yes | Native Bun engine developed by the Socket.IO team |
Note: Unless you need polling fallback, consider using Bun’s native WebSockets directly—they’re significantly faster.
BullMQ
| Metric | Result |
|---|---|
| Does it work? | ⚠️ Partial |
| Performance boost | Only ~20% (bottleneck in IORedis) |
| Bun.redis | Not supported yet |
Auth and Payments
bcrypt (native)
| Feature | Does it work? | Details |
|---|---|---|
| Original | ❌ No | Native addon incompatible, segfaults reported |
| Alternatives | ✅ Yes | Use Bun.password (native) or bcryptjs |
Bun has built-in password hashing:
const hash = await Bun.password.hash("my-password");
const valid = await Bun.password.verify("my-password", hash);
Stripe
| Bun Version | Does it work? | Details |
|---|---|---|
| 1.1.4 | ✅ Yes | Works correctly |
| 1.1.5 | ❌ No | Regression that broke Stripe |
| 1.1.6+ | ⚠️ Variable | Verify with your version |
Regressions are a real problem. A Bun upgrade can break critical integrations.
Cloud and AWS
AWS SDK v3
| Feature | Does it work? | Details |
|---|---|---|
| Basic services | ✅ Yes | S3, DynamoDB, etc. work |
| S3 with SDK | ✅ Yes | 5x faster than Node.js since Bun 1.1.25 |
| Native Bun.s3 | ✅ Recommended | 5x faster than @aws-sdk/client-s3 |
If you only need S3, consider using Bun.s3 directly instead of the SDK.
ORMs and Databases
Prisma
| Operation | Does it work? | Details |
|---|---|---|
| Queries | ✅ Yes | The client works |
prisma generate | ⚠️ Requires Node.js | CLI hangs if Node isn’t installed |
prisma migrate | ⚠️ Requires Node.js | Same issue |
| Docker | ⚠️ Problematic | Query Engine errors due to incompatible architectures |
The Prisma team is working on a new “Rust-free” generator that improves the situation, but today you need Node.js installed even if you run your app with Bun.
TypeORM
| Feature | Does it work? | Details |
|---|---|---|
| Basic decorators | ✅ Yes | Since Bun 1.0.3 with emitDecoratorMetadata |
| Edge cases | ⚠️ Problematic | Reports of Cannot find module with internal metadata |
Drizzle ORM
| Feature | Does it work? | Details |
|---|---|---|
| Everything | ✅ Yes | Native support, integration with Bun.sql |
Verdict: Use Drizzle if starting a new project. If you already have Prisma, keep Node.js in your toolchain.
Mongoose
| Feature | Does it work? | Details |
|---|---|---|
| Basic connection | ✅ Yes | MongoDB driver works |
| All features | ✅ Yes | Official Bun documentation confirms compatibility |
Browser Automation
Puppeteer
| Platform | Does it work? | Details |
|---|---|---|
| Linux | ✅ Yes | Works since Bun 1.1 |
| macOS | ✅ Yes | Works since Bun 1.1 |
| Windows | ⚠️ Unstable | Unpredictable behavior, random exits |
Playwright
| Platform | Does it work? | Details |
|---|---|---|
| Linux | ✅ Yes | Works since Bun 1.1 |
| macOS | ✅ Yes | Works since Bun 1.1 |
| Windows | ⚠️ Partial | Named pipes implemented in v1.1.29+, but there are still timeout reports |
Verdict: If you develop on Windows or your CI runs on Windows, stick with Node.js.
Image Processing
Sharp
| Operation | Does it work? | Details |
|---|---|---|
| Runtime | ✅ Yes | Works once installed |
bun install | ❌ No | Postinstall scripts not compatible |
| Segfaults | ⚠️ Reported | In Docker and concurrent operations |
Workaround: Install with npm install sharp and then use bun to run.
node-canvas
| Feature | Does it work? | Details |
|---|---|---|
| Original | ❌ No | Uses node-gyp which requires native compilation |
| @napi-rs/canvas | ⚠️ With issues | musl/glibc problems, crashes in executables |
Note: @napi-rs/canvas doesn’t require node-gyp, but has its own issues with Bun. Verify compatibility with your version.
Bots and Gaming
Discord.js
| Feature | Does it work? | Details |
|---|---|---|
| Text/commands | ✅ Yes | Works correctly |
| Voice channels | ❌ No | @discordjs/voice fails because @discordjs/opus (native) doesn’t load correctly and there are connection issues |
Verdict: If you only need a text bot, go ahead. If you need audio, stick with Node.js.
The Elephant in the Room
Looking at the list above, an obvious question arises: Why is Bun building native S3, Postgres, and Redis clients before completing Node.js compatibility?
The official answer from the Bun team in their Bun.sql documentation:
“We believe it’s simpler for developers to have a database driver built into Bun. The time you spend choosing libraries is time you could be building your app.”
And there’s a technical reason:
“We take advantage of some JavaScriptCore engine internals to make object creation faster in ways that would be difficult to implement in a library.”
In other words: these native features are significantly faster than their npm equivalents precisely because they’re integrated into the runtime.
But this creates tension. Every engineering hour dedicated to Bun.redis is an hour not dedicated to fixing node:cluster on macOS. It’s a legitimate product decision, but you need to understand the implications:
Bun is betting that you prefer new, fast features over perfect compatibility with the existing ecosystem.
If your priority is migrating an existing Node.js project without surprises, that bet may not align with your needs.
Ghosts in Production
Beyond API compatibility, there are stability issues you need to know about.
Segfaults Under Load
In December 2024, a developer reported random crashes in production:
“Random segfaults happening dozens of times a day, roughly correlating with periods of higher load.”
The problem disappeared when rolling back to Bun 1.1.33 from 1.1.38. Docker automatically restarted the container, but the problem persisted until the rollback.
Regressions That Break Packages
The Stripe case is illustrative. Bun version 1.1.5 broke the Stripe integration. The solution was to downgrade to 1.1.4.
This means you can’t assume a Bun upgrade is safe. You need a CI pipeline that tests your critical integrations before updating.
The Windows Problem
Multiple packages (Playwright, Puppeteer, and others) have Windows-specific issues that don’t exist on Linux or macOS. If your team develops on Windows or your CI runs on Windows, you’ll encounter more friction.
Verdict: Should You Make the Switch?
After all this research, here’s my decision framework:
Use Bun if…
- ✅ You’re building CLIs or development tools (single-binary is great for distribution)
- ✅ You’re developing simple APIs with Hono or Elysia (frameworks designed for Bun)
- ✅ Your stack is basic Express without complex native dependencies
- ✅ You need SQLite, Postgres, or S3 and want maximum performance
- ✅ It’s a new project where you can choose Bun-friendly dependencies
- ✅ You develop on Linux or macOS (Windows has more issues)
Don’t use Bun if…
- ❌ You do intensive cryptographic work (10-14x slower than Node.js)
- ❌ Your CI or team develops on Windows (Playwright, Puppeteer, and others have issues)
- ❌ You need perfect compatibility with a large existing Node.js codebase
- ❌ You use native addons like node-canvas, native bcrypt, sharp (without workarounds)
- ❌ You depend on Discord.js with audio
Evaluate Carefully if…
- ⚠️ You use Next.js — works as a package manager, but the runtime has edge cases (streaming, meta tags, hot reload)
- ⚠️ You use NestJS — officially “compatible” but without support from the NestJS team
- ⚠️ You depend on Prisma — the client works but the CLI requires Node.js installed
Pre-Migration Audit Checklist
Before attempting to migrate, answer these questions:
1. Do you use native modules?
Run this command to identify them:
npm ls | grep -E "(native|binding|addon)"
According to Bun’s module documentation, N-API addons should work, but those depending on node-gyp may fail.
N-API (Node-API) is Node.js’s stable interface for creating native C/C++ extensions. Unlike V8’s internal APIs that change between versions, N-API guarantees binary compatibility—an addon compiled for Node 14 works on Node 20 without recompilation. Bun reimplements this API so existing addons work without modifications.
Common alternatives:
| Native Package | Bun-friendly Alternative |
|---|---|
bcrypt | bcryptjs or Bun.password |
node-canvas | @napi-rs/canvas (with limitations) |
better-sqlite3 | native bun:sqlite |
2. Does your project have >50k lines of code?
A developer documented migrating a monorepo with 300+ packages and ~100,000 lines. Their conclusions:
“I ended up removing most references to
Bun.*and ensuring that where I still use the bun global, I import it like this:import Bun from 'bun'. This way everything can run in Node as well.”
The recommendation: maintain dual compatibility until you’re sure everything works.
3. Do you develop or deploy on Windows?
Bun 1.1 added official Windows support, but with limitations:
- Only supports x64, not ARM
- Playwright and Puppeteer have unpredictable behavior
- Some users report segfaults during installation
Consider using WSL or Linux containers for development if your team is on Windows.
4. Do your tests cover critical integrations?
Before migrating, run your test suite with Bun:
bun test
As we saw with the Stripe case, regressions are real. The production migration guide recommends:
“Monitor error rates obsessively for the first 48 hours. If anything breaks, one command reverts the deployment.”
5. Can you rollback quickly?
Bun automatically converts package-lock.json to bun.lock, preserving resolved versions. But keep your original lockfile:
# Save the original lockfile
cp package-lock.json package-lock.json.backup
# Migrate to Bun
bun install
# If something fails, immediate rollback
mv package-lock.json.backup package-lock.json
rm bun.lock
npm install
6. Do your dependencies have postinstall scripts?
Unlike npm, Bun doesn’t execute lifecycle scripts by default for security. Only packages in the top 500 npm packages are in the allowlist.
To see which scripts were blocked:
bun pm untrusted
To trust a specific package:
bun pm trust <package-name>
Or add it to your package.json:
{
"trustedDependencies": ["sharp", "puppeteer", "@prisma/client"]
}
After adding, reinstall:
rm -rf node_modules
rm bun.lock
bun install
Conclusion
Bun is an impressive project with a clear vision: make JavaScript faster and simpler. But that vision is not to be a copy of Node.js.
The question “Can I replace Node.js with Bun?” has an honest answer: it depends on your specific stack. For some projects, Bun is strictly better. For others, it’s a functional downgrade.
The most important things to remember:
- The goal is 90% compatibility, not 100%
- New features (S3, Redis, Postgres) compete for resources with compatibility
- Windows has more problems than Linux/macOS
- Regressions between versions are real—don’t assume upgrades are safe
- Audit your stack before migrating
Bun didn’t promise to replace Node.js 100%. And now you know exactly what that means for your project.