When I first heard about the Bun project, I honestly thought it was overambitious to the point of obvious failure. You know the projects I’m talking about – the ones that promise the world but never reach fruition, leaving their early adopters to twist in the wind.
But here we are: Bun 1.0. And by all accounts, the Bun JavaScript runtime has achieved its original goals.
In this article, we’re going to discuss Bun’s features, as well as its history and future. Since the Bun team claims that their product is a drop-in replacement for Node.js, we’ll also examine a non-trivial example of replacing Node.js with Bun in a pre-existing project.
What Is Bun?
Bun is a new JavaScript runtime developed by a company called Oven (yes, really). The mastermind behind the project is Jarred Sumner, although at this point the company appears to have attracted a small team of developers.
On an episode of the PodRocket podcast, Jarred summarized Bun as:
[2:10] …an all-in-one JavaScript Runtime. It combines a bundler, a transpiler, a package manager, a script runner, all-in-one in addition to being a runtime. And so it comes with a TypeScript transpiler, JSX transpiler. And all of this is quite a bit faster than anything that exists today.
How Fast Is Bun?
To be clear, when Jarred says “quite a bit faster”, he means many times faster than other prominent JavaScript runtimes such as Node.js and Deno.
One benchmark on the Bun website compares the HTTP requests per second processed by Bun, deno.serve(), and Node.js. When comparing Bun vs. Node, Bun processed 5x as many requests per second; when comparing Bun vs. Deno, Bun processed 2x as many requests per second.
Another benchmark asserts that yarn install
runs 33x slower than bun install
.
Yet another benchmark asserts that tests in a Jest/Babel configuration would run 20x slower than Bun’s test runner.
Of course, we all know that benchmarks can be misleading. I haven’t personally run the benchmarks provided by Bun, nor have I looked at the code to see if they make sense.
That being said, these claims have been backed up by some third-party testing. On our end, one of our talented software engineers has already looked into Bun and was very impressed with its speed compared to Node.js (more on his experience later).
How Is Bun So Fast?
According to Jarred Sumner, there are really two major contributors to Bun’s comparative speed: (1) use of the JavaScriptCore engine over V8 and (2) use of the Zig language for building the transpiler and runtime.
JavaScriptCore is the JavaScript engine built by Apple for Safari, while V8 is the engine built by Google for Chromium-based web browsers. I can’t speak much to their relative speed, nor have I heard Jarred or the Bun team discuss the benefits of JavaScriptCore in great detail.
The choice to use Zig, on the other hand, seems like a slam dunk for performance. Bun documentation claims the use of Zig results in a 4x faster startup time for Bun vs. Node when running scripts.
Frankly, I hadn’t heard of Zig prior to learning about Bun several months ago. It’s a relatively young language, but seems well-suited to building products like Bun based on Jarred’s statements:
[4:12] Zig is really good for this type of systems programming to do it as quickly as possible while also not going crazy because it's a low level systems' language with manual memory management. By its nature, without garbage collection, things are a little bit harder, but Zig does a really good job of making it easier than it would be otherwise in C.
Is Bun Production Ready?
By releasing version 1.0, the team is declaring that Bun is production ready.
Speaking on the JavaScript Jabber podcast, Jarred stated there are already “companies using it in production” with a “decent amount of traffic in some cases”.
That’s not to say that Bun is flawless. The host of that podcast – which aired May 30, 2023, only three months before 1.0 – mentioned that he had encountered several issues when attempting to use Bun.
Of course, Jarred assured the host that progress was being made on many known issues.
My personal opinion? Bun is ready for production use, so long as you’re willing to tackle the weird compatibility issues and edge cases that inevitably arise when using bleeding edge technology.
So the question really should be: do the pros of adopting Bun outweigh these inconveniences?
Why Should You Switch to Bun?
There are a few benefits to Bun that jump out at me:
- Do you have a giant test suite that takes a long time to run? Adopting Bun will reduce the time to run that test suite, which can save CI/CD dollars and developer time.
- Do you run serverless JavaScript functions? Switching over to Bun will reduce cold start and execution times.
-
Do you like TypeScript and want it to work out-of-the-box? Bun can directly execute
.ts
and.tsx
files with no additional configuration. - Do you want to reduce your dependencies and simplify bundling? Bun can probably help. If you like languages such as Go that have rich standard libraries, Bun brings some of that ethos to the JavaScript world by including its own bundler and package manager.
Aside from directly reducing costs via faster execution time, Bun’s performance has the potential to increase developer productivity. By reducing the amount of time that developers spend waiting on test suites to run, for instance, you also reduce the time needed to iterate on those tests.
And lastly, the improved developer experience of having an all-in-one product shouldn’t be underestimated. How much time have you invested messing with webpack
configurations or troubleshooting a Jest upgrade? Grouping these disparate elements of JavaScript development within a single, batteries-included framework should help mitigate these sorts of problems.
What Is the Future of Bun?
Jarred envisions a future in which Bun facilitates fast server-side JavaScript rendering. This certainly agrees with the recent shift back to server-side rendering, as embodied by the changes introduced in Next.js 13 and the creation of React Server Components.
Jarred discusses this concept in his PodRocket interview:
[7:00] Bun will eventually have a production transpiler API/bundling API. And I think what people will do with that is they will actually bundle and transpile in network requests. And so for that, you need it to be really fast. But the reason why I think people will do that is because it's going to enable a lot of new kinds of plugin systems where you have this dynamic code generation and you do server-side JavaScript rendering. Similarly you do server-side HTML rendering. But if you can embed the data…it'll let people delete a bunch of code.
This use-case for Bun seems supportive of the so-called islands architecture (a phrase popularized most recently by Astro). If you’re unfamiliar with this concept, the main gist is: since web pages are largely static content, only ship JavaScript when and where you need it.
More specifically, I can imagine a scenario in which a user submits data to a server and the server responds by creating data-specific JavaScript which is bundled and sent back to the client as part of an interactive page element.
That sort of client/server interaction ensures you’re only sending the JavaScript you need to the client – and that the JavaScript you send has the smallest footprint possible.
I don’t think the value proposition for this sort of system is lost on Jarred and Bun, either. In his interview with JavaScript Jabber, Jarred mentions that he aims to eventually offer “really fast edge hosting for Javascript specialized cloud” as a commercial product.
And in his PodRocket interview, he also highlights that Oven wants to create a version of Bun specifically for edge computing:
[16:07] …one of the things we'll focus on is specifically [a] version of Bun for the edge. It will have single file deploys. And it'll do this really efficiently because it'll use a binary bundling format to turn it all into one compact file.
So based on these comments, I anticipate we’ll see Oven create something like Deno Deploy for the Bun ecosystem in the not-too-distant future.
Is Bun a Drop-In Replacement for Node.js?
Whenever a new project bills itself as a “drop-in replacement” for an existing tool, I’m immediately suspicious. In my experience, there’s usually some big issue that pops up soon after adopting these sorts of solutions.
Luckily, one of our Gnarnians has already looked into this! Alex Jarvis recently converted his randsum-ts library from Node.js to Bun and generously agreed to share his takeaways from the experience.
Firstly, let’s establish that his library itself isn’t extremely complicated. Alex states that it “has no databases, no HTTP calls, just logic and exhaustively-thorough TypeScript”.
But if you look at the library, I’m sure you’ll quickly notice that it’s a pretty far cry from a “hello, world” application. This is a production-ready, pre-existing project, making it a fantastic opportunity for putting Bun’s “drop-in replacement” claims to the test.
More importantly, this wasn’t just an experiment for Alex. He saw legitimate benefits in Bun and wanted to leverage those benefits in his project:
I have played with a number of different workflows and build scripts –
rollup
,parcel
, straight-uptsc
– and had lost my head a few times working my way aroundcjs
vs.esm
. What I wanted was a little existential stability in my workflow – something to put my back against. When I heard of Bun’s built-in (lightning fast) bundler and saw it operated with first-level TypeScript support, I decided to try my hand at converting from ayarn/node
backed project to being one run onbun
.
If you’ve lived in the JavaScript world for a while, this is probably a familiar sentiment. My hope is Bun helps to smooth out developer experience by avoiding these sorts of headaches.
Replacing Node.js with Bun was fairly straightforward, though Alex mentioned it did involve “a small amount of re-architecturing”. To be fair, I expected that changing the JavaScript runtime for an existing project would be an outright nightmare; his experience seemed positively seamless by comparison.
He did, however, highlight testing as a pain point during adoption:
The biggest headache was the test suite, where a few useful / mission critical things are not yet implemented when compared to the modern
jest
suite (while I can live withoutexpect.arrayContaining
, it is a slightly more annoying existence) With some creative dependency injection and well-architected tests, this was easy to get around.
That said, Alex seemed genuinely impressed with the results once he was done. He stated his test suite and build script ran “instantly” after the switch, which serves as yet more validation of Bun’s impressive performance claims.
Alex additionally pointed out an interesting benefit to Bun’s TypeScript support that hadn’t occurred to me:
There is already a plugin ecosystem developing (making it easy for my
build
script to also spit out ad.ts
file). Being able to REPL one of my TypeScript files natively has really opened up my debugging possibilities.
So is Bun a drop-in replacement for Node.js? I’ll let you come to your own conclusion on that. But from my perspective, Alex’s experience is a solid endorsement of that claim.