The short answer: on a bare hello-world benchmark, Bun handles roughly four times more requests per second than Node.js — but once you add a real Postgres query and serialization, that gap collapses to about 3%, because database I/O dominates total latency, not the JavaScript runtime. Which one you pick in 2026 depends far more on your app's age and workload than on a benchmark headline.
Raw HTTP throughput: why Bun looks 4x faster
On synthetic benchmarks, the gap is dramatic. On a simple hello-world HTTP server, Bun sustains roughly 52,000 requests per second, while Node.js plateaus around 13,000 requests per second (PkgPulse's 2026 runtime comparison). That's roughly a 4x gap, and it's real — Bun's JavaScriptCore engine and a leaner HTTP server implementation both contribute.
But that number represents no production system. A real API endpoint parses JSON, calls an ORM, hits a database, and serializes a response. The next section shows what actually happens there.
Why that gap collapses once a real database shows up
Here's the article's core, contrarian data point: repeat the same benchmark with a Postgres query and real serialization, and Bun's 4x advantage nearly evaporates. Strapi's performance comparison guide and PkgPulse's data point the same direction — on a realistic, Postgres-backed endpoint, Bun handles roughly 12,400 requests per second versus Node.js's roughly 12,000, a difference of only about 3%.
The reason is straightforward: database I/O dominates total latency far more than the JavaScript runtime does. While a query round-trips over the network, waits in a connection pool, or blocks on disk I/O, it barely matters whose event loop is driving the request. There's still a real, secondary difference in p99 latency: under a sustained ~10,000 req/s load against Postgres, Node.js shows ~48ms p99 versus Bun's ~31ms — DB I/O dominates, but differences in event-loop and I/O implementation still leave a measurable trace.
The table below puts both scenarios side by side:
Scenario | Bun | Node.js | Gap |
|---|---|---|---|
Hello-world HTTP (req/s) | ~52,000 | ~13,000 | ~4x |
Postgres-backed endpoint (req/s) | ~12,400 | ~12,000 | ~3% |
p99 latency (10K req/s, Postgres) | ~31ms | ~48ms | ~35% |
Bare hello-world cold start | ~9ms | ~41ms | ~4.5x |
Install (1,847 dependencies) | ~47s | ~28min | ~35x |
If you're running an ORM — Drizzle or Prisma, for instance — the runtime's contribution to total response time stays much smaller than query planning and index design. The same logic applies to architectures that just use Postgres for everything: optimizing the database layer almost always pays off more than swapping runtimes.
Cold starts, and why they matter for serverless
Cold start is the time a runtime takes to spin up before it can serve a request's first millisecond, and it shows up directly in user-facing latency on serverless. On a bare hello-world HTTP server, Bun 1.2 starts in roughly 9ms, versus roughly 41ms for Node.js 22. Real applications push both numbers higher depending on how many modules load and how large the bundle is — treat these figures as a floor, not a guarantee.
Don't conflate this with Lambda-style serverless cold starts — that's a different, larger-magnitude metric. Tech Insider's 2026 comparison puts a Bun AWS Lambda cold start at roughly 290ms versus roughly 940ms for Node.js; container boot, runtime load, and handler init all stack on top of each other, pushing the numbers well above the bare-server test. Our guide to edge functions and rendering strategies covers when that difference actually reaches the user. If you're weighing a single runtime across a platform like Vercel Services running multiple frameworks in one project, the cold-start gap compounds fastest on low-traffic functions.
Install speed: up to 35x faster than npm
Bun's install speed is real, but it's also the easiest number in this comparison to overstate. The most-cited figure — up to 35x faster than npm — comes from one large monorepo with 1,847 dependencies: Bun finishes the install in 47 seconds, npm takes roughly 28 minutes (PkgPulse). That's a ceiling seen on large dependency trees, not a universal multiplier.
On a smaller, typical project, the gap narrows to a 10–30x range — still dramatic, but don't plan your CI budget around "35x, always." Install speed is felt most in CI/CD duration, in large monorepos, and in day-to-day developer experience.
Native TypeScript, a built-in test runner, and the remaining ecosystem gaps
Bun runs .ts files directly with no separate compile step; Node.js still needs ts-node, tsx, or a build step to do the same job. TypeScript 7's Go-native compiler speeds up type checking, but that's a separate concern — Bun's advantage is skipping the compile step at runtime entirely.
Bun's built-in test runner (bun test) comes from the same philosophy: you write and run Jest-like tests with no extra dependency to install. Node.js only recently got an experimental built-in test runner of its own; it still trails Bun on maturity and ecosystem support.
Two minimal HTTP servers side by side:
// Bun — native, zero extra dependencies
Bun.serve({
port: 3000,
fetch(req) {
return new Response("hello");
},
});
// Node.js — built-in http module
import { createServer } from "node:http";
createServer((req, res) => {
res.end("hello");
}).listen(3000);The flip side is ecosystem maturity. Bun's compatibility with Node-API native addons and npm packages that lean on Node-specific internals improves with every release, but edge cases remain. Migrating a mature Node app with heavy native dependencies — image processing, crypto, database drivers — isn't as simple as "install the package and run it"; some packages break silently or fail to build at all.
The greenfield-vs-migrate decision rule
My clearly opinionated take: migrating a mature Node.js app to Bun purely to chase "maybe better than a 3% gap" is a risk that outweighs the reward for most teams. The real win isn't in DB-heavy production traffic — it's in install speed, native TypeScript, and developer experience.
A simple decision rule:
- Starting a greenfield service or API, especially serverless- or edge-heavy, Bun should be the default: cold start, install speed, and native TypeScript are all a direct win.
- Running a mature, DB-bound Node app with heavy native dependencies, the migration risk outweighs the production performance gain — try Bun only for local development, CI installs, and running tests, and you'll capture most of the benefit without touching the production runtime.
- Somewhere in between (mid-sized app, few native dependencies, traffic already DB-bound), measure your own 3% first with a realistic load test in staging — trust your own numbers over a generalized benchmark.
Other runtime and framework comparisons in the Web Development category can help when you're weighing this kind of decision.
Frequently Asked Questions
Is Bun production-ready in 2026?
Yes. Bun 1.2 and later are considered production-ready for greenfield APIs and serverless functions. The risk isn't the runtime itself — it's migrating an existing Node app with heavy native dependencies.
Will Bun completely replace Node.js?
Not in the near term. Node.js still has far broader ecosystem maturity, native addon support, and enterprise adoption. Bun is gaining ground, especially on new projects and developer experience, but fully replacing Node.js is a years-long process, if it happens at all.
What's the biggest risk when migrating to Bun?
Packages that depend on Node-API native addons or Node-specific internal behavior. These can break silently or fail to build on Bun, so audit your dependency tree for this before migrating.
Has Node's built-in test runner caught up to bun test?
Not quite. Node's built-in test runner is still experimental with limited ecosystem support; bun test offers a more mature API and faster run times.



