← All articles
RUNTIME Bun Runtime: Faster Node.js Alternative with Built-i... 2026-03-04 · 4 min read · bun · javascript · typescript

Bun Runtime: Faster Node.js Alternative with Built-in Tooling

Runtime 2026-03-04 · 4 min read bun javascript typescript runtime node.js alternative package manager bundler performance

Bun is a JavaScript and TypeScript runtime, package manager, bundler, and test runner — all in one. It runs the V8 alternative JavaScriptCore (the engine behind Safari) and is written in Zig, resulting in significant performance improvements over Node.js for many workloads. It also natively runs TypeScript without compilation.

Why Bun

Speed: Bun starts 2-5x faster than Node.js, installs packages ~20-30x faster than npm, and executes many workloads 2-3x faster. For scripts, CLIs, and services with fast startup requirements, the difference is noticeable.

All-in-one: Bun replaces Node.js + npm/yarn/pnpm + ts-node/tsx + Jest + Webpack (in some cases). Fewer tools, faster setup.

TypeScript native: Run .ts files directly without compilation or ts-node:

bun run script.ts

Node.js compatibility: Bun implements most Node.js built-in modules (fs, path, http, crypto, etc.) and require(). Most Node.js packages work without changes.

Installation

curl -fsSL https://bun.sh/install | bash
# or
brew install bun  # macOS

Check version:

bun --version

Basic Usage

# Run a script
bun run index.ts

# Run npm scripts
bun run start
bun run build
bun test

# Install packages (lockfile: bun.lockb — much faster than npm)
bun install
bun add express
bun add -D typescript
bun remove lodash

# Run any npm-compatible script
bun x vite  # equivalent to npx vite

Bun-Native APIs

Bun provides fast, built-in APIs that outperform equivalent npm packages:

Bun.file (File I/O)

// Read file
const file = Bun.file("./data.json");
const data = await file.json();  // or .text(), .arrayBuffer(), .stream()

// Write file
await Bun.write("output.json", JSON.stringify(data));

// Check if file exists
const exists = await Bun.file("config.json").exists();

// Get file metadata
const { size, type, lastModified } = Bun.file("video.mp4");

Bun.serve (HTTP Server)

const server = Bun.serve({
  port: 3000,
  async fetch(req: Request): Promise<Response> {
    const url = new URL(req.url);

    if (url.pathname === "/api/hello") {
      return Response.json({ message: "Hello from Bun!" });
    }

    // Serve static files
    return new Response(Bun.file(`./public${url.pathname}`));
  },
});

console.log(`Listening on ${server.url}`);

Bun's HTTP server benchmarks significantly faster than Node.js with Express, closer to Go or Rust HTTP servers in raw throughput.

Bun.spawn (Subprocess)

const proc = Bun.spawn(["ls", "-la"], {
  stdout: "pipe",
  cwd: "/tmp",
});

const output = await new Response(proc.stdout).text();
const exitCode = await proc.exited;

Bun.password (Hashing)

// Built-in bcrypt/argon2 — no bcryptjs package needed
const hash = await Bun.password.hash("my-password", {
  algorithm: "bcrypt",
  cost: 10,
});

const valid = await Bun.password.verify("my-password", hash);

Bun.env

// Access environment variables
const port = Bun.env.PORT ?? "3000";

// Bun auto-loads .env files — no dotenv package needed

SQLite

import { Database } from "bun:sqlite";

const db = new Database("app.db");

// Queries are synchronous (better for simple use cases)
db.run(`CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)`);

const insert = db.prepare("INSERT INTO users (name) VALUES (?)");
insert.run("Alice");

const users = db.query("SELECT * FROM users").all();
// Type: { id: number, name: string }[]

Bun Test Runner

Built-in test runner compatible with Jest's API:

// test/user.test.ts
import { test, expect, describe, beforeEach } from "bun:test";

describe("User", () => {
  let user: User;

  beforeEach(() => {
    user = new User("Alice", "[email protected]");
  });

  test("creates user with correct properties", () => {
    expect(user.name).toBe("Alice");
    expect(user.email).toBe("[email protected]");
  });

  test("validates email format", () => {
    expect(() => new User("Bob", "invalid")).toThrow();
  });
});
bun test                 # Run all tests
bun test --watch         # Watch mode
bun test user.test.ts    # Run specific file
bun test --coverage      # Coverage report

Bundler

Bun includes a bundler for frontend and library builds:

# Bundle app for production
bun build ./src/index.ts --outdir ./dist --target browser

# Bundle as library
bun build ./src/index.ts --outfile dist/lib.js --format esm
// bun build API
await Bun.build({
  entrypoints: ["./src/index.ts"],
  outdir: "./dist",
  target: "bun",  // or "browser", "node"
  minify: true,
  sourcemap: "external",
});

For complex frontend builds with HMR, Vite is still the better choice. Bun's bundler is better suited for server-side bundles and simple frontend apps.

Node.js Compatibility

Bun implements most of the Node.js API and runtime behavior:

Known gaps (2024):

For most web APIs, servers, CLIs, and scripts: Bun is drop-in compatible. For very complex Node.js applications or those relying on native addons, test before migrating.

When to Use Bun

Good fit:

Consider alternatives:

Package manager only: You can use bun install as just a package manager in a Node.js project. It's the fastest way to install dependencies regardless of what runtime you use.

# Use bun as package manager in a Node.js project
bun install  # replaces npm install — generates bun.lockb
bun add react
node dist/index.js  # still run with Node if needed

Bun is at v1.x and production-ready for most use cases. The team is actively closing Node.js compatibility gaps and the ecosystem is maturing quickly.