← Back to contents

Bun Never Promised to Replace Node.js 100% — Is That Good or Bad?

nodejs bun runtime research

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%)

ModuleTest Suite Pass Rate
node:events100%
node:os100%
node:path100%
node:zlib98%
node:http295.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%)

ModuleTest Suite Pass RateNotes
node:fs92%Missing fs.openAsBlob in some versions
node:streams82%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 install instead of bun install, or migrate to bun:sqlite directly.
  • 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.

Critical Limitations in Partial Modules

node:cluster (documentation)

node:child_process (Issue #6743)

  • Cannot send socket handles via IPC—the sendHandle argument is undefined
  • 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.allowHTTP1 and options.enableConnectProtocol

node:crypto — The Elephant in the Room

Crypto functions in Bun are significantly slower than in Node.js. Multiple issues document the problem:

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

MetricResult
Does it work?✅ Yes
Performance3x faster than Node.js
Memory~2x more RAM usage

Fastify

MetricResult
Does it work?✅ Yes, but…
PerformanceSlower than Node.js in some benchmarks
RecommendationUse 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.

FeatureDoes it work?Details
Decorators✅ YesSince Bun 1.0.3
Core features✅ YesOfficial issue closed as completed
TypeORM integration⚠️ Variablerequire('module').globalPaths caused issues (fixed in canary builds)
Production under load⚠️ Mixed reportsCrashes 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

FeatureDoes it work?Details
Everything✅ YesDesigned 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”.

UseDoes it work?Details
Package manager✅ Yesbun install, bun run build work perfectly
Runtime (development)⚠️ VariableInconsistent hot reload reported
Runtime (production)⚠️ With issuesMeta tags in <body> on refresh (Next 15.4+)
Native Bun APIs⚠️ Limitedimport { 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

SetupDoes it work?Details
Direct⚠️ LimitedRequires special configuration
With @socket.io/bun-engine✅ YesNative 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

MetricResult
Does it work?⚠️ Partial
Performance boostOnly ~20% (bottleneck in IORedis)
Bun.redisNot supported yet

Auth and Payments

bcrypt (native)

FeatureDoes it work?Details
Original❌ NoNative addon incompatible, segfaults reported
Alternatives✅ YesUse 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 VersionDoes it work?Details
1.1.4✅ YesWorks correctly
1.1.5❌ NoRegression that broke Stripe
1.1.6+⚠️ VariableVerify with your version

Regressions are a real problem. A Bun upgrade can break critical integrations.


Cloud and AWS

AWS SDK v3

FeatureDoes it work?Details
Basic services✅ YesS3, DynamoDB, etc. work
S3 with SDK✅ Yes5x faster than Node.js since Bun 1.1.25
Native Bun.s3✅ Recommended5x faster than @aws-sdk/client-s3

If you only need S3, consider using Bun.s3 directly instead of the SDK.


ORMs and Databases

Prisma

OperationDoes it work?Details
Queries✅ YesThe client works
prisma generate⚠️ Requires Node.jsCLI hangs if Node isn’t installed
prisma migrate⚠️ Requires Node.jsSame issue
Docker⚠️ ProblematicQuery 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

FeatureDoes it work?Details
Basic decorators✅ YesSince Bun 1.0.3 with emitDecoratorMetadata
Edge cases⚠️ ProblematicReports of Cannot find module with internal metadata

Drizzle ORM

FeatureDoes it work?Details
Everything✅ YesNative 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

FeatureDoes it work?Details
Basic connection✅ YesMongoDB driver works
All features✅ YesOfficial Bun documentation confirms compatibility

Browser Automation

Puppeteer

PlatformDoes it work?Details
Linux✅ YesWorks since Bun 1.1
macOS✅ YesWorks since Bun 1.1
Windows⚠️ UnstableUnpredictable behavior, random exits

Playwright

PlatformDoes it work?Details
Linux✅ YesWorks since Bun 1.1
macOS✅ YesWorks since Bun 1.1
Windows⚠️ PartialNamed 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

OperationDoes it work?Details
Runtime✅ YesWorks once installed
bun install❌ NoPostinstall scripts not compatible
Segfaults⚠️ ReportedIn Docker and concurrent operations

Workaround: Install with npm install sharp and then use bun to run.

node-canvas

FeatureDoes it work?Details
Original❌ NoUses node-gyp which requires native compilation
@napi-rs/canvas⚠️ With issuesmusl/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

FeatureDoes it work?Details
Text/commands✅ YesWorks 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 PackageBun-friendly Alternative
bcryptbcryptjs or Bun.password
node-canvas@napi-rs/canvas (with limitations)
better-sqlite3native 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:

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:

  1. The goal is 90% compatibility, not 100%
  2. New features (S3, Redis, Postgres) compete for resources with compatibility
  3. Windows has more problems than Linux/macOS
  4. Regressions between versions are real—don’t assume upgrades are safe
  5. 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.