DEV Community

Gabriel Morishita
Gabriel Morishita

Posted on

NestJS: Bun vs NodeJS

What is Bun?

Bun JS or Bun Sh is an all-in-one toolkit for JavaScript and TypeScript, it offers a powerful toolkit with its CLI, it is currently available for Linux, MacOS and WSL users. To install it, run:

curl -fsSL https://bun.sh/install | bash

To see more of what Bun is and what it can do, check the official documentation.

Why doing that?

We all know that NodeJS deals with it pretty well, but Bun is a really promising deal, so why not?? We programmers love to test and see what happens, especially to try out new things!

Getting started

So now that we've got our bun CLI up and running, lets use nest CLI to generate two separate projects. They will be fully installed, built and run using both npm and bun so we can see the difference on first hand.

Note: all the benchmarking will be tested with wrk using Arch Linux x86_64 environment.

1. Dependency Install

After "nest newing" both projects, its time to see the first feature available on Bun, which is the package manager.

npm install
bun install

We can already see some improvement here! Bun install is blasting fast and wins the first challenge.

2. Development Server

We can't ignore the fact that a good development experience is a must have when it comes to frameworks. As both Bun and Node supports runtimes such as 'npm run start' we will have to see which one is the best when it comes to developing on real time. At the moment, NestJS is not using Bun.serve() to create a web server, so the comparisons we are making are all with the default NestJS provider.

Let's run both projects on different ports. Bun will be running on 3333 and Node will run on 4444 so we can easily see them acting.
Servers up

Without any change, let's compare them with wrk. Note: we are not running them concurrently at the same time, which means that the following results were achieved with all the computational power dedicated to one and only one test at a time.

http tests on dev server

We can see that Bun not only handles more requests per second (almost 2.4K requests more) but it has an average latency 30ms faster. This one is a solid win for Bun.

But this section ain't over, we still have something ALL developers love, and this is hot-reload. To enable hot-reload on NestJS using node, we need a service like nodemon to do that for us. Meanwhile on Bun we have the --watch arg that can be passed on bun start command. We have yet another type of hot-reload on Bun natively! But the watch key runs on file changes (which is the best for real time developers)

Bun hot reloader

Our little Chinese bread Bun is now 2x0 against the big guy NodeJS.

3. Testing

As we are too busy to write them from scratch, I guess we are going with the auto-generated test files from NestJS.

Test runners

WOOOOW, it seems NodeJS won't throw away the towel. Unlike the http requests battle, this one is by such a small difference that we don't feel comfortable using it. Our tiebreaker was expected to be the native test modules, but both NodeJS and Bun are loaded with a test runner, and as we are only considering Jest results, NodeJS can take this one and make it a 2x1 difference for Bun.

4. Build and deployment

Let's now build our giant Hello World NestJS application and see how it performs on raw using both "node dist/main.js" and "bun run dist/main.js" as well as the build time.

Build time

And another tiny difference on our comparison, only 500ms difference for Bun! This tiny differences can be justified by the fact that we are testing such a small project. It is worth mentioning though that this is not over! We still need to compare performance running compiled projects.

Builds running

When in doubt, benchmark it out!

http tests on build

And again a solid one for Bun, it's worth noticing that when dealing with compiled NestJS, Bun handles almost 10 thousand requests more then when running it on a development server, holly cow!

Also, we can now compare the development server and build server on both Node and Bun. While Bun cut the average latency by half and more then double requests per second. Node also shows some better results by reducing latency and passing Bun on max requests per second by almost 1k.

In general, Node performance is pretty decent, meanwhile Bun is just stunningly powerful. This was a really great test but Bun takes it on 3x1.

Conclusion

Overall, Bun can be really great on performance and deliver some amazing results. But we can't forget that it is currently on it's first version and can be very unstable on production, that's why I wouldn't recommend trading NodeJS by Bun on bigger projects. NodeJS is still the most reliable and trusted runtime environment to deal with JavaScript applications. However, Bun seems to be getting closer every step to take Node's crown. I was able to watch the early development of Bun since 0.3, times when running bun install would result on a segfault. Being able to see it grow it's own community and compete with giants like NodeJS is so nice.

Thanks for reading it, feel free to share your thoughts!!

Top comments (9)

Collapse
 
mihail profile image
mihail • Edited

I "feel free to share your " facts : 😂

dude, if you run bun start, it runs nest cli that uses node 😂,

you made node vs node test 😁

the only "real" test you made was running node dist/main vs bun dist/main 😇

relevant: github.com/oven-sh/bun/issues/3417 (dig further from there 😇)

use --bun flag after bun cmd in order to really use bun (here some ref:bun.sh/guides/ecosystem/vite)

Collapse
 
sfabruz profile image
sfabruz

Can you explain this?
Is it for the shebang at the beginning of the file inside the path "node_modules/@nestjs/cli/bin/nest.js"?
I mean, I tried to install bun and nestjs in an environment without nodejs, launching "bun start" it launches "nest start" under the hood, and it prints it in the console, but with bun not with nodejs.
So in an mixed environment how do I know which runtime nest is using? I'm not convinced that the test the author made is wrong because the test results are very different from each other and that cannot be "nodejs vs nodejs".
But you put a doubt in my mind :D

Collapse
 
mihail profile image
mihail

for the not so technical stuff:
"very different" in which form?
run the same using only node and you'll may see the same spread between tests (besides the install part, bun is fking fast), 100ms - 2 sec spread (depending on test) is irrelevant and may be generated by the system itself 🤷‍♂️, idk
"the test the author made is wrong", no is not, he just didn't care about the thing that he runs node twice 😂

for the technical stuff :
yes, you're right " I tried to install bun and nestjs in an environment without nodejs", I tried that too, it works 👍 (don't know how/why, ask the bun devs for more info)
(fount this medium.com/@greentransportation/wh... ) and the docs say "By default, Bun respects this shebang and executes the script with node" (bun.sh/docs/cli/run#bun)

simply put "#!/usr/bin/env node" on first line of any js file and it is an executable (at least on unix like systems Mac/linux as far as I know, it may work in win powershell too ), remove (or not) the .js extension and run it with bash.

when you run any of the files containing "#!/usr/bin/env node" if you use "bun --bun" it will replace the shebang with the bun specific one "#!/usr/bin/env bun" (not legit string, just for the sake of example)

for more read the docs or pm the author idk

Thread Thread
 
sfabruz profile image
sfabruz

I didn't know that bun respect the shebang it found inside the file. It's correct, I guess.
I didn't know neither that, with bun, you can override that behaviour with a flag and I'm happy that it has that feature.
I hate shebang inside a software like nestjs because if you want to run nest with another runtime, you have to deal with this kind of issue. Thank you javascript :D
But I understand that software is written over several layers, and those layers must have foundations, like nodejs instead of all kind of runtimes javascript or typescript have.
So, now I understand why the author had test node vs node :D For fix that, he can run "bun run --bun dist/main.js" and leave the rest of the article as it is.
Thanks for pointing this out. I would have wasted hours in the early bun tests before finding these two info shebangs-related.
This is not the first article nor video I see where they show this difference in performance between the two runtimes. although it is the first one I see running with a shebang that falsifies the results :D
That is why they seemed to me quite different and in line with all the other tests
Last but not least, thanks for explain me how a shebang works. Really not necessary :D

Thread Thread
 
mihail profile image
mihail
Collapse
 
ottodevs profile image
Otto

Man this benchmarking is so weak... Testing benchmarking with just 1 helloworld test and with just 1 execution?

For testing improvement an actual tip would be moving from jest to vitest, that has 99.99% same syntax and is well supported by nest... Bun testing is not so much ready yet...

and FYI Nest comes with a --watch flag you don't need nodemon anymore, even Node comes with --watch since v18

Collapse
 
mihail profile image
mihail

remake the test urself with bunx --bun nest cmd (I didn't test it) and you should be able to get some real results, check the other comment about the bun start running the node shebang in Nest CLI 😅

Collapse
 
hakimio profile image
Tomas Rimkus

strager (Matthew Glazar) made a video on YT, showing that bun is not that fast and still quite buggy in real-world applications:

Collapse
 
andrzej_kowal profile image
Andrzej Kowal

Thanks for article. Would be good of course to see heavier application in all of this comparisons, not just the smallest possible example of hello world app.