DEV Community

Cover image for Why using Bun in production (maybe) isn't the best idea
Wojciech Maj
Wojciech Maj

Posted on

Why using Bun in production (maybe) isn't the best idea

Bun deserves credit. It's fast, ambitious, and it shook a JavaScript ecosystem that had once been stagnating. The pace of exciting innovations sped up significantly after Bun showed what an integrated experience could feel like. Node.js, once conservative to a fault, suddenly delivered: native TypeScript support, fetch in core, built-in watch mode, an official test runner, .env support. Bun lit the fire, and the whole ecosystem got warmer.

That's a win for everyone. But production is where optimism meets entropy.

“Be everything” or “be sustainable”?

When Bun 1.0 launched, the pitch wasn't just “another runtime”. It aimed to replace Node itself and a half-dozen tools around it: npx, dotenv, cross-env, nodemon, pm2, ws, node-fetch/isomorphic-fetch, tsc, Babel, ts-node, tsx. At the time, that all-in-one story felt like the future.

Two years later, many of those headline features landed in Node. The parts Node didn't absorb (bundling, package management, etc.) are arguably better left in userland, where specialization and rapid iteration thrive (think: Rolldown or LightningCSS). Not everything should be integrated into one runtime, because, respectfully, no single team can possibly excel at everything at once.

Performance: it's fast, but…

Bun's launch aura was speed. While their obsession for performance still stands and continues to push the industry forward, some of the charts they advertised Bun with were questionable from the start - like comparing against Yarn v1 when Yarn v3 was already available. Worse yet, the same charts are still featured prominently two years later.

Other headline numbers often lack context. Take “Bun is 5× faster than Vitest”. Sounds impressive, until you note that Vitest and Jest deliberately add overhead for test isolation, making tests way more deterministic and debuggable. It's part of the reason why Jest even earned its crown back in the Mocha days.

Ignoring those trade-offs doesn't inform; it misleads. At best, it's incomplete. At worst, dishonest marketing.

Meanwhile, the rest of the ecosystem didn't stand still. Node, npm, pnpm, Vitest, and others, all continue to improve. On top of that, community initiatives (e.g., e18e) are driving performance wins across the entire ecosystem, not just Bun.

Portability & lock-in: easy to start, hard to stop

Bun ships non-standard APIs that may feel great on day one - but quietly tether you to Bun itself. It's tempting to bun init, bun test, and lean on helpers like Bun.file, Bun.serve, and Bun.YAML.stringify. Migrating away later if something goes south? Good luck.

Consider the long-standing “Support Vitest” request. It was opened before Bun 1.0 and remains open today. If you want to have a go with Bun seriously, you're effectively pushed into using Bun's own test runner. That seems convenient, until you want to move back to Node or another runtime and face an tedious migration.

Versioning & stability: version numbers are a contract

After announcing 1.0, Bun shipped dozens of 1.0.x releases that included new features - not just bug fixes - attempting to keep 1.1 for the elephant in the room - Windows support.

That simply isn't how semantic versioning works; it's closer to the internet-famous “pride versioning” joke:

PROUD.DEFAULT.SHAME
PROUD for changes you're proud of, DEFAULT for routine releases, SHAME for fixes you hope nobody notices.

If patch releases include new features, what stops them from releasing a minor release from shipping breaking changes? We don't need to wonder, because that's EXACTLY what happened already!
For example, Bun 1.1 changed the default NODE_ENV value, changed the way conditional exports are resolved, and 1.1.26 changed idleTimeout in node:http.

For production teams, version numbers are a contract. They signal when it's safe to upgrade and when to brace for impact. If those signals can't be trusted, upgrades become roulette.

Contrast with Node: today, Node ships fast on current releases, so you can try new features quickly. But there's also the battle-tested, super-stable LTS line (that still receives some of the cool stuff from time to time!), and that dual model is critical. You can experiment at the edge, but when you need reliability, the LTS cadence gives you exactly that. That balance is what makes Node production-ready.

Questionable design choices

  • JSONC in package.json: comments are handy, but making package.json not JSON breaks compatibility with every other tool. That's fragmentation, not progress.

  • Binary lockfile: Bun originally shipped a binary lockfile that made PR reviews opaque - a dream scenario for anyone trying to sneak malicious code through. It later switched to text, but the format remains far less readable than pnpm or Yarn. Hard-to-audit lockfiles weaken security culture.

  • Lifecycle scripts: Bun doesn't run them by default (which partially explains its “faster installs” - less work is being done). Skipping scripts by default is a fantastic idea that greatly improves ecosystem safety, and for this reason other package managers quickly adopted it as well. The problem lies in the details: Bun maintains an arbitrary allowlist of “popular packages” whose scripts do run. If you're listed, your postinstall executes - great for you (or… for someone who compromised your npm account). If you're not, Bun users will need to run extra steps to make your package work. That's a perfect mix of no actual security and no actual convenience.

YOLO-driven roadmap & disregard for neighbors

Bun often feels like it ships whatever won last week's Twitter poll.

The speed Bun ships these features with can be intoxicating, but it also leads to overreach: a made-up tsconfig.json flag, jsxSideEffects, was added in Bun 1.2.22. Think about it: this flag was dropped into TypeScript's namespace by a project other than TypeScript itself. If the TS team ever wanted to actually add that flag, confusion and breaking changes are inevitable.

This also reminds me of the LightningCSS controversy where instead of collaborating with the existing Rust project, whose author even provided C bindings and offered support, Bun ported it to Zig and keeps a separate copy (did I mention something about userland and sustainability? I thought so…).

That's not collaboration - that's duplication without reciprocity. Whatever the license permits, ethics and ecosystem trust matter.

It paints a picture of a project more interested in going its own way than building alongside the wider community, and that's not the kind of foundation I would advise to rest production systems on.

Maintenance signals: issue trackers don't lie

As of today, Node - the runtime powering practically the entire planet, including your toothbrush, probably - carries about 1.7k open issues. Bun, much younger and - while popular - considerably far less adopted, has around 4.7k. Raw numbers are never telling us the full story, but the imbalance is striking. Node shoulders a global workload and yet manages a far leaner backlog. Bun, still in its infancy, is already swamped. That doesn't exactly inspire confidence for production workloads.

When would I use Bun?

This isn't “never use Bun.” It's “use it wisely.”

Good fits:

  • Prototypes and playgrounds where the integrated DX speeds you up.
  • Single-purpose CLIs or scripts where portability isn't critical.
  • Projects in which performance matters more than anything else.

Guardrails if you adopt it:

  • Stick to standards; isolate Bun specifics.
  • Prefer portable tooling.
  • Pin versions, read changelogs carefully, and test upgrades like you would a database migration.

What Bun could do to earn a production seat

  • Treat semver as a contract; features in minors, breakages in majors.
  • Establish a clear LTS and release schedule so teams know what's safe to adopt.
  • Make benchmarks honest: compare like with like, explain trade-offs.
  • Prefer collaboration over duplication: contribute upstream, coordinate publicly.
  • Ship new features with a thoughtful, ecosystem-aware process.

Bottom line

Production depends on sustainability, predictability, and trust. Right now, Bun's design choices, versioning, and marketing weaken those foundations. If these matter to you, think twice before building on Bun today.

But don't get me wrong: Bun made the ecosystem better simply by existing. It reminded everyone what great DX can feel like, and it jolted Node into shipping long-awaited features. And it continues to do so! I'm genuinely thankful for that.

Top comments (0)