know.2nth.ai tech runtime Bun
tech/runtime · Bun · Skill Leaf

One tool, five tools' worth of work.

Bun is a JavaScript runtime, package manager, test runner, and bundler in a single binary. Built on JavaScriptCore (Safari's engine) and written in Zig, it installs ~10x faster than npm, runs TypeScript natively, and replaces the node + npm + webpack + tsc + jest stack with one command. Three years old, production-credible since 1.0, and aggressively shipping.

Live since 2023 Engine · JavaScriptCore Built in Zig Drop-in npm-compatible v1.x stable

A runtime, a package manager, a test runner, and a bundler — in one binary.

Bun is the load-bearing tool collapse of the JavaScript ecosystem. The pitch isn't "we built a faster Node" — it's "we built a single tool that replaces node, npm/pnpm, tsc, webpack/esbuild, and jest, and each individual replacement happens to be the fastest in its category." That's a different value proposition than "shave 30ms off cold starts."

Under the hood: JavaScriptCore as the JS engine (Safari's engine, not V8), Zig as the implementation language (manual memory management, fast compiles, tight FFI), and a small army of native APIs that mirror Node's where they exist and add new ones (Bun.serve, Bun.write, Bun.file) where they don't.

The result that matters most in day-to-day work: bun install on a typical Next.js app finishes in 1-3 seconds vs 20-60 seconds for npm. bun test runs roughly 4x faster than Jest on the same suite. Cold start is ~5ms vs Node's ~30-50ms. None of these are individually transformative; together they change how the development loop feels.

The all-in-one frame, in one breath

Bun = bun (run) + bun install (npm) + bun test (jest) + bun build (webpack/esbuild) + bun x (npx) + bunx + bun init + native TypeScript + native JSX + native env-var loading + native SQLite + native HTTP server. One binary, one config file, one mental model. The "no JavaScript build chain" thesis, made executable.

Drop-in for Node, plus the rest of the toolchain.

If you can run a project with node script.ts (or tsx), you can probably run it with bun script.ts. The package.json stays unchanged, the node_modules structure is the same, the dependency resolution is npm-compatible. Bun then layers on the bits Node doesn't include: native TypeScript, the package manager, the test runner, the bundler.

The day-to-day commands:

# Install bun (macOS / Linux)
curl -fsSL https://bun.sh/install | bash

# In an existing Node project — drop in
bun install                  # replaces npm install
bun run "any-script-name"    # replaces npm run script-name
bun server.ts             # run TypeScript directly, no transpile step

# Test runner (Jest-API-compatible)
bun test
bun test --watch
bun test --coverage

# Bundler (esbuild-compatible API)
bun build ./src/index.ts --outdir=./dist --target=node

# Greenfield project — one command
bun init                     # project + package.json + tsconfig + entrypoint

The hello-world server, in seven lines, no dependencies, no build step:

// server.ts — run with: bun server.ts
Bun.serve({
  port: 3000,
  fetch(req) {
    const url = new URL(req.url);
    if (url.pathname === "/") return new Response("hello world");
    return new Response("not found", { status: 404 });
  },
});

Why JavaScriptCore, not V8

JavaScriptCore is Apple's JS engine, used in Safari. Compared to V8: faster cold start (lower startup overhead), better memory profile under sustained load, comparable peak throughput on optimised hot loops. JSC matters for cold-start-sensitive workloads (edge functions, CLI tools, serverless) where V8's optimisation budget hasn't paid off yet. For long-running servers, the difference is small — both engines are excellent.

Six places Bun bites if you're new to it.

Bun is genuinely production-ready, but it's three years old, not sixteen. There are real edges — mostly around long-tail npm packages, platform-specific behaviour, and the pace at which Bun itself ships breaking changes. Knowing where it bites means you can plan around it.

Native Node addon compatibility

Packages that use node-gyp to compile C++ addons (e.g. better-sqlite3, some canvas bindings, ML/native libs) usually work but have edge cases. Bun's NAPI implementation is good; not 100%. Always check the project's "Bun compatibility" badge or test before committing to a stack choice.

Cloudflare Workers isn't a Bun target

Workers run on V8 isolates with Cloudflare's runtime; Bun isn't the runtime there. Use Bun for local dev, build, and tests; deploy to Workers using wrangler as normal. Don't try to ship Bun-specific APIs (Bun.serve, Bun.write) to Workers — they don't exist there. See tech/cloudflare/workers.

Breaking changes in minor versions

Bun ships fast. v1.0 to v1.x has had semantic-version compliance — but minor releases occasionally fix bugs by changing behaviour, and that has bitten teams pinned to specific versions. Pin your Bun version in .bunversion or CI; review release notes before bumping.

Lockfile is binary, not text

bun.lockb is a binary lockfile (faster to parse than text). Diffs in PRs are unreadable; some hosting platforms can't render it cleanly. Mitigations: bun install --print-text-lock for human-readable output; or convert to bun.lock JSON format (introduced 2024) for diff-friendly history.

Windows is officially supported but second-class

Native Windows support shipped 2024 but lags macOS / Linux for some package compatibility and performance. If your team is mixed-OS, test on the actual OS the dev runs — don't assume parity. WSL2 is a reliable fallback.

Some Node patterns work, some surprise you

process.env, fs, path, http, https, events, stream — all work. worker_threads works but with edge cases. vm module has gaps. child_process works but spawning is slightly different. The "drop-in for Node" frame is true for 95% of code; that 5% is where to test before betting the project on it.

When Bun wins. When Node still wins.

Both runtimes are credible production choices in 2026. The interesting question is when each one is the better fit for a given project, not whether one is universally superior. The honest answer: Node is the safe default for production with mature dependency chains; Bun is the upgrade for greenfield projects, edge / cold-start workloads, and teams that value developer-loop ergonomics.

ConcernNode.jsBun
Cold start~30-50ms~3-10ms (4-10x faster)
Install speednpm: 20-60s typical / pnpm: ~5-15sbun install: 1-3s (~10x npm, ~3x pnpm)
Test runnernode:test (built-in but rough) / vitest / jestbun test (Jest-compatible API, ~4x Jest)
TypeScriptNeeds tsx / ts-node / tsc compile stepNative, no config needed
BundlerExternal (webpack / esbuild / rollup / vite)bun build (esbuild-API-compatible)
Ecosystem maturity16 years, every package tested3 years, ~99% npm compat with edge cases
Cloudflare WorkersWorkers Node compat layer is solidNot a Workers runtime; use for local dev
Native addons (node-gyp)Universal supportMostly works, some edge cases
Production track recordMassive (Netflix, Uber, LinkedIn, etc.)Growing fast (Vercel uses internally, many startups)
"Just works" for developer ergonomicsFive separate tools to configureOne tool, opinionated defaults

Pick Bun when

  • Greenfield project — you're choosing the stack, not migrating
  • Cold start matters — CLI tools, edge functions, serverless
  • TypeScript-heavy — you want to skip the build chain
  • Monorepo with frequent installs — the speed compounds
  • Developer ergonomics — one tool replacing five is the value
  • You can afford to pin and test — smaller team, faster iteration

The hybrid pattern most teams adopt

Local development on Bun, production on Node — or even local on Bun, production on Workers. Bun gives you the fast install + native TS + fast tests during development; Node (or Workers) handles the production runtime where the long compatibility tail matters. Only the Bun-specific APIs (Bun.serve, Bun.write, Bun.file) need a fallback; everything else is portable. The package.json stays compatible with both.

Where Bun links in the tree.

Bun is the runtime layer beneath modern JavaScript projects, which means it touches almost every other tech sub-tree — databases (Drizzle works on both Bun and Node), edge platforms (Workers isn't Bun but Node-compat is), serverside-rendered frameworks (most Vite/Next.js dev experiences benefit from bun dev), and the MCP / agent ecosystem (Bun's startup speed is a real advantage for spawning short-lived agent processes).

Go deeper.

Bun's documentation is unusually good for a young runtime — the docs site is the right place to start. The GitHub repo is where the actual development happens; the changelog is where you find out what just broke or just got faster.