Benchmark Results

The following page contains benchmark results for server-side rendering of dynamic pages in Next.js 15.0.4.

The goal of this test is to demonstrate how well the Next.js server can handle a large number of concurrent requests.

If you wish, you can run this test locally by following the instructions in the README.md.

How the Benchmark Works

The benchmark sends concurrent requests to several pages.

Each page renders a list of 10,000 items.

Each page is rendered dynamically for every incoming request.

Route path Served by Description
/next-app-router App Router Server Component Page
/next-pages-router Pages Router Regular Page
/react Custom Server Regular React 19 rendering
/use-client-route App Router Page with use client on top of it

I used two different benchmarking tools to generate concurrent requests:

  1. Apache Benchmark
  2. Artillery

During the test, the Next.js server was run on Node.js v22 inside a Docker container with 2 CPU cores and 2 GB of RAM.

Apache Benchmark Results

During this test, I sent 500 requests in total to each page with a concurrency limit of 50 requests.

Document Path /next-app-router /next-pages-router /react /use-client-route
Document Length 960702 bytes 330067 bytes 328957 bytes 333192 bytes
Concurrency Level 50 50 50 50
Time taken for tests 43.977 seconds 6.965 seconds 2.632 seconds 8.993 seconds
Complete requests 500 500 500 500
Failed requests 0 0 0 0
Total transferred 480508000 bytes 165174500 bytes 164516000 bytes 166753000 bytes
HTML transferred 480351000 bytes 165033500 bytes 164478500 bytes 166596000 bytes
Requests per second 11.37 #/sec 71.79 #/sec 189.99 #/sec 55.60 #/sec
Time per request 87.953 [ms] (mean, across all concurrent requests) 13.930 [ms] (mean, across all concurrent requests) 5.263 [ms] (mean, across all concurrent requests) 17.986 [ms] (mean, across all concurrent requests)
Transfer rate 10670.36 [Kbytes/sec] received 23159.24 [Kbytes/sec] received 61047.68 [Kbytes/sec] received 18107.84 [Kbytes/sec] received
Connection time [ms] min 113 33 10 49
Connection time [ms] mean 4192 658 250 854
Connection time [ms] median 4398 683 253 872
Connection time [ms] max 4620 768 312 1024

Artillery Results

The Artillery test shows the same results but also includes charts.

Route path Sent Requests Received Responses
/next-app-router link link
/next-pages-router link link
/react link link
/use-client-route link link

Conclusion

It appears that pages served by the App Router can handle fewer requests than those served by the Pages Router.

It is also interesting to note that when we add the use client directive to an App Router page, it can handle more requests per second.

I believe there is room for improvement.