Bun

Bun 1.0


Bun 1.0 is finally here.

Bun is a fast, all-in-one toolkit for running, building, testing, and debugging JavaScript and TypeScript, from a single file to a full-stack application. Today, Bun is stable and production-ready.

Install Bun

curl
npm
brew
docker
curl
curl -fsSL https://bun.sh/install | bash
npm
npm install -g bun
brew
brew tap oven-sh/bun
brew install bun
docker
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun

Upgrade Bun

bun upgrade

Bun is an all-in-one toolkit

We love JavaScript. It's mature, it moves fast, and its developer community is vibrant and passionate. It's awesome.

However, since Node.js debuted 14 years ago, layers and layers of tooling have accumulated on top of each other. And like any system that grows and evolves without centralized planning, JavaScript tooling has become slow and complex.

Why Bun exists

Bun's goal is simple: eliminate slowness and complexity without throwing away everything that's great about JavaScript. Your favorite libraries and frameworks should still work, and you shouldn't need to unlearn the conventions you're familiar with.

You will however need to unlearn the many tools that Bun makes unnecessary:

Node.js — Bun is a drop-in replacement for Node.js, so you don't need:

  • node
  • npxbunx is 5x faster
  • dotenv, cross-env — Bun reads .env files by default
  • nodemon, pm2 — built-in watch mode
  • ws — built-in WebSocket server
  • node-fetch, isomorphic-fetch — built-in fetch

Transpilers — Bun can run .js, .ts, .cjs, .mjs, .jsx, and .tsx files, which can replace:

  • tsc — (but you can keep it for typechecking!)
  • babel, .babelrc, @babel/preset-*
  • ts-node, ts-node-esm
  • tsx

Bundlers — Bun is a JavaScript bundler with best-in-class performance and an esbuild-compatible plugin API, so you don't need:

  • esbuild
  • webpack
  • parcel, .parcelrc
  • rollup, rollup.config.js

Package managers — Bun is an npm-compatible package manager with familiar commands. It reads your package.json and writes to node_modules, just like other package managers, so you can replace:

  • npm, .npmrc, package-lock.json
  • yarn, yarn.lock
  • pnpm, pnpm.lock, pnpm-workspace.yaml
  • lerna

Testing libraries — Bun is a Jest-compatible test runner with support for snapshot testing, mocking, and code coverage, so you no longer need:

  • jest, jest.config.js
  • ts-jest, @swc/jest, babel-jest
  • jest-extended
  • vitest, vitest.config.ts

While these tools are each good in their own right (mostly), using them all together inevitably creates fragility and a slow developer experience. They perform a lot of redundant work; when you run jest, your code will be parsed 3+ times by various tools! And the duct tape, plugins, and adapters required to stitch everything together always frays eventually.

Bun is a single integrated toolkit that avoids these integration problems. Each tool in this toolkit provides a best-in-class developer experience, from performance to API design.

Bun is a JavaScript runtime

Bun is a fast JavaScript runtime. Its goal is to make the experience of building software faster, less frustrating, and more fun.

Node.js compatibility

Bun is a drop-in replacement for Node.js. That means existing Node.js applications and npm packages just work in Bun. Bun has built-in support for Node APIs, including:

  • built-in modules like fs, path, and net,
  • globals like __dirname and process,
  • and the Node.js module resolution algorithm. (e.g. node_modules)

While perfect compatibility with Node.js isn't possible — looking at you node:v8 — Bun can run virtually any Node.js application in the wild.

Bun is tested against test suites of the most popular Node.js packages on npm. Server frameworks like Express, Koa, and Hono just work. As do applications built using the most popular full-stack frameworks. Collectively, these libraries and frameworks touch every part of Node.js's API surface that matters.

Full-stack applications built with Next.js, Remix, Nuxt, Astro, SvelteKit, Nest, SolidStart, and Vite work in Bun.

Note — For a detailed breakdown of Node.js compatibility, check out: bun.sh/nodejs.

Speed

Bun is fast, starting up to 4x faster than Node.js. This difference is only magnified when running a TypeScript file, which requires transpilation before it can be run by Node.js.

Bun runs a "hello world" TypeScript file 5x faster than esbuild with Node.js.

Unlike Node.js and other runtimes that are built using Google's V8 engine, Bun is built using Apple's WebKit engine. WebKit is the engine that powers Safari and is used by billions of devices every day. It's fast, efficient, and has been battle-tested for decades.

TypeScript and JSX support

Bun has a JavaScript transpiler that's baked into the runtime. That means you can run JavaScript, TypeScript, and even JSX/TSX files, no dependencies needed.

bun index.ts
bun index.jsx
bun index.tsx

ESM & CommonJS compatibility

The transition from CommonJS to ES modules has been slow and full of terrors. After ESM was introduced, Node.js took 5 years before supporting it without an --experimental-modules flag. Regardless, the ecosystem is still full of CommonJS.

Bun supports both module systems, all the time. No need to worry about file extensions, .js vs .cjs vs .mjs, or including "type": "module" in your package.json.

You can even use import and require(), in the same file. It just works.

import lodash from "lodash";
const _ = require("underscore");

Web APIs

Bun has built-in support for the Web standard APIs that are available in browsers, such as fetch, Request, Response, WebSocket, and ReadableStream.

const response = await fetch("https://example.com/");
const text = await response.text();

You no longer need to install packages like node-fetch and ws. Bun's built-in Web APIs are implemented in native code, and are faster and more reliable than the third-party alternatives.

Hot reloading

Bun makes it easier for you to be productive as a developer. You can run Bun with --hot to enable hot reloading, which reloads your application when files change.

bun --hot server.ts

Unlike tools that hard-restart the entire process, like nodemon, Bun reloads your code without terminating the old process. That means HTTP and WebSocket connections don't disconnect and state isn't lost.

Plugins

Bun is designed to be highly-customizable.

You can define plugins to intercept imports and perform custom loading logic. A plugin can add support for additional file types, like .yaml or .png. The Plugin API is inspired by esbuild, which means that most esbuild plugins will just work in Bun.

import { plugin } from "bun";

plugin({
  name: "YAML",
  async setup(build) {
    const { load } = await import("js-yaml");
    const { readFileSync } = await import("fs");
    build.onLoad({ filter: /\.(yaml|yml)$/ }, (args) => {
      const text = readFileSync(args.path, "utf8");
      const exports = load(text) as Record<string, any>;
      return { exports, loader: "object" };
    });
  },
});

Bun APIs

Bun ships with highly-optimized, standard-library APIs for the things you need most as a developer.

In contrast to Node.js APIs, which exist for backwards compatibility, these Bun-native APIs are designed to be fast and easy-to-use.

Bun.file()

Use Bun.file() to lazily load a File at a particular path.

const file = Bun.file("package.json");
const contents = await file.text();

It returns a BunFile, which extends the Web standard File. The file contents can be lazily loaded in various formats.

const file = Bun.file("package.json");

await file.text(); // string
await file.arrayBuffer(); // ArrayBuffer
await file.blob(); // Blob
await file.json(); // {...}

Bun reads files up to 10x times faster than Node.js.

Bun.write()

Use Bun.write() is a single, flexible API for writing almost anything to disk — string, binary data, Blobs, even a Response object.

await Bun.write("index.html", "<html/>");
await Bun.write("index.html", Buffer.from("<html/>"));
await Bun.write("index.html", Bun.file("home.html"));
await Bun.write("index.html", await fetch("https://example.com/"));

Bun writes files up to 3x faster than Node.js.

Bun.serve()

Use Bun.serve() to spin up an HTTP server, WebSocket server, or both. It's based on familiar Web-standard APIs like Request and Response.

Bun.serve({
  port: 3000,
  fetch(request) {
    return new Response("Hello from Bun!");
  },
});

Bun can serve 4x more requests per second than Node.js.

You can also configure TLS using the tls option.

Bun.serve({
  port: 3000,
  fetch(request) {
    return new Response("Hello from Bun!");
  },
  tls: {
    key: Bun.file("/path/to/key.pem"),
    cert: Bun.file("/path/to/cert.pem"),
  }
});

To support WebSockets alongside HTTP, simply define an event handler inside websocket. Compare this with Node.js, which doesn't provide a built-in WebSocket API and requires a third-party dependency like ws.

Bun.serve({
  fetch() { ... },
  websocket: {
    open(ws) { ... },
    message(ws, data) { ... },
    close(ws, code, reason) { ... },
  },
});

Bun can serve 5x more messages per second than ws on Node.js.

bun:sqlite

Bun has built-in support for SQLite. It has an API that's inspired by better-sqlite3, but is written in native code to be faster.

import { Database } from "bun:sqlite";

const db = new Database(":memory:");
const query = db.query("select 'Bun' as runtime;");
query.get(); // => { runtime: "Bun" }

Bun can query SQLite up to 4x faster than better-sqlite3 on Node.js.

Bun.password

Bun also supports APIs for common, but complex things you wouldn't want to implement yourself.

You can use Bun.password to hash and verify passwords using bcrypt or argon2, no external dependencies required.

const password = "super-secure-pa$$word";
const hash = await Bun.password.hash(password);
// => $argon2id$v=19$m=65536,t=2,p=1$tFq+9AVr1bfPxQdh...

const isMatch = await Bun.password.verify(password, hash);
// => true

Bun is a package manager

Even if you don't use Bun as a runtime, Bun's built-in package manager can speed up your development workflow. Gone are the days of staring at that npm spinner as your dependencies install.

Bun may look like the package managers you're used to —

bun install
bun add <package> [--dev|--production|--peer]
bun remove <package>
bun update <package>

— but it doesn't feel like them.

Install speeds

Bun is orders of magnitude faster than npm, yarn, and pnpm. It uses a global module cache to avoid redundant downloads from the npm registry and uses the fastest system calls available on each operating system.

Installing dependencies for a starter Remix project from cache.

Running scripts

Chances are, you haven't ran a script directly with node in a while. Instead, we often use our package managers to interface with the frameworks and CLIs to build our apps.

npm run dev

You can replace npm run with bun run to save 150ms milliseconds every time you run a command.

These numbers may all seem small, but when running CLIs, the perceptual difference is huge. Running npm run is noticably laggy—

—whereas bun run feels instantaneous.

And we're not just picking on npm. In fact, bun run <command> is faster than the equivalent in yarn and pnpm.

Script runnerAvg. time
npm run176ms
yarn run131ms
pnpm run259ms
bun run7ms 🚀

Bun is a test runner

If you’ve written tests in JavaScript before, you’re probably familiar with Jest, which pioneered the "expect"-style APIs.

Bun has a built-in testing module bun:test that is fully Jest-compatible.

import { test, expect } from "bun:test";

test("2 + 2", () => {
  expect(2 + 2).toBe(4);
});

You can run your tests with the bun test command.

bun test

You also get all the benefits of the Bun runtime, including TypeScript and JSX support.

Migration from Jest or Vitest is easy. Any imports from @jest/globals or vitest will be internally re-mapped to bun:test, so everything works, even without code changes.

index.test.ts
import { test } from "@jest/globals";

describe("test suite", () => {
  // ...
});

In a benchmark against the test suite for zod, Bun was 13x faster than Jest and 8x faster than than Vitest.

Running the test suite for Zod

Bun's matchers are implemented in fast native code — expect().toEqual() in Bun is 100x faster than Jest and 10x faster than Vitest.

To get started, you can speed up your CI using bun test. In Github Actions, use the official oven-sh/setup-bun action.

.github/workflows/ci.yml
name: CI
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: oven-sh/setup-bun@v1
      - run: bun test

And to make things that even nicer, Bun automatically adds annotations to your test failures, so your CI logs are easy to read.

Bun is a bundler

Bun is a JavaScript and TypeScript bundler and minifier that can be used to bundle code for the browser, Node.js, and other platforms.

CLI
bun build ./index.tsx --outdir ./build

It's heavily inspired by esbuild and provides a compatible plugin API.

import mdx from "@mdx-js/esbuild";

Bun.build({
  entrypoints: ["index.tsx"],
  outdir: "build",
  plugins: [mdx()],
});

Bun's plugin API is universal, meaning it works for both the bundler and the runtime. So that .yaml plugin from earlier can be used here to support .yaml imports during bundling.

Using esbuild's own benchmarks, Bun is 1.75x faster than esbuild, 150x faster than Parcel 2, 180x times faster than Rollup + Terser, and 220x times faster than Webpack.

Bundling 10 copies of three.js from scratch, with sourcemaps and minification.

Since Bun's runtime and bundler are integrated, it means that Bun can do things that no other bundler can do.

Bun introduces JavaScript macros, a mechanism for running JavaScript functions at bundle-time. The value returned from these functions are directly inlined into your bundle.

index.ts
release.ts
index.ts
import { getRelease } from "./release.ts" with { type: "macro" };

// The value of `release` is evaluated at bundle-time,
// and inlined into the bundle, not run-time.
const release = await getRelease();
release.ts
export async function getRelease(): Promise<string> {
  const response = await fetch(
    "https://api.github.com/repos/oven-sh/bun/releases/latest"
  );
  const { tag_name } = await response.json();
  return tag_name;
}

CLI
bun build index.ts
// index.ts
var release = await "bun-v1.0.0";

This is a new paradigm for bundling JavaScript, and we're excited to see what you build with it.

Bun more thing...

Bun provides native builds for macOS and Linux, but there's been one notable absence: Windows. Previously, to run Bun on Windows, you would need to install Windows Subsystem for Linux... but not anymore.

For the first time, we're excited to release an experimental, native build of Bun for Windows.

While the macOS and Linux builds of Bun are production-ready, the Windows build is highly experimental. At the moment, only the JavaScript runtime is supported; the package manager, test runner, and bundler have been disabled until they are more stable. The performance has also not been optimized — yet.

We'll be rapidly improving support for Windows over the coming weeks. If you're excited about Bun for Windows, we'd encourage you to join the #windows channel on our Discord for updates.

Thank you

Bun's journey to 1.0 would have not been possible without Bun's amazing team of engineers and the growing community of contributors.

We'd like to thank those who helped us get here.

  • Node.js & its contributors: Software is built on the shoulder of giants.
  • WebKit & its contributors, especially Constellation: Thank you for making WebKit faster, you're amazing.
  • The nearly 300 contributors who have helped build Bun over the past two years!

What's next?

Bun 1.0 is just the beginning.

We’re developing a new way to deploy JavaScript and TypeScript to production. And we’re hiring low-level systems engineers if you want to help us build the future of JavaScript.

You can also:

  • Join our Discord server to hear the latest about Bun.
  • Follow us on X/Twitter for JavaScript memes and daily updates from Jarred and the team.
  • Star us on Github — it pays the bills! (/s)

Install Bun

curl
npm
brew
docker
curl
curl -fsSL https://bun.sh/install | bash
npm
npm install -g bun
brew
brew tap oven-sh/bun
brew install bun
docker
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun

Upgrade Bun

bun upgrade

Changelog since v0.8

If you were using Bun before 1.0, there are a few changes since Bun 0.8.

  • Next.js, Astro, and Nest.js are now supported!
  • The deprecated bun dev command has been removed. Running bun dev will now run the "dev" script in your package.json.

Bun now supports the following Node.js APIs:

Hot reloading now supports Bun.serve(). Previously, this was only possible if the server was defined as a default export.

server.ts
Bun.serve({
  fetch(request) {
    return new Response("Reload!");
  },
})

CLI
bun --hot server.ts