Bun 1.x Complete Guide 2026: Runtime, Package Manager, Bundler
Master Bun 1.x in 2026 — from installation and CLI commands to performance benchmarks vs Node/pnpm, built-in SQLite, hot reload, and production deployment strategies.
Bun 1.x has crossed from “interesting experiment” to “production-ready runtime” that thousands of teams are adopting in 2026. Unlike Node.js, which was designed for servers in 2009, Bun was architected from scratch with modern developer needs in mind: fast startup, fast installs, TypeScript-first, and zero config.
This guide covers everything you need to know — from your first bun install to deploying a full-stack app in production.
What Is Bun?
Bun is a JavaScript toolkit that replaces four separate tools with one binary:
| Tool | Replaced by Bun |
|---|---|
| Node.js | bun run |
| npm/pnpm/yarn | bun install |
| esbuild/Rollup | bun build |
| Jest/Vitest | bun test |
Written in Zig and powered by JavaScriptCore (WebKit’s JS engine), Bun prioritizes startup speed and I/O performance over everything else.
# The entire Bun toolkit in four commands
bun run server.ts # Execute TypeScript directly — no transpile step
bun install # Install packages (reads package.json)
bun build ./app.ts # Bundle for browser or Node.js
bun test # Jest-compatible test runner
Installation
macOS / Linux
curl -fsSL https://bun.sh/install | bash
This installs the bun binary to ~/.bun/bin. Add it to your PATH if not auto-configured.
Windows
powershell -c "irm bun.sh/install.ps1 | iex"
Docker
FROM oven/bun:1 AS base
WORKDIR /usr/src/app
FROM base AS install
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
FROM base AS release
COPY --from=install /usr/src/app/node_modules node_modules
COPY . .
EXPOSE 3000
CMD ["bun", "run", "src/index.ts"]
Version Management
# Check version
bun --version
# Upgrade Bun itself
bun upgrade
# Install a specific version
curl -fsSL https://bun.sh/install | bash -s "bun-v1.1.38"
Bun as a Runtime
TypeScript Out of the Box
Bun executes TypeScript directly without a build step. No ts-node, no tsx, no tsc --watch.
// server.ts
import { serve } from "bun";
const server = serve({
port: 3000,
fetch(req) {
const url = new URL(req.url);
if (url.pathname === "/health") {
return Response.json({ status: "ok", uptime: process.uptime() });
}
return new Response("Hello from Bun!", { status: 200 });
},
});
console.log(`Server running at http://localhost:${server.port}`);
bun run server.ts # Works immediately, no config needed
Node.js Compatibility
Bun implements the Node.js API. Most packages work without modification:
import { readFileSync, writeFileSync } from "fs";
import { join } from "path";
import { createServer } from "http";
import express from "express"; // Works
import fastify from "fastify"; // Works
import { PrismaClient } from "@prisma/client"; // Works
Notable gaps as of 2026:
- Some native addons (
.nodefiles) may not work - Worker threads: mostly supported, some edge cases
clustermodule: supported since Bun 1.1
Hot Reload
# Watch mode — restarts on file changes
bun --hot run server.ts
# Development mode with more verbose output
bun --watch run server.ts
The --hot flag uses Bun’s hot module replacement without restarting the process, preserving state. --watch is a full restart on change.
Bun as a Package Manager
Core Commands
# Install all dependencies (reads package.json)
bun install
# Add a package
bun add express
bun add -d typescript @types/node # Dev dependency
# Remove a package
bun remove lodash
# Update packages
bun update
bun update express # Update specific package
# Run a script from package.json
bun run dev
bun run build
# Execute a binary from node_modules/.bin
bunx eslint . # Like npx
Performance vs npm/pnpm
Bun’s package manager is dramatically faster thanks to a symlink-based module resolution and a global binary cache:
| Operation | npm | pnpm | Bun |
|---|---|---|---|
| Fresh install (cache cold) | 45s | 18s | 8s |
| Install (cache warm) | 12s | 4s | 0.8s |
node_modules size | 300 MB | 120 MB | 90 MB |
Benchmarks on a 150-package React app, Apple M2 Pro, 2026.
bun.lockb
Bun uses a binary lockfile (bun.lockb) instead of JSON for speed:
# View lockfile in human-readable format
bun bun.lockb
# Force regenerate lockfile
rm bun.lockb && bun install
Commit bun.lockb to version control. Use --frozen-lockfile in CI to fail on drift.
Workspaces
// package.json (root)
{
"name": "my-monorepo",
"workspaces": ["packages/*", "apps/*"]
}
# Install all workspace dependencies
bun install
# Run a script in a specific workspace
bun run --filter ./apps/web dev
Bun as a Bundler
Basic Bundling
# Bundle for browser
bun build ./src/index.ts --outdir ./dist --target browser
# Bundle for Bun/Node.js
bun build ./src/server.ts --outdir ./dist --target bun
# Minify output
bun build ./src/index.ts --outdir ./dist --minify
# Watch mode for development
bun build ./src/index.ts --outdir ./dist --watch
Bundle API
// build.ts
const result = await Bun.build({
entrypoints: ["./src/index.ts"],
outdir: "./dist",
target: "browser",
minify: true,
sourcemap: "external",
splitting: true, // Code splitting
define: {
"process.env.NODE_ENV": '"production"',
},
});
if (!result.success) {
console.error("Build failed:", result.logs);
process.exit(1);
}
console.log(`Built ${result.outputs.length} files`);
Loaders
Bun handles many file types without plugins:
// All these just work
import styles from "./app.css"; // CSS as text
import logo from "./logo.png"; // Images as data URL
import data from "./config.json"; // JSON objects
import raw from "./template.html" with { type: "text" }; // Raw text
Performance vs esbuild/Webpack
| Bundler | Cold build (150 modules) | Rebuild (1 file change) |
|---|---|---|
| Webpack 5 | 8.2s | 1.4s |
| Vite (dev) | 1.1s | 0.08s |
| esbuild | 0.31s | 0.04s |
| Bun build | 0.28s | 0.03s |
Bun’s bundler matches esbuild in most benchmarks.
Bun as a Test Runner
Writing Tests
Bun’s test API is Jest-compatible:
// math.test.ts
import { expect, test, describe, beforeEach } from "bun:test";
import { add, multiply } from "./math";
describe("Math utilities", () => {
test("adds numbers correctly", () => {
expect(add(2, 3)).toBe(5);
expect(add(-1, 1)).toBe(0);
});
test("multiplies numbers correctly", () => {
expect(multiply(3, 4)).toBe(12);
});
});
// Async tests
test("fetches user data", async () => {
const user = await fetchUser(1);
expect(user).toMatchObject({ id: 1, name: expect.any(String) });
});
Running Tests
# Run all tests
bun test
# Run specific file
bun test math.test.ts
# Watch mode
bun test --watch
# Coverage report
bun test --coverage
# Filter by test name
bun test --test-name-pattern "adds numbers"
Mocking
import { mock, spyOn } from "bun:test";
// Mock a module
mock.module("./database", () => ({
findUser: mock(() => Promise.resolve({ id: 1, name: "Alice" })),
}));
// Spy on a method
const spy = spyOn(console, "log");
someFunction();
expect(spy).toHaveBeenCalledWith("expected message");
Built-in APIs
Bun.serve() — HTTP Server
import { serve } from "bun";
serve({
port: 3000,
// WebSocket support built-in
websocket: {
open(ws) {
ws.send("Connected!");
},
message(ws, message) {
ws.send(`Echo: ${message}`);
},
close(ws) {
console.log("Client disconnected");
},
},
fetch(req, server) {
const url = new URL(req.url);
// Upgrade to WebSocket
if (url.pathname === "/ws") {
if (server.upgrade(req)) return;
return new Response("WebSocket upgrade failed", { status: 400 });
}
return new Response("Hello World");
},
});
SQLite Built-in
Bun ships with SQLite3 — no npm install required:
import { Database } from "bun:sqlite";
const db = new Database("myapp.db");
// Create table
db.run(`
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
)
`);
// Prepared statements (use these for performance)
const insertUser = db.prepare(
"INSERT INTO users (name, email) VALUES ($name, $email)"
);
const getUser = db.prepare("SELECT * FROM users WHERE id = $id");
const getAllUsers = db.prepare("SELECT * FROM users ORDER BY created_at DESC");
// Execute
insertUser.run({ $name: "Alice", $email: "[email protected]" });
insertUser.run({ $name: "Bob", $email: "[email protected]" });
const alice = getUser.get({ $id: 1 });
const users = getAllUsers.all();
console.log(users);
// Transactions
const insertMany = db.transaction((users) => {
for (const user of users) {
insertUser.run(user);
}
});
insertMany([
{ $name: "Carol", $email: "[email protected]" },
{ $name: "Dave", $email: "[email protected]" },
]);
db.close();
File I/O
Bun’s file APIs are faster than Node.js’s fs module:
// Read a 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 a file
await Bun.write("./output.txt", "Hello World");
await Bun.write("./data.json", JSON.stringify({ key: "value" }));
// Stream a large file
const file = Bun.file("./large.csv");
const stream = file.stream();
const reader = stream.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Process chunk
}
// Copy a file
await Bun.write(Bun.file("./copy.txt"), Bun.file("./original.txt"));
Environment Variables
// .env is loaded automatically — no dotenv needed
const port = Bun.env.PORT ?? "3000";
const dbUrl = Bun.env.DATABASE_URL;
// Access all env vars
console.log(Bun.env);
Performance Benchmarks
HTTP Server Throughput (req/s)
Bun.serve() ~127,000 req/s
Fastify on Bun ~108,000 req/s
Hono on Bun ~115,000 req/s
Node.js (native) ~62,000 req/s
Fastify on Node.js ~58,000 req/s
Express on Node.js ~28,000 req/s
Tested on Apple M2 Pro, simple JSON response, wrk benchmark.
Startup Time
Bun run hello.ts ~5ms
Node.js hello.js ~45ms
Deno run hello.ts ~30ms
Package Install (React app, 847 packages)
bun install (cold) 8.2s
pnpm install (cold) 18.4s
npm install (cold) 44.7s
yarn install (cold) 35.1s
Migration Guide from Node.js
Step 1: Replace the runtime
# Before
node server.js
npx ts-node server.ts
# After
bun server.js
bun server.ts # TypeScript works directly
Step 2: Replace package manager
# Before
npm install
npm run dev
npx some-tool
# After
bun install
bun dev
bunx some-tool
Step 3: Update package.json scripts
{
"scripts": {
"dev": "bun --hot run src/index.ts",
"build": "bun build src/index.ts --outdir dist --target bun",
"start": "bun dist/index.js",
"test": "bun test"
}
}
Step 4: Handle Node.js-specific patterns
// Before (Node.js)
import { createRequire } from "module";
const require = createRequire(import.meta.url);
// After (Bun supports both)
import something from "some-package"; // ESM
const something = require("some-package"); // CommonJS also works in Bun
// __dirname equivalent in Bun
const dir = import.meta.dir; // Bun-native
const file = import.meta.file; // Current file path
// process.env
process.env.NODE_ENV; // Works
Bun.env.NODE_ENV; // Bun-native, same data
Common Issues During Migration
Issue: Native modules don’t load
# Check if a native addon is the problem
bun --print "process.versions"
# If the module uses N-API/nan, it may need to be rebuilt for Bun
Issue: Some npm lifecycle scripts fail
// package.json
{
"trustedDependencies": ["sharp", "canvas"]
}
Issue: Crypto module differences
// Node.js crypto works in Bun, but Bun also has Web Crypto API
const { createHash } = await import("crypto"); // Node.js API
const hash = createHash("sha256").update("data").digest("hex");
// Web Crypto API (also available)
const buffer = await crypto.subtle.digest("SHA-256", new TextEncoder().encode("data"));
Production Deployment
Compile to a Single Executable
# Create a self-contained binary
bun build ./src/index.ts --compile --outfile server
# Run it (no Bun installation needed on target machine)
./server
Docker Production Build
FROM oven/bun:1 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 build
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN bun build ./src/index.ts --outdir ./dist --target bun --minify
# Production image
FROM oven/bun:1-slim AS production
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=deps /app/node_modules ./node_modules
EXPOSE 3000
USER bun
CMD ["bun", "dist/index.js"]
Environment Configuration
# Development
bun --hot run src/index.ts
# Staging
NODE_ENV=staging bun run src/index.ts
# Production
NODE_ENV=production bun run dist/index.js
Health Check Pattern
import { serve } from "bun";
const startTime = Date.now();
serve({
port: process.env.PORT ?? 3000,
fetch(req) {
const url = new URL(req.url);
if (url.pathname === "/health") {
return Response.json({
status: "healthy",
uptime: Math.floor((Date.now() - startTime) / 1000),
memory: process.memoryUsage(),
version: Bun.version,
});
}
// Application routes...
return new Response("Not Found", { status: 404 });
},
});
When to Use Bun
Use Bun when:
- You want faster installs in CI/CD pipelines
- You’re building TypeScript-first applications
- Your API server needs high throughput
- You want SQLite without adding dependencies
- You’re building CLI tools (fast startup matters)
- You’re starting a new project and want a clean setup
Stick with Node.js when:
- Your project relies on native addons that don’t support Bun
- Your team has deep Node.js expertise and migration cost is high
- You’re using specific Node.js features in early/unstable Bun support
- Your deployment environment (AWS Lambda, etc.) doesn’t support Bun runtimes yet
Developer Tools for Bun Projects
These DevPlaybook tools are useful when working with Bun:
- JSON Formatter — Format and validate package.json and API responses
- Regex Tester — Test patterns for Bun’s file routing or validation
- Hash Generator — Explore Bun’s built-in crypto APIs
- Base64 Encoder — Work with binary data in Bun’s file APIs
Summary
Bun 1.x in 2026 is a mature, production-ready alternative to Node.js for most web applications. Its strongest advantages are:
- Speed: 5–10x faster package installs, 2x faster startup, and significantly higher HTTP throughput
- TypeScript-native: run
.tsfiles directly with no config - All-in-one: replace four tools with one binary
- Built-ins: SQLite, WebSocket, and fast file I/O without npm packages
- Node.js compatibility: most existing npm packages just work
The migration path from Node.js is often as simple as swapping node for bun and npm install for bun install. For new projects, Bun is an excellent default choice in 2026.
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.