RepoFlow Team · Jan 20, 2026
Node.js 16 to 25 Performance Benchmarks
We benchmarked Node.js 16 through 25 to see what really changed.
We recently benchmarked Express across several Node.js versions and noticed a large performance jump on Node 24. That finding led us to benchmark Node.js itself, running the same Express workload across versions 16 through 25 to see how performance has evolved over time.
All benchmarks in this article were run against the following Node.js versions:
16.0.0, 16.20.2, 17.0.0, 17.9.1, 18.0.0, 18.20.8, 19.0.0, 19.9.0, 20.0.0, 20.20.0, 21.0.0, 21.7.3, 22.0.0, 22.22.0, 23.0.0, 23.11.1, 24.0.0, 24.13.0, 25.0.0, 25.3.0
This includes both LTS and non-LTS releases to show the full performance trajectory rather than isolated snapshots.
16.0.0, 16.20.2, 17.0.0, 17.9.1, 18.0.0, 18.20.8, 19.0.0, 19.9.0, 20.0.0, 20.20.0, 21.0.0, 21.7.3, 22.0.0, 22.22.0, 23.0.0, 23.11.1, 24.0.0, 24.13.0, 25.0.0, 25.3.0
This includes both LTS and non-LTS releases to show the full performance trajectory rather than isolated snapshots.
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.
Integer loop with randomized input
To validate the unusually large performance increase observed in Node 25 for the integer loop, we ran a second version of the test that introduces randomness into the loop using
This makes the computation data-dependent and significantly harder for the engine to aggressively optimize, helping distinguish genuine runtime improvements from optimizations that only apply to highly predictable code.
Math.random().This makes the computation data-dependent and significantly harder for the engine to aggressively optimize, helping distinguish genuine runtime improvements from optimizations that only apply to highly predictable code.
How the Tests Were Performed
Each test was run five times, with results reported as median (p50) throughput. The system was allowed to cool down between runs to avoid thermal bias.
- Hardware: Apple M4, 10 cores, macOS 25.0.0 (arm64)
- Tooling: Custom Node.js benchmark harness, no external frameworks involved
Conclusion
Node.js performance continues to improve steadily across releases, but Node 25 stands out, particularly for numeric and loop-heavy workloads.
Not every application will see dramatic gains, but workloads involving tight loops, computation heavy logic, or transformation pipelines can benefit meaningfully from newer Node versions.
As always, synthetic benchmarks represent best-case scenarios. Real world performance depends on I/O, memory access patterns, and application structure. Still, these results clearly show that recent Node releases deliver tangible runtime-level improvements.
Let us know which benchmark you’d like to see next !
Not every application will see dramatic gains, but workloads involving tight loops, computation heavy logic, or transformation pipelines can benefit meaningfully from newer Node versions.
As always, synthetic benchmarks represent best-case scenarios. Real world performance depends on I/O, memory access patterns, and application structure. Still, these results clearly show that recent Node releases deliver tangible runtime-level improvements.
Let us know which benchmark you’d like to see next !
