Node.js vs Deno vs Bun: JSON request & response performance comparison
I’ve done a good number of performance comparisons in the past 2 years. All of those comparisons were good & valid at that time. However, things are changing fast these days. New technologies are coming in (like Bun), and continual better performance is coming out (recent improvements in Deno and Node.js). Going with the fast changing world, the performance comparisons also need redoing to stay relevant. Any comparisons done a year back may be totally outdated now.
In the previous re-looking article, I’ve compared Node.js, Deno, and Bun for simple hello world case. The article can be seen here.
In this article, I’m going to compare Node.js, Deno, and Bun for the JSON request & response. This is relooking at the performance with the recent releases in all the technologies. Let’s see if anything changes this time.
Test Setup
All the tests are executed on MacBook M1 with 16G RAM. The HTTP tester is the well known benchmarking tool called Bombardier. Bombardier is a HTTP(S) benchmarking tool. It is written in Go programming language and uses excellent fasthttp instead of Go’s default net/http library, because of its lightning fast performance. The tester runs the tests with the following levels of concurrency:
- 10 concurrent connections
- 50 concurrent connections
- 100 concurrent connections
- 300 concurrent connections
The software versions are:
- Node.js v19.5.0
- Deno v1.30.0
- Bun v0.5.1
A total of 5M (5 million) requests are executed in each test.
Code
Only native HTTP servers are used in this comparison. No third-party packages or libraries are used.
The following is the JSON request & response processing app in all the four systems. The app receives a simple JSON body containing an array of objects. Names are extracted from the JSON array and sent back in the response as a JSON array of strings.
Node.js
import http from "node:http";
http.createServer(
(req, rsp) => {
let data = "";
req.on("data", (c) => data += c);
req.on("end", () => {
rsp.writeHead(200, {
"Content-Type": "application/json",
});
const reqBody = JSON.parse(data);
const ret = [];
reqBody.forEach((e) => ret.push(e.name));
rsp.end(JSON.stringify(ret));
});
},
).listen(3000);
Deno
Deno.serve(async (req: Request) => {
const reqBody = await req.json();
const ret = [];
reqBody.forEach((e) => ret.push(e.name));
return Response.json(ret);
}, { port: 3000 });
Bun
Bun.serve({
port: 3000,
async fetch(req) {
const reqBody = await req.json();
const ret = [];
reqBody.forEach((e) => ret.push(e.name));
return Response.json(ret);
},
});
With the support of web APIs, the Deno and Bun code looks very similar. The request handler function is exactly the same. Node’s native HTTP server is still the old style callback based server.
Measurements
It’s not only about how fast a system is. A system/runtime can be very fast, but may stall the system by using too much CPU, memory, disk, etc. Some official benchmarks only focus on RPS. The more RPS, the better. Given unlimited resources, this is probably fine. However, for all practical purposes, only RPS doesn’t represent the complete picture. We need to measure latencies, and system usage too. Also, we need to see the response time distribution across different quantiles.
Here is the complete list of measurements:
- 1st quartile (or 25th percentile) latency
- Mean latency
- Median latency
- 3rd quartile (or 75th percentile) latency
- 90th percentile latency
- Maximum latency
- Avg. CPU usage
- Avg. Memory usage
Results
The following are the charts to show the results. There is one bar chart for each measurement metric. All concurrency levels are covered for each metric in the same chart.
All latencies are in microseconds.
My analysis
First, Node.js is very slow in comparison to Deno and Bun. The newer runtimes are between 1 and half to 2 times faster than the market leader, Node.js. Node.js offers about 57K RPS, while Deno goes around 85K and Bun goes around 115K. This is a huge difference. Especially, Node.js to Bun is a big gap.
Second, Bun’s excellent performance comes without hogging system resources. Bun’s CPU & memory usage are the same as others, but performance is much better.
Other articles in performance series are: