Bun Runtime for Production 2026: Speed Benchmarks, Node.js Migration & Best Practices
Is Bun ready for production in 2026? Comprehensive guide to Bun runtime performance benchmarks vs Node.js, npm/package migration, built-in bundler, test runner, TypeScript support, and real-world production deployment best practices.
Bun Runtime for Production 2026: Speed Benchmarks, Node.js Migration & Best Practices
Bun entered the JavaScript ecosystem with bold claims: faster than Node.js, built-in bundler, native TypeScript, all-in-one toolchain. Two years since its 1.0 release, the question has shifted from βis Bun promising?β to βis Bun ready for production?β
The answer depends on what youβre building β but for a significant range of workloads, the answer is yes.
What Is Bun?
Bun is a JavaScript runtime built on JavaScriptCore (Safariβs engine) rather than V8 (Chromeβs engine, used by Node.js and Deno). It ships as a single binary that replaces:
nodeβ runtimenpm/yarn/pnpmβ package managertsc/ts-nodeβ TypeScript executionwebpack/esbuildβ bundlerjest/vitestβ test runner
The value proposition is: one tool, faster everywhere.
Performance Benchmarks 2026
HTTP Server Throughput
Bunβs HTTP server is consistently faster than Node.js + Express for simple JSON APIs:
Bun.serve HTTP (plain): ~180,000 req/s
Fastify (Node.js): ~85,000 req/s
Express (Node.js): ~52,000 req/s
Tested on: AMD Ryzen 9 5900X, Ubuntu 22.04, single-process, no clustering
For realistic workloads with database queries and middleware, the gap narrows but Bun still leads:
Bun + Hono + DB query: ~28,000 req/s
Fastify + Node.js + DB: ~21,000 req/s
Express + Node.js + DB: ~18,000 req/s
Startup Time
Startup time matters for serverless functions and CLI tools:
// app.ts - simple "hello world" server
const server = Bun.serve({
port: 3000,
fetch(req) {
return new Response("Hello, World!");
},
});
Bun startup: ~5ms
Node.js startup: ~50ms
Deno startup: ~30ms
For Lambda cold starts or CLI tools invoked frequently, this is a meaningful difference.
Package Install Speed
bun install (fresh): ~1.2s (3,847 packages)
pnpm install (fresh): ~8.4s
npm install (fresh): ~24.1s
yarn install (fresh): ~18.7s
bun install (with lockfile): ~0.14s
pnpm install (with lockfile):~2.1s
Bunβs package manager is genuinely 10-20x faster than npm for fresh installs. This alone makes it worth using for CI pipelines.
TypeScript Execution
Bun executes TypeScript directly without a separate compilation step:
# Node.js requires:
npx ts-node app.ts # ~800ms startup
# or build first:
npx tsc && node dist/app.js
# Bun:
bun run app.ts # ~5ms startup
The TypeScript support uses a transpile-only approach (no type checking at runtime), which is fine for execution but means you still need tsc --noEmit for type validation.
Core Bun APIs
HTTP Server
const server = Bun.serve({
port: 3000,
hostname: "0.0.0.0",
async fetch(req: Request): Promise<Response> {
const url = new URL(req.url);
if (url.pathname === "/health") {
return Response.json({ status: "ok", uptime: process.uptime() });
}
if (url.pathname === "/users" && req.method === "GET") {
const users = await db.query("SELECT id, name FROM users LIMIT 100");
return Response.json(users);
}
return new Response("Not Found", { status: 404 });
},
error(error: Error): Response {
console.error(error);
return Response.json({ error: "Internal Server Error" }, { status: 500 });
},
});
console.log(`Listening on ${server.hostname}:${server.port}`);
File I/O
Bun provides high-level file APIs that are simpler than Node.jsβs fs:
// Read entire file
const text = await Bun.file("./data.txt").text();
const json = await Bun.file("./config.json").json();
const buffer = await Bun.file("./image.png").arrayBuffer();
// Write file
await Bun.write("./output.txt", "Hello, World!");
await Bun.write("./data.json", JSON.stringify({ key: "value" }));
// Stream large files
const file = Bun.file("./large-file.csv");
const stream = file.stream();
for await (const chunk of stream) {
processChunk(chunk);
}
SQLite (Built-in)
Bun ships with a built-in SQLite driver β no npm install required:
import { Database } from "bun:sqlite";
const db = new Database("myapp.db");
db.exec(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
const insert = db.prepare("INSERT INTO users (name, email) VALUES ($name, $email)");
const getUser = db.prepare("SELECT * FROM users WHERE id = $id");
const getAll = db.prepare("SELECT * FROM users LIMIT $limit");
// Insert
insert.run({ $name: "Alice", $email: "[email protected]" });
// Query
const user = getUser.get({ $id: 1 });
const users = getAll.all({ $limit: 10 });
For production apps that need a lightweight embedded database (CLI tools, local-first apps, development databases), this is excellent.
WebSocket Server
const server = Bun.serve({
port: 3000,
fetch(req, server) {
if (server.upgrade(req)) {
return; // Upgraded to WebSocket
}
return new Response("Upgrade failed", { status: 500 });
},
websocket: {
message(ws, message) {
ws.send(`Echo: ${message}`);
},
open(ws) {
ws.subscribe("chat-room");
},
close(ws, code, message) {
ws.unsubscribe("chat-room");
},
},
});
// Broadcast to all subscribers
server.publish("chat-room", "Someone joined!");
Bunβs WebSocket implementation uses pub/sub patterns natively β no need for Socket.io.
Package Manager: Replacing npm/pnpm
Basic Commands
# Initialize project
bun init
# Install all dependencies
bun install
# Add package
bun add express
bun add -d typescript @types/node # dev dependency
bun add -g nodemon # global
# Remove package
bun remove express
# Run script from package.json
bun run build
bun run dev
bun start # shorthand for "bun run start"
# Execute any file
bun run ./scripts/seed.ts
# Execute package binaries
bunx create-next-app # equivalent to npx
Workspaces (Monorepo)
// package.json (root)
{
"name": "my-monorepo",
"workspaces": ["packages/*", "apps/*"],
"scripts": {
"build": "bun run --filter='*' build",
"test": "bun run --filter='*' test"
}
}
# Run command in specific workspace
bun run --filter=my-app dev
# Install for all workspaces
bun install
Built-in Test Runner
// math.test.ts
import { expect, test, describe, beforeEach, mock } from "bun:test";
import { add, multiply, divide } from "./math";
describe("Math operations", () => {
test("adds numbers", () => {
expect(add(2, 3)).toBe(5);
expect(add(-1, 1)).toBe(0);
});
test("multiplies numbers", () => {
expect(multiply(3, 4)).toBe(12);
});
test("throws on divide by zero", () => {
expect(() => divide(10, 0)).toThrow("Division by zero");
});
});
// Mock example
test("calls API", async () => {
const mockFetch = mock(() =>
Promise.resolve(new Response(JSON.stringify({ id: 1, name: "Alice" })))
);
globalThis.fetch = mockFetch;
const user = await getUser(1);
expect(mockFetch).toHaveBeenCalledTimes(1);
expect(user.name).toBe("Alice");
});
# Run tests
bun test
# Watch mode
bun test --watch
# Filter tests
bun test --test-name-pattern "adds"
# Coverage
bun test --coverage
The test runner is Jest-compatible for most patterns. Migration from Jest typically requires changing imports from jest to bun:test.
Bundler
Bunβs bundler handles TypeScript, JSX, and modern JavaScript natively:
// build.ts
await Bun.build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
target: "node", // or "browser" or "bun"
format: "esm", // or "cjs"
splitting: true, // Code splitting
minify: true,
sourcemap: "linked",
external: ["react", "react-dom"], // Don't bundle these
});
# CLI usage
bun build ./src/index.ts --outdir ./dist --target node --minify
For simple bundling tasks, Bun is faster than esbuild and doesnβt require configuration files for standard use cases.
Node.js Migration Guide
Compatibility Layer
Bun implements most of the Node.js API. Common modules work without changes:
// These work in Bun with no modifications:
import fs from "node:fs";
import path from "node:path";
import crypto from "node:crypto";
import { EventEmitter } from "node:events";
import { Readable, Writable } from "node:stream";
import http from "node:http";
import https from "node:https";
import os from "node:os";
import process from "node:process";
Migration Steps
Step 1: Install Bun
curl -fsSL https://bun.sh/install | bash
Step 2: Try running your app
bun run src/index.ts
# Most Node.js apps just work
Step 3: Replace package manager (optional but recommended)
# Remove node_modules and lockfiles
rm -rf node_modules package-lock.json yarn.lock
# Reinstall with Bun
bun install
Step 4: Update test runner (optional)
# Replace jest config with bun:test
# Change: import { describe, test, expect } from '@jest/globals'
# To: import { describe, test, expect } from 'bun:test'
Known Incompatibilities
// Node.js APIs with partial support:
// β
Works in Bun
import { createServer } from "net";
import { Worker } from "worker_threads";
import { createHash } from "crypto";
// β οΈ Partial support (check bun.sh/compatibility)
import cluster from "cluster"; // Basic support, not production-ready
import vm from "vm"; // Partial
import inspector from "inspector"; // Limited
// β Not supported
// Some internal Node.js C++ addons (.node files) won't work
// Specific native modules that depend on N-API may have issues
Check bun.sh/compatibility for the current compatibility matrix β it improves with every release.
Framework Compatibility
| Framework | Bun Support | Notes |
|---|---|---|
| Express | β Full | Drop-in compatible |
| Fastify | β Full | Drop-in compatible |
| Hono | β Native | Built for Bun/Edge |
| Next.js | β οΈ Partial | bun run next dev works, some edge cases |
| NestJS | β Full | Use @nestjs/platform-bun adapter |
| Prisma | β Full | Bun-native client available |
| Drizzle | β Full | Works natively |
Production Deployment
Docker
FROM oven/bun:1.1-alpine AS base
WORKDIR /app
# Install dependencies
FROM base AS deps
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile --production
# Build
FROM base AS builder
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build
# Production image
FROM base AS runner
ENV NODE_ENV=production
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json .
EXPOSE 3000
CMD ["bun", "run", "dist/index.js"]
PM2 Alternative: Bunβs Process Management
# Simple process management
bun run --watch src/index.ts # Development
bun run src/index.ts # Production (use systemd or PM2 externally)
For production, use systemd or PM2 to manage Bun processes β Bun itself doesnβt include a process manager.
Environment Variables
// Bun reads .env automatically (no dotenv package needed)
const port = Bun.env.PORT ?? "3000";
const dbUrl = Bun.env.DATABASE_URL;
if (!dbUrl) {
throw new Error("DATABASE_URL is required");
}
When to Use Bun in Production
Use Bun when:
- CLI tools and scripts: 10x faster startup + TypeScript natively = ideal for dev tooling
- Serverless functions: Cold start matters, bundle size matters
- New greenfield APIs: No legacy dependencies, can use Bunβs native APIs
- CI/CD pipelines:
bun installis dramatically faster - Microservices: Well-defined scope, easy to validate compatibility
Stick with Node.js when:
- Large existing codebase with heavy native module dependencies
- Specific C++ addons that arenβt compatible yet
- Team unfamiliarity and short deadline β migration risk isnβt worth it
- Enterprise requirements for LTS support timelines
Conclusion
Bun in 2026 is genuinely production-ready for a wide range of use cases. The performance benefits are real and measurable β 3-5x faster for I/O-heavy workloads, 10x faster package installs, near-instant TypeScript execution.
The migration story has also improved significantly. Most Express apps run on Bun without changes. Most Jest tests work with a single import swap.
The pragmatic approach: start using Bun for new microservices and CLI tools today. Migrate existing services when the timing is right β not because you have to, but because the developer experience improvements are genuinely worth it.
Benchmarks run on Bun 1.1.x, Node.js 22 LTS, Ubuntu 22.04. Results vary by workload β measure your specific use case.
50 CLI Commands That Save Hours Every Week
The exact Git shortcuts, file search tricks, Docker commands, and productivity hacks that senior developers use daily. Compiled from 5+ years of shipping production code.
- Git mastery (10 cmds)
- File & search wizardry
- Docker & DevOps tricks
- Process & network tools
- Productivity boosters
- macOS & Linux install guide
No spam. 1 email/week max. Unsubscribe anytime.
Found this guide useful? Check out our free developer tools.
Affiliate disclosure: Some links below are affiliate links β we may earn a small commission at no extra cost to you. Learn more.
Recommended Tools & Resources
DigitalOcean
$200 credit for new users. Simple, affordable cloud hosting for developers.
GitHub Student Pack
Free access to 100+ developer tools. Perfect for students and new devs.
Vercel
Deploy frontend apps instantly. Free tier is generous for side projects.
DevPlaybook Products
Boilerplates, scripts & AI toolkits to 10x your dev workflow.