← cd ~

How Bun Quietly Became My Default Runtime

Hey folks,

Last weekend a toolchain bump went out across my repos, and looking at the diff I realized every active project I own now pins the same runtime: Bun 1.4.3. Varsafe, Glowo, a couple of streaming and PDF services, my homelab tooling, the CLIs. No Node fallback in sight.

There was never a big “we’re migrating to Bun” moment. It happened one release at a time, until Node became the exception instead of the default. So here’s how I got there and why I stayed. I’ll also go through the runtime news from this past week, because there was a lot of it.

A (very) short history of Bun

Bun started in April 2021 as a side quest. Jarred Sumner was building a voxel game in the browser, and testing each change took 45 seconds, most of it waiting on the Next.js dev server. Frustrated, he started porting esbuild’s JSX and TypeScript transpiler from Go to Zig. A runtime grew around it (on JavaScriptCore, Safari’s engine, rather than V8), then a package manager, a bundler and a test runner.

  • July 2022, v0.1: public launch, 20k GitHub stars in the first week. Jarred founds Oven and raises a $7M seed led by Kleiner Perkins.
  • September 2023, 1.0: “stable and production-ready”. Production usage picks up, and Oven raises a $19M Series A led by Khosla Ventures.
  • 2024–2025, 1.1, 1.2 and 1.3: Windows support, built-in S3, Postgres, MySQL and Redis clients, a full-stack dev server.
  • December 2025: Bun joins Anthropic.
  • August 2026, 1.4: the first release written in Rust.

The Anthropic deal answered the question everybody used to ask me when I said I ran Bun in production. Jarred, the day it was announced:

People frequently ask:

How is Bun sustainable? If I bet my company’s tech stack on Bun, will Bun still be around in a few years?

We didn’t have a great answer to this question, until today

(@jarredsumner, December 2, 2025)

Bun stays MIT-licensed, same team, built in public. And the incentive is about as aligned as it gets, straight from Bun’s announcement: “Claude Code ships as a Bun executable to millions of users. If Bun breaks, Claude Code breaks.” That’s a pretty good sustainability model.

Line chart of Bun monthly downloads from 5.1M in September 2025 to 19.6M in May 2026, with markers for Bun 1.3 and the Anthropic acquisition
Monthly downloads, Sep 2025 → May 2026. Chart by the Bun team (@bunjavascript on X, June 24, 2026). By September the team was reporting 32.8M for the previous month.

How I got here

I tried Bun early. bun install was absurdly fast from the start, but what really got me was the runtime: I wrote a couple of quick scripts with it and loved that it just ran TypeScript natively, a great alternative to ts-node and tsx back in the day.

1.0 to 1.3 is when it crept in. More scripts, then tests, then side projects, then APIs. Nest is behind almost everything I build, so what made Bun viable for me was decorator metadata support landing in 1.0.3. It wasn’t always smooth: now and then a patch release would break decorators or trip over Nest’s CommonJS packages, and I’d pin a version or add a workaround until the fix shipped. Small things, but they’re the reason “Bun everywhere” stayed “Bun almost everywhere” for a while.

1.3/1.4 is when it became the default, and what tipped it was stability. In July, Bun 1.3 (still Zig) turned a plain circular-import bug in my PDF service into a worker-thread segfault that crash-looped the process. On the 1.4 canary, the Rust build, the same bug surfaced as a normal, catchable JavaScript error. I moved that service to the canary the same day, and once stable 1.4.2 landed, every project followed.

What the Rust port changed

Jarred wrote the full story of the rewrite, and it’s worth reading. Why he did it, in his own words:

“why: I am so tired of worrying about & spending lots of time fixing memory leaks and crashes and stability issues. it would be so nice if the language provided more powerful tools for preventing these things.” (@jarredsumner)

How they did it surprised me even more. About 50 Claude Code workflows running in a loop ported 535,496 lines of Zig to Rust in 11 days, with every line reviewed by two adversarial Claude reviewers. It cost roughly $165,000 of tokens at API pricing, and no test was skipped or deleted. Jarred’s estimate for doing it by hand: three engineers with full context, for about a year.

The 1.4 release notes cover everything since 1.3.0: over 2,900 issues fixed, seven core modules passing 97% of Node’s own tests, 13–48% less memory for HTTP servers, and a hello.js that starts in 5.1 ms on Linux versus 27.2 ms on Node 26 (Bun’s own benchmarks).

Chart of Bun's Node.js test suite progress: about 1,380 test files at v1.2.0, a plateau around 2,250 through v1.3, then a spike to 3,188 on main in July 2026, with a target of 3,693 to ship v1.4
Node.js test-suite files passing, run on every commit. The flat line is the Zig era, the spike is the Rust port. Chart by the Bun team (@bunjavascript on X, July 22, 2026).
Table of peak memory usage in Bun 1.4 versus 1.3.14 across HTTP servers, build/lint/format tasks and bun install, showing reductions from 6.7% to 48.6%
Peak RSS, Bun 1.4 vs 1.3.14, Linux x64, measured before the release. Chart by the Bun team (@bunjavascript on X, July 14, 2026).

There’s a side effect I didn’t expect. A couple of weeks ago, a multi-gigabyte upload OOM-killed one of my services, and the trail led into Bun’s native S3 client. I’m not a Rust developer, but out of curiosity I opened Bun’s source and tracked the bug down. A codebase split into ~100 crates, with a compiler that tells you exactly what’s wrong, turned out to be approachable in a way I don’t think half a million lines of Zig would have been for me.

Why I love it

DX is the bottleneck now

We’re in the agentic era. As I wrote before, Claude writes a lot of my code now, and it writes it fast. What it can’t speed up is the loop around the code: install, lint, format, typecheck, test, build. An agent runs that loop dozens of times per session, so every second in it gets multiplied.

That’s where Bun’s “one fast binary for everything” philosophy pays off, together with the rest of the native-speed toolchain:

  • Tests: bun test with zero config. Glowo’s API runs 4,645 unit tests plus 1,628 integration and e2e tests on every pipeline.
  • Installs: when CI restores node_modules from its cache, a frozen bun install checks Glowo’s 1,550 packages in about 50 ms.
  • Lint & format: oxlint and oxfmt, which I moved to from Biome earlier this year.

And Bun keeps adding more of these tools. Jarred posted this last week:

Today, Bun is a:

  • Node-compatible JavaScript runtime
  • npm-compatible package manager
  • jest-compatible test runner
  • esbuild-compatible bundler

Next week, Bun gets 3 more tools on that list.

(@jarredsumner, October 8, 2026)

You can already see all three. bun check, a built-in TypeScript type checker, shipped in 1.4.3 over the weekend (more on it below).

bun fmt and bun lint landed on canary this week. They don’t pull in oxc as a dependency, but they owe it a lot: Bun ported oxc’s JavaScript and TypeScript formatter and many of oxlint’s rules, along with large parts of Prettier and ESLint, onto the parser behind bun check. They read your existing oxlint/ESLint and oxfmt/Prettier configs and aim to print exactly what those tools print. Since I’m already on oxc, switching should be easy.

bun fmt benchmark: 0.43 seconds to check microsoft/vscode versus 0.85 s for oxfmt, 3.6 s for Biome and 139 s for Prettier; supports 20 languages and passes 99% of Prettier's tests
bun fmt --check on microsoft/vscode (10,148 files, 8 cores). Chart by the Bun team (@bunjavascript on X, October 13, 2026).

Fewer dependencies to maintain

Day to day, the built-ins are what I like the most. Each one is a dependency, a container or a sidecar I don’t have to maintain anymore:

  • Bun.s3: Glowo’s database backups used to shell out to an aws-cli container. Now uploads and downloads go through Bun’s native client.
  • Bun.password: bcrypt/argon2 hashing with no native addon to compile.
  • Bun.Image (added in 1.3.14): replaced sharp in my PDF service. One less native dependency fighting musl.
  • bun:sqlite, Bun.sql, Bun.$, Bun.randomUUIDv7(), Bun.Glob, Bun.YAML… the small stuff that adds up.

NestJS just runs (from source)

Glowo’s and my streaming service’s APIs run NestJS straight from TypeScript source, no build step: CMD ["bun", "src/main.ts"] in the Dockerfile (Glowo adds a --preload for OpenTelemetry), and that’s it. I covered the Nest side of this in my NestJS v12 article, where Kamil himself confirmed “AFAIK bun is already supported”. Fastify, BullMQ, Kysely, better-auth, Zod: nearly everything I’ve thrown at it just works.

One codebase, six native binaries

This is my favorite. The Varsafe CLI is a NestJS + nest-commander app, and it ships as six self-contained binaries (Linux x64/arm64 in glibc and musl flavors, macOS x64/arm64) from a single Bun.build call per target:

await Bun.build({
  entrypoints: ["./src/bootstrap.ts"],
  target: "bun",
  minify: true,
  compile: {
    target: "bun-linux-arm64-musl",
    outfile: "dist/varsafe-linux-arm64-musl",
    // a CLI that holds credentials should not pick up the .env / bunfig.toml
    // of whatever directory it happens to run in
    autoloadDotenv: false,
    autoloadBunfig: false,
  },
});

Cross-compiled from one CI job, no toolchain per platform. One lesson learned the hard way: don’t run UPX on a Bun-compiled binary, it destroys the embedded JavaScript. Node has single executable applications too, but they’re still marked “active development”. With Bun it has been reliable for a long time, which is what I want from my release pipeline.

Where it still bites

It’s not perfect, though. Under Bun, OpenTelemetry’s auto-instrumentation only works for libraries loaded with require(). On Node, import is covered by an ESM loader hook, but Bun doesn’t actually install that hook, so ESM imports silently go uninstrumented (a native Bun.otel is in the works). I still hit the occasional behavioral difference from Node in edge cases. And Platformatic published a benchmark showing ugly tail latency for Bun on Next.js SSR. It predates 1.4 and it’s a vendor benchmark, but it’s a good reminder to measure your own workload. Most of the time it just works, but not always.

The runtime landscape, October 2026

Deno is joining Cloudflare

On October 9, Ryan Dahl announced that the entire Deno team is joining Cloudflare (TechCrunch calls it an acquisition). The Deno runtime gets one more year of monthly bugfix and security releases, then the team stops developing it (it stays open source). Deno Deploy shuts down in six months, JSR continues on Cloudflare’s infrastructure, and the team will work on merging workerd and Deno’s celld to make self-hosting workerd a first-class option.

The line that stuck with me is from Ryan on Hacker News, quoted by Simon Willison: Deno got “sucked into the gravity well of node compatibility”. Deno started as a clean break from Node and spent years being pulled back toward it, because that’s where the packages and the users are. Respect to the Deno team, though: permissions, web-standard APIs and first-class TypeScript pushed the entire ecosystem forward, Node included.

With Astro (which runs this blog) and VoidZero (Vite, Vitest, Rolldown, oxc) also joining Cloudflare this year, JavaScript tooling is consolidating fast.

Node.js got a lot better

I still use Node professionally, and I want to give it full credit: the last three years have been great.

A lot of this is stuff Bun or Deno shipped first. I think the competition helped, and everyone benefits from it.

Platformatic and Watt

In the Node/V8 world, Platformatic, co-founded by Matteo Collina (its CTO, a Node TSC member and Fastify’s lead maintainer), is doing some of the most interesting work. Watt, their “Node.js application server”, runs several apps as worker threads listening on the same port, and they claim 93% lower median latency for Next.js on Kubernetes versus PM2. They also ship node-caged, a Node build with V8 pointer compression turned on (the V8 work is Igalia’s, sponsored by Cloudflare), which roughly halved memory in their benchmarks. It’s not in official Node builds yet. Watt is on my list to try with real traffic.

Nub: Bun’s DX, on stock Node

The newcomer I find most telling is Nub, from Colin McDonnell (the creator of Zod): a Rust all-in-one toolkit (script runner, package manager, Node version manager) that runs TypeScript on the stock node binary, with no Nub-specific APIs on purpose. Basically Bun’s DX without leaving Node. Even if it doesn’t take off, it shows that people who want to stay on Node now expect the kind of DX Bun offers.

Where I think this converges

With Deno winding down as a standalone runtime, we’re left with two major general-purpose server runtimes. Node keeps adding Bun-style DX, and Bun keeps getting closer to full Node compatibility.

The big difference left is how they’re built. Node is a foundation-governed runtime with an ecosystem of tools around it. Bun is one integrated toolchain, owned by a well-funded company with a major product (Claude Code) that depends on it. I expect Node to stay the safe choice for enterprises for a long time, and that’s fine. But when I start something new, I reach for Bun, and I think more people will too.

What I’m watching

Bun AOT

Two weeks ago Jarred posted an early preview of Bun + JavaScriptCore with ahead-of-time compilation. On Claude Code’s CLI, with the JIT turned off: 24% faster to interactive, 48% less memory, 46% less CPU, for a binary almost twice as big. It’s still an open draft PR on Bun’s WebKit fork and the Bun side isn’t public yet. These numbers come from a macOS arm64 prototype. But for CLIs like Varsafe, where startup time and memory are the user experience, I’m watching this closely.

Bun AoT versus Bun JIT on Claude Code: time to interactive 165 vs 216 ms, CPU time 395 vs 738 ms, peak memory 101 vs 194 MB, executable size 430 vs 229 MB
Early prototype, macOS arm64, Claude Code's CLI over the same 5-turn session. Chart by Jarred Sumner (@jarredsumner on X, September 29, 2026).

Tov

Tov, from Richie McIlroy (founder of Cap), is a TypeScript-shaped language built for coding agents that compiles to native binaries. There’s no any, no null and no ==, and tov check --json returns machine-applicable fixes so an agent can correct itself. Bun and Node APIs and npm packages still work. It’s v0.0.1 and two weeks old, but I expect to see a lot more languages designed for agents rather than humans.

The type checker race

Type checking suddenly has a lot of competition. TypeScript 7, the Go port (tsgo), went GA in July, and Microsoft reports 8–12x faster full builds. On Varsafe, typecheck went from ~6.5 s to ~2.2 s when I switched to the preview back in February. And in the past week, two challengers showed up claiming to beat it:

  • bun check, built into Bun since 1.4.3: a port of typescript-go that passes 100% of TypeScript 7.0.2’s conformance suite and claims 3x to 6.4x faster than tsc 7 with 2.2x to 4.9x less memory. It’s check-only (no .d.ts emit, no language server), so your editor keeps using TypeScript.
  • tsc-rs, released last week by Theo Browne: an experimental Rust port of the TypeScript 7 compiler, language server included, claiming type checking in about half of tsgo’s time. Its README is a story in itself: roughly $400k spent on OpenAI models never got past ~84% compatibility, then Claude Opus 5.5 did a fresh port for about $24k in two weeks.

Both are days old, so I won’t call a winner. But Bun’s angle fits my workflow best: no extra package, same binary, and bun test --check collapses two pre-commit steps into one.

Bun’s 11-day Rust port and tsc-rs both point to the same thing: porting a huge, well-tested codebase to another language has become much cheaper, because the test suite works as a spec an agent can port against. I suspect that changes which “rewrite it in X” ideas are worth trying, and the JavaScript toolchain is where I’m seeing it first.

Closing thoughts

It wasn’t one benchmark that won me over. It was a lot of small things adding up: a package manager that was fast from day one, a runtime that kept getting closer to Node, built-ins that removed dependencies, binaries that made my CLI easy to ship, and finally a Rust rewrite that fixed the last thing I worried about, stability.

And the ecosystem around it has rarely moved this fast. It’s a great time to be a TypeScript developer.

Bun 1.5 is scheduled to ship tomorrow. I’ll be bumping the pin again.

Sources

Bun

Ecosystem

Images

All charts are by the Bun team and Jarred Sumner, reproduced with credit and linked to the original posts: monthly downloads, Node.js test suite progress, Bun 1.4 memory, bun fmt (all @bunjavascript), and Bun AoT vs JIT (@jarredsumner). The Bun logo is a trademark of Oven.