Node.js vs Deno vs Bun: Benchmark for a real-world case — JWT, Postgres, PDF gen

Mayank C
Tech Tonic

--

In this article, we’ll write & benchmark a real-world app in Node.js, Deno, and Bun. The app is something like this:

  • Verify JWT from authorization header & get user email
  • Query Postgres and get the user record
  • Create a PDF from user record

This app is a blend of I/O intensive work (reading from DB), and CPU intensive work (Generating PDF).

Let’s get started.

Test setup

All tests are executed on MacBook Pro M2 with 16G RAM and 8+4 cores. The load tester is a modified version of Bombardier that can send a different JWT is each request.

The software versions are:

  • Node.js v21.6.2
  • Deno v1.40.5
  • Bun v1.0.27

For each runtime, I’ve chosen the fastest & stable web framework available:

  • Fastify for Node app
  • Hono for Deno app
  • Elysia for Bun app

I’ve not chosen HyperExpress for Node because I’m not aware of the production grade quality of HyperExpress. Fastify is a fairly old, battle tested, & reliable framework.

On the database front, 100K user records are preloaded in Postgres database:

testdb=# select count(*) from users;
count
-------
99999

For the communication with database, I’ve used Sequelize ORM.

At the end, a PDF is sent in the HTTP response. For PDF generation, I’ve used pdf-lib package from NPM. The generated PDF is like this:

Application

The application code is partly different & partly shared across Node.js, Deno, and Bun. The controller code is different, while the auth, database, and pdf service code is the same.

The structure is as follows:

As the name indicates, fastifyMain & fastifyController are for Node app, honoMain & honoController are for Deno app, and elysiaMain & elysiaController are for Bun app.

The complete code is as follows:

Again, this real world app is a blend of CPU intensive and I/O intensive work.

Results

Each test of 10, and 100 concurrent connections is executed for 100K requests. The results are as follows:

Verdict

This was a real-world case with many things happening in the application: Verify JWT, read database record, generate PDF.

For such a real-world case, Bun turns out to be the winner in all aspects. The Bun app is able to process 37% more requests compared to Node.js app, and 10% more requests compared to Deno app. While achieving this, Bun’s resource usage stays lower. The CPU usage is slightly higher than Node.js, while the memory usage is about half of Node.js.

Winner: Bun

Thanks for reading this article!

--

--