My Experience with Bun
I’ve been using Bun for a while now. The first time I’ve heard about it I thought it was cool that it uses JavaScriptCore instead of V8 and that I could use it as a drop-in replacement for npm install
. As a web developer working on Shopify Hydrogen apps, I ended up just staying with the project defaults, which meant npm.
Moving CI to Bun
However, as we added more steps to our CI, like additional lint rules, I noticed the pipeline slowed down significantly. In particular, I observed that our dependent steps spent substantial time on the installation phase. Due to that, a year or so ago I decided to experiment with Bun on our CI for all our steps, including deployment.
I was cautious about breakage, but our weekly release cadence meant changes hit production later, so I tried it on preview deployments first. I think there was even a code freeze at the time, so the release took even longer to really go out and the CI ran for a month or so without any issues.
Therefore, it was not really a surprise that it simply worked once it rolled out. I don’t have the exact numbers, but from what I recall it shaved the install step from about ~60-90s with npm install
to ~20s with bun install
on GitHub shared runners.
Local Development
Although I did move our CI in a few projects to use Bun, I haven’t really used it locally. However, these days I’ve been experimenting with git worktrees and having to run install more frequently became frustrating. I switched to Bun locally and it has been a breeze. I am not really using the lockfile though, as part of the team is still on npm
and I haven’t pushed for a switch yet. The --no-save
option in bun install
has been broken for a while, and so I ended up adding a postinstall to delete it so that it does not interfere with CI in our package.json
:
{
"scripts": {
"postinstall": "rm -f bun.lock 2> /dev/null || true"
}
}
The Technical Deep Dive
I am not really explaining what is behind the scenes on bun install
, you can read this article for that. I just read it today and it was definitely a good read. I’ve become more interested in learning about systems programming and that article has been quite interesting, in particular because I am also following along Operating System in 1,000 Lines and I am starting to get a better grasp of what a syscall really means. When you do a syscall, your program stops and context is switched to the kernel mode. Your program will eventually continue running, so registers need to be saved in memory with the current state for it to be restored later. The Bun team observed that earlier designs optimized for slow disks, but as storage sped up, syscall overhead (especially many small filesystem calls) became the bottleneck. To be fair, npm
does seem to have become better over the years and the biggest culprit these days seems to be yarn
(up to 17x slower in their benchmarks).
Anyway, don’t take my word for it and give the article a read and try Bun. What are your thoughts on it?