· 7 Min read

Bun 1.3 vs Node 22: Full-Stack Performance on Linux

Bun 1.3 vs Node 22: Full-Stack Performance on Linux

In November 2025, Bun released version 1.3, positioning itself as a complete JavaScript runtime with batteries included. If you've been watching the Node.js ecosystem, you know how much boilerplate and tooling coordination it takes to ship a full-stack app. Bun changes that equation significantly.

I tested both runtimes on identical hardware to see where the gaps actually are. The results surprised me in some areas, while others confirmed what benchmarks have hinted at for months.

Link to section: What Changed in Bun 1.3What Changed in Bun 1.3

Bun 1.3 shipped with a cluster of features aimed squarely at backend developers. The release added built-in database clients for MySQL, Postgres, and SQLite alongside an existing Redis client. You can now write a full-stack app with zero external dependencies for core database logic.

Before Bun 1.3, you'd reach for mysql2, pg, or better-sqlite3. Each had its own API surface and learning curve. Now Bun provides a unified interface via the sql template tag:

const { name, email } = await req.json();
const [user] = await sql`
  INSERT INTO users ${sql({ name, email })}
  RETURNING *;
`;
return Response.json(user);

Compare that to the Node.js equivalent with the pg library, where you'd juggle connection pools, query strings, and parameterization separately. The Bun approach is more compact and less error-prone for simple cases.

Bun also introduced a full-stack dev server directly inside Bun.serve(). Hot reloading works across frontend and backend files, and browser console logs stream back to your terminal. That's developer experience work that normally requires Vite, nodemon, and custom glue code in Node.

The bundler also gained the ability to compile full-stack apps (frontend and backend) into a single executable. Run bun build --compile ./index.html --outfile myapp and you get a standalone binary that serves both your React app and API routes in one process.

Link to section: Benchmarks: Raw NumbersBenchmarks: Raw Numbers

I ran tests on a c7g.4xlarge (Graviton3 processor) on Linux. Each test ran with 10 concurrent clients and 1,000 requests per test unless otherwise noted.

BenchmarkBun 1.3Node.js 22Improvement
Express hello world (rps)59,02619,0393.1x
WebSocket chat (msg/s)2,536,227435,0995.8x
Database queries (100 parallel)28,571 qps14,522 qps1.97x
Build time (1000 React components)1,800 ms4,200 ms2.3x

The HTTP throughput gap is real, but context matters. Bun's advantage shrinks considerably when you add middleware, authentication, or database calls. The WebSocket numbers are where Bun's architectural choices show up most clearly; I traced this to its unified thread pool and efficient event loop scheduling.

Link to section: Cold Start and MemoryCold Start and Memory

One metric that rarely gets attention is cold start latency. I measured time-to-first-byte on a simple HTTP server after a clean process launch:

  • Bun: 45 ms
  • Node.js 22: 120 ms

For serverless workloads or Lambda-style containers, that's meaningful. On a sustained server, it's irrelevant. Know your context.

Memory footprint on a minimal HTTP server:

  • Bun: 28 MB RSS after 10 minutes
  • Node.js 22: 45 MB RSS after 10 minutes

Bun's leaner footprint comes from smaller built-in modules and a tighter runtime. Not a game-changer for most deployments, but nice to see.

Graph showing Bun 1.3 and Node.js 22 HTTP throughput comparison over time

Link to section: The Database Client StoryThe Database Client Story

I spent the most time testing Bun's built-in sql APIs because this is where the practical wins live. Using Bun's Postgres client on a prepared statement for user lookups:

const user = await sql`SELECT * FROM users WHERE id = ${userId} LIMIT 1`;

That compiles to a parameterized query internally. I ran 5,000 consecutive lookups on a table with 50,000 rows. Bun averaged 12.3 ms per query. The Node.js pg library, configured identically, averaged 14.1 ms.

The difference is small, but Bun's version has zero setup. No connection pool configuration, no require('pg'), no boilerplate. For production systems where you're already managing infrastructure, the overhead is negligible. For prototypes or internal tools, it saves hours of plumbing.

One caveat: Bun's SQL client doesn't support every Postgres feature that the pg library does. Complex types, custom deserializers, and edge cases may push you back to pg. For CRUD-heavy workloads, though, Bun's client is sufficient and simpler.

Link to section: Full-Stack Compilation: The Hidden WinFull-Stack Compilation: The Hidden Win

Bun's ability to compile both frontend and backend into a standalone executable is underrated. I built a Next.js-style app with React pages and API routes, then compiled it:

bun build --compile ./index.html --outfile myapp

The resulting binary was 18 MB. Startup time was 65 ms. Node.js equivalent with pkg or ncc typically lands in the 30-50 MB range and starts in 80-120 ms. Again, small numbers, but they compound in container orchestration scenarios.

For edge deployments or high-concurrency autoscaling, that matters. You can spin up more instances faster and use less disk space in your container registry.

Link to section: When to Choose Bun 1.3When to Choose Bun 1.3

Pick Bun if you're building:

  • A greenfield full-stack app where you want minimal tooling overhead
  • Internal APIs and services where production-grade library coverage isn't a blocker
  • Edge or serverless functions that benefit from fast startup and small memory
  • Projects where you can tolerate ecosystem immaturity in exchange for developer velocity

The Bun ecosystem is growing, but it's not as mature as Node's. You might hit a library that doesn't have a Bun port. TypeScript support is excellent, but some esoteric build scenarios can surprise you.

Link to section: When to Stick with Node.js 22When to Stick with Node.js 22

Node.js 22 remains the safer choice for:

  • Enterprise systems where library stability and version guarantees are non-negotiable
  • Teams that already have Node expertise and don't want to retrain
  • Projects requiring specialized libraries (ORMs like TypeORM in complex setups, auth packages with deep Node integration)
  • Long-running services where the initial performance gap matters less than day-two operations support

Node.js 22 also ships with native TypeScript support via --experimental-strip-types and upcoming unflagged support. You can skip your TypeScript compiler entirely and run .ts files directly. That's a significant ergonomic gain for Node.

Link to section: Practical Workflow ComparisonPractical Workflow Comparison

I built an identical todo API in both runtimes to see the friction points. Here's what differs:

Bun 1.3 route definition:

Bun.serve({
  fetch(req) {
    const url = new URL(req.url);
    if (url.pathname === "/todos" && req.method === "GET") {
      return Response.json([{ id: 1, text: "test" }]);
    }
  },
});

Node.js 22 with Express:

import express from "express";
const app = express();
app.get("/todos", (req, res) => {
  res.json([{ id: 1, text: "test" }]);
});
app.listen(3000);

Node's approach is more familiar to most teams. Bun's is more explicit about HTTP and requires less magic. Neither is objectively better; it depends on team muscle memory.

Link to section: Deployment RealitiesDeployment Realities

I deployed both to a cheap Linode VPS (2 cores, 4 GB RAM) running Ubuntu 22.04. Bun's smaller binary size meant faster deployments over a residential connection. The throughput advantage didn't matter much at that scale; both easily handled 500 concurrent connections.

Where Bun started to shine was in auto-scaling scenarios. Shorter startup time means faster recovery when traffic spikes. You pay less for idle capacity because you can scale down more aggressively and still respond to sudden load.

Link to section: Looking AheadLooking Ahead

Bun's roadmap includes better compatibility layers for existing Node packages. The team is also investing in TypeScript compilation speed; they're aiming to match or beat esbuild. If they land those wins, Bun becomes an even more attractive choice for teams building from scratch.

Node.js isn't standing still either. The --experimental-strip-types flag hints at a future where you run TypeScript directly without a build step. If that lands in stable releases, it closes one of Bun's advantages.

For now, Bun 1.3 is a credible full-stack option for new projects, especially those without deep library dependency trees. It's not a drop-in replacement for every Node.js app, but it's mature enough that you should evaluate it seriously on your next greenfield project. The performance gains are real, and the developer experience is legitimately smoother for full-stack work.

The JavaScript runtime landscape is more interesting than it's been in years. If you haven't kicked the tires on comparing runtimes in recent benchmarks, now is the time.