Bun is a fast JavaScript runtime & toolkit. All in one.
Runtime, package manager, test runner and bundler in a single binary. Use bun install or bun test in an existing Node.js project, or run the whole thing on Bun.
Install Bun v1.3.14
curl -fsSL https://bun.sh/install | bashBundling 10 copies of three.js
with sourcemaps and minification · milliseconds (lower is better)
| runtime | version | bundle time | peak RAM |
|---|---|---|---|
| Bun | v1.3.0 | 269.1 ms | |
| Rolldown | v1.0.0-beta.42 | 494.9 ms | |
| esbuild | v0.25.10 | 571.9 ms | |
| Farm | v1.0.5 | 1,608 ms | |
| Rspack | v1.5.8 | 2,137 ms |
Express.js “hello world”
HTTP requests per second (higher is better)
| runtime | version | requests/sec | peak RAM |
|---|---|---|---|
| Bun | v1.2 | 59,026 req/s | |
| Deno | v2.1.6 | 25,335 req/s | |
| Node.js | v23.6.0 | 19,039 req/s |
Load a huge Postgres table
100 rows × 100 parallel queries · queries per second (higher is better)
| runtime | version | queries/sec | peak RAM |
|---|---|---|---|
| Bun | v1.2.22 | 28,571 queries/s | |
| Node.js | v24.8.0 | 14,522 queries/s | |
| Deno | v2.5.1 | 11,169 queries/s |
A WebSocket chat server
32 clients · messages sent per second (higher is better)
| runtime | version | messages/sec | peak RAM |
|---|---|---|---|
| Bun.serve() | v1.2 | 2,536,227 msgs/s | |
| Deno.serve() | v2.1.6 | 1,320,525 msgs/s | |
| ws (Node.js) | v23.6.0 | 435,099 msgs/s |
Used by
Four tools, designed together.
Adopt one, or all of them.
bun install and bun test drop into existing Node.js projects. No runtime switch required.
Runtime
replaces Node.js
Runs JavaScript & TypeScript on JavaScriptCore. Node.js APIs, node_modules and your framework work as-is.
$ bun run index.tsxPackage manager
replaces npm · yarn · pnpm
npm-compatible, up to 30× faster. Workspaces, catalogs, overrides, patches and a lockfile you can read.
$ bun installTest runner
replaces Jest · Vitest
Jest-compatible expect(), mocks, snapshots, DOM and coverage — starting in milliseconds.
$ bun testBundler
replaces esbuild · Vite · webpack
TS, JSX, CSS & HTML for browsers and servers. Dev server with HMR. Single-file executables.
$ bun build ./app.tsxA minute with Bun
One binary for the whole workflow.
Install, develop, run, test and ship with the same tool. Every step below is a real command with real output — click one, or just watch.
$ bun installbun install v1.3.14 (0aa2b1cd)🔍 Resolving [712/712]+ react@19.1.0+ react-dom@19.1.0+ next@15.4.1+ tailwindcss@4.1.11+ typescript@5.9.2 (+ 706 more)712 packages installed [1.18s]$
v1.3.14Latest release · May 2026
Built-in image processing, HTTP/3, and 7× faster warm installs.
Bun 1.3.14 fixes 92 issues and keeps shrinking the toolchain you need around it: image transforms without sharp, HTTP/2 and HTTP/3 clients in fetch(), QUIC in Bun.serve(), and a global store that makes repeat installs nearly free.
$ bun upgrade- faster warm installs
- 7×
- issues fixed
- 92
- in fetch & Bun.serve
- HTTP/3
- smaller binary
- −4MB
isolated linker + shared global store
addressing 380 👍 on GitHub
experimental QUIC client and server
on Linux x64 since 1.3.11
Bun.Imageresize, convert and optimise images nativelyfetch()experimental HTTP/2 and HTTP/3 clientsfs.watch()rewritten on Linux and macOS for reliabilityprocess.execve()replace the current process, like exec(3)Bun.Terminalnow works on Windows via ConPTY--no-orphanschild processes never outlive their parent- FreeBSD and Android builds
- Shared SSL_CTX cache: less memory per TLS connection
In production
Bun in production
Claude Code ships to millions of developers as a Bun executable. Midjourney pushes every image notification through Bun's WebSocket server. Railway runs its serverless functions on it. Hear it from them:
Claude Code
Claude Code ships to every developer as a Bun single-file executable.
Claude Code is a single file with Bun inside it. Users download it and run it. There is no install step and no startup lag.
Midjourney
Every image notification Midjourney sends goes through Bun's WebSocket server.
Pub/sub, backpressure and per-message compression are built into Bun.serve() — no ws, no socket.io, no sidecar.
Railway
Railway built its serverless Functions product on Bun.
A Railway Function is a TypeScript file. Bun runs it as-is, so a deploy skips the build and a cold start takes milliseconds.
Frameworks
Bun runs Next.js, Remix, Nuxt, Astro, SvelteKit, Hono, Elysia & friends.
Node.js compatibility means your framework already works. Swap npm run dev for bun --bun run dev and keep shipping — with Bun's SQL, S3 and shell APIs available right inside your route handlers.
import { s3, $, sql } from "bun";export default async function BlogPage({ params }) {const [post] = await sql`SELECT * FROM posts WHERE slug = ${params.slug}`;const img = s3.file(post.imageKey).presign();const words = await $`wc -w < ${post.file}`.text();return <Article post={post} img={img} words={words} />;}
Batteries included
The APIs you need, baked in.
Most servers need an HTTP stack, a database client, Redis, S3, hashing and a way to shell out. Bun ships all of them, so that is a stack of packages you never install or patch.
Bun.serve() with routes, params and static responses.
Docsserver.ts
import { serve, sql } from "bun";
const server = serve({
port: 3000,
routes: {
"/": new Response("Welcome to Bun!"),
"/api/users/:id": async req => {
const [user] = await sql`SELECT * FROM users WHERE id = ${req.params.id}`;
return Response.json(user);
},
},
});
console.log(`Listening on ${server.url}`);Pub/sub WebSocket server, built into Bun.serve().
Docschat.ts
Bun.serve({
fetch(req, server) {
if (server.upgrade(req, { data: { room: "lobby" } })) return;
return new Response("Expected a WebSocket", { status: 400 });
},
websocket: {
open(ws) {
ws.subscribe(ws.data.room);
},
message(ws, message) {
// broadcast to everyone in the room
ws.publish(ws.data.room, message);
},
},
});Bun.sql — tagged templates, pipelining, transactions.
Docsdb.ts
import { sql } from "bun";
// Parameters are escaped automatically
const active = await sql`
SELECT * FROM users
WHERE active = ${true}
LIMIT 10
`;
// Insert with object notation
const [user] = await sql`
INSERT INTO users ${sql({ name: "Alice", email: "alice@example.com" })}
RETURNING *
`;A fast Redis client with Pub/Sub — no driver to install.
Docscache.ts
import { redis } from "bun";
await redis.set("greeting", "Hello from Bun!");
const greeting = await redis.get("greeting");
await redis.hset("user:1", { name: "Alice", plan: "pro" });
await redis.expire("user:1", 3600);
const subscriber = redis.duplicate();
await subscriber.subscribe("events", message => {
console.log("event:", message);
});Read, write and presign objects on any S3-compatible store.
Docsstorage.ts
import { s3 } from "bun";
const file = s3.file("uploads/avatar.png");
await file.write(await Bun.file("./avatar.png").bytes(), {
type: "image/png",
});
const url = file.presign({ expiresIn: 3600 });
const exists = await file.exists();Bun.$ — cross-platform bash-like scripting with JS interop.
Docsdeploy.ts
import { $ } from "bun";
// Works the same on macOS, Linux and Windows
const branch = await $`git rev-parse --abbrev-ref HEAD`.text();
await $`bun run build`;
// Pipe a fetch() Response straight through gzip
const res = await fetch("https://example.com/data.json");
await $`gzip -9 < ${res} > data.json.gz`;
console.log(`deployed ${branch.trim()}`);bun test — Jest-compatible, concurrent, instant startup.
Docsmath.test.ts
import { describe, expect, mock, test } from "bun:test";
describe("math", () => {
test("addition", () => {
expect(2 + 2).toBe(4);
});
test.concurrent("fetches a user", async () => {
const res = await fetch("https://api.example.com/users/1");
expect(res.status).toBe(200);
});
test("mocks", () => {
const fn = mock(() => 42);
fn();
expect(fn).toHaveBeenCalledTimes(1);
});
});argon2 & bcrypt hashing without native addons.
Docsauth.ts
const password = "super-secure-pa$$word";
const hash = await Bun.password.hash(password);
// => $argon2id$v=19$m=65536,t=2,p=1$tFq+9AVr1bf...
const ok = await Bun.password.verify(password, hash);
// => true
const legacy = await Bun.password.hash(password, {
algorithm: "bcrypt",
cost: 12,
});Import an HTML file and you have a full-stack dev server.
Docsapp.ts
import { serve } from "bun";
import homepage from "./index.html";
import dashboard from "./dashboard.html";
serve({
routes: {
"/": homepage,
"/dashboard": dashboard,
"/api/health": () => Response.json({ ok: true }),
},
development: {
hmr: true, // hot module reloading
console: true, // stream browser logs to this terminal
},
});Call into C, Rust or Zig shared libraries.
Docssqlite-version.ts
import { dlopen, FFIType, suffix } from "bun:ffi";
// "dylib" on macOS, "so" on Linux, "dll" on Windows
const lib = dlopen(`libsqlite3.${suffix}`, {
sqlite3_libversion: {
args: [],
returns: FFIType.cstring,
},
});
console.log(`SQLite ${lib.symbols.sqlite3_libversion()}`);…and the rest of the standard library
Full API referenceHTTP & WebSockets
Files & processes
Frontend
Full speed, full‑stack
Point Bun at an HTML file and you get a dev server with instant hot reloading, then bun build --production for optimized bundles. React, TypeScript, Tailwind and CSS imports work out of the box.
- 1
bun init --reactScaffold a React app (or add index.html to any project).
- 2
bun ./index.htmlDev server with HMR that preserves state; browser logs stream to your terminal.
- 3
bun build ./index.html --productionTree-shaken, minified, code-split bundles.
Bun is a complete toolkit.
| Feature | Node.js | Deno | |
|---|---|---|---|
| Runtime | |||
| Node.js compatibility | |||
| Web Standard APIs | |||
| TypeScript | |||
| JSX | |||
| Native addons | |||
| Module loader plugins | |||
| Built-in APIs | |||
| PostgreSQL, MySQL & SQLite drivers | |||
| S3 client | |||
| Redis client | |||
| Tooling | |||
Try it on the repo
you have open
right now.
Install Bun, open the project you were already working on, and run bun install. Your code, dependencies and scripts stay exactly as they are.
curl -fsSL https://bun.sh/install | bash