01200K Lines
200,000 mounted <p> elements4,026×× requests/sec
This test is meant to stress-test how well both frameworks handle extremely large payloads; as well as how efficiently they scale up. By creating a page with *200 thousand* individual `<p>Stress-Testing.</p>` elements, we effectively scale up every miniscule *bit* of baggage both frameworks accumulate, exposing inefficiencies. At first you may think that something is incorrect with the test data, and so did we. However, the byte size *is actually correct*. The page HTML is roughly 4.2Mb in size, but the out-of-the-box Brotli compression in elegance comresses it down to 185 bytes transferred. Elegance also does not ship a VDOM, nor any other unneeded JavaScript. This page also contains no interactive elements, meaning our JS shipped was a mere few kilobytes. For Next.JS, we were shocked to see that the actual page HTML generated by default was a stagerring *18.1 megabytes*! We suspect this is because Next.JS by default includes a serialized VDOM of sorts, GZIP tries it's best, and to it's credit it actually shrinks the page HTML down to about a megabyte. Developer Notes: I think it's interesting, this page actually *doesn't load* with `npm run dev` on Next.JS. I get an OOM-error and the first-request crashes the entire server. We are also aware this is not hyper-realistic in terms of usage, but it's interesting to note, nevertheless. This page also took almost *2.5 minutes* to compile in Next, whereas in Elegance it took roughly 5.5 seconds.
metricEleganceNext.JSratio
Requests / sec40,260104,026× more
Average latency1.24 ms5.57 s4,494× lower
p99 latency2.36 ms8.54 s3,622× lower
Transferred / request185 B1.03 MB5,571× less
Success rate100.00%100.00%
200K Linesresults/200k-lines/test.md // Elegance and Next.JS: /pages/page.tsx export default function page() { return <div> <h1>Stress-Testing.</h1> {/* ... 200 thousand more times ... */} </div> }
02Raw API RPS
one GET endpoint · identical payloads15.5×× requests/sec
This test is meant to measure raw RPS (requests-per-second) by simulating a primitive GET endpoint that returns `{"message": "Hello, World!", }`. Both frameworks return the exact same paylod, so the only factor which affects RPS is raw framework level overhead and optimizations.
metricEleganceNext.JSratio
Requests / sec47,8653,08315.5× more
Average latency1.04 ms16.22 ms15.6× lower
p99 latency2.17 ms23.25 ms10.7× lower
Transferred / request27 B27 Bidentical
Success rate100.00%100.00%
Raw API RPSresults/raw-rps-test/test.md // Elegance: /pages/api/route.ts import type { IncomingMessage, ServerResponse } from "node:http"; export async function GET(req: IncomingMessage, res: ServerResponse) { res.end(JSON.stringify({ message: "Hello, World!", })); } // Next.JS: /pages/api/route.ts export async function GET() { const res = new Response(JSON.stringify({ message: "Hello, World!", })); return res; }
03Hello World
minimal static page8.7×× requests/sec
This test attempts to measure raw RPS (requests-per-second) with a minimal static page. The page code looks as follows: - Prod mode uses -prod flag - Dev mode uses -dev flag - Production mode test uses `output: "standalone"` in `next.config.ts`, and was executed with `node .next/standalone/server.js`.
metricEleganceNext.JSratio
Requests / sec29,7793,4038.7× more
Average latency44.32 ms393.93 ms8.9× lower
p99 latency47.90 ms431.70 ms9.0× lower
Transferred / request145 B1.5 KB10.2× less
Success rate100.00%95.28%
Hello Worldresults/hello-world/test.md // Next.JS & Elegance: /pages/page.tsx export default function page() { return <div> <h1>Hello World!</h1> </div> }
04SSR Test
dynamic page · rendered per request22.6×× requests/sec
This test aims to measure how fast both frameworks can render a dynamic server-rendered page. For next, this involves `force-dynamic` to ensure the result isn't cached. On both pages, we read some request headers, and embed them into the response.
metricEleganceNext.JSratio
Requests / sec17,89679322.6× more
Average latency2.79 ms63.13 ms22.6× lower
p99 latency5.47 ms81.79 ms14.9× lower
Transferred / request324 B1.8 KB5.7× less
Success rate100.00%100.00%
SSR Testresults/ssr-test/test.md // Next.JS: /pages/page.ts import { headers } from 'next/headers' export const dynamic = 'force-dynamic' export default async function page() { const h = await headers() const headerValue = h.get('accept-encoding'); return <div>{headerValue}</div> } // Elegance: /pages/page.ts import type { IncomingMessage, } from "node:http"; export default function page({ req, }: { req: IncomingMessage }) { const headerValue = req.headers["accept-encoding"]; return <div>{headerValue}</div>; } export const isDynamic = true;