After the last Node.js benchmark, readers asked for an application-style benchmark too. The old action benchmarks were useful, but they did not show what happens when Node is serving requests, parsing JSON, updating state, doing compute work, and running for a while.
With Node.js 26 released, we benchmarked recent Node 24, 25, and 26 builds again. This version keeps the action-benchmark style from the original post and adds a sustained synthetic app run.
Versions tested
24.15.0, 25.9.0, 26.2.0
Synthetic application benchmark
The synthetic app is a dependency-free HTTP service with an in-process load driver. The metrics include both the server work and the request driver work in the same Node process. Each run used the same request mix:
- 10% health checks
- 30% reads from an in-memory record map
- 25% writes with JSON parsing and record updates
- 25% compute requests with 200 SHA-256 iterations over a 4 KiB payload
- 10% report requests that summarize app state
The app keeps a 64 MiB target data set, uses 4 KiB records, and runs with 32 concurrency. The run is intentionally not a maximum-throughput race: it is fixed at 50 requests per second so tail latency and memory behavior are easier to compare across versions.
Synthetic app p95 latency
For request latency, this post uses p95 only. That keeps the comparison focused on one tail-latency signal instead of stacking several percentile lines into the same chart.
Peak memory during the app run
Peak RSS is the clearest memory signal from the one-hour app run. Node 26.2.0 used the least peak memory in this workload.
Synthetic app memory over time
This chart uses one-minute points selected from the recorded 5-second process samples. It shows sustained RSS during the load window, while the previous chart shows the maximum observed RSS. During the steady part of the run, all three versions climb in similar steps.
Synthetic app CPU over time
CPU is shown as percent of one CPU core. Because this benchmark is fixed at 50 requests per second, the useful signal is stability and runtime efficiency rather than maximum CPU saturation. All three versions stay close throughout the run.
Targeted action benchmark
The additional action benchmarks keep the structure of the original Node benchmark: one small operation, repeated enough times to compare runtime throughput. Each chart uses median throughput from 10 repeats.
HTTP GET throughput
How many requests per second Node can handle in a simple localhost HTTP server with keep-alive and 32 concurrent requests.
JSON.parse speed
Measures how fast Node can parse a small JSON payload.
JSON.stringify speed
How fast Node can serialize a small object into JSON.
SHA-256 hashing
Hashing throughput using crypto.createHash("sha256").
Buffer copy (64 KB)
Memory throughput when copying a 64 KB buffer using Buffer.copy.
Array map + reduce
A common JavaScript pattern involving array mapping followed by reduction.
String concatenation
Repeated string building using string concatenation.
Integer loop + arithmetic
A tight integer loop performing simple arithmetic operations. This test highlights how efficiently the JavaScript engine executes highly optimized numeric code.
How the tests were performed
Shared setup
Host: Mac mini, Apple M4, 10 cores, 16 GB RAM
OS: macOS 26.3
Synthetic application benchmark
- Synthetic app: 3,600 seconds per Node version, 50 requests per second, 32 concurrency
- Synthetic app timeline charts: one-minute points selected from 5-second process samples
- Synthetic app data: 64 MiB target in-memory data set, 4 KiB payloads
- Synthetic app compute: 200 SHA-256 iterations per compute request
Action benchmarks
- Action benchmark: 10 repeats, 750 ms minimum measurement window, 150 ms warmup
- Action result shown: median throughput in operations per second
- Action benchmark cooldown: 60 seconds between Node versions
Conclusion
The main thing I take from this benchmark is that the recent Node versions are close, but not identical. The synthetic app gives a better picture than a single micro benchmark because it mixes request handling, JSON, memory pressure, and compute in one long run.
I would not pick a runtime version from one chart. If you are running Node 24 or 25 today, the practical next step is to test 26 with your own service and look for the same shape: latency, memory, CPU, and the few hot paths your app actually cares about.