Each framework serves the server-rendered table route over a real local HTTP
server
The measured route is /server-side-rendered, using the same
1000-row UUID table as the SSR request throughput and browser rendering
tests
Load is applied in staged connection counts, from 1 through 200 concurrent
connections, with each stage running for approximately 5 seconds
Peak requests/sec is the highest successful stage throughput observed during
the staged run
P90 and P99 latency are compared at the 25-, 50-, and 100-connection stages
for every framework, so latency is measured under the same concurrency
pressure
Total requests cover the full staged load run, not only the peak stage
Astro, Nuxt, and SvelteKit handle Node.js HTTP requests natively. React
Router, SolidStart, and TanStack Start use Web APIs internally, so
benchmarks include the cost of their Node.js adapter layers (@react-router/node, h3, and srvx respectively)
Next.js defaults to React Server Components (RSC), a different rendering
model than traditional server-rendered React. To keep the comparison fair,
Next.js uses "use client" to opt out of RSC and use traditional server
rendering + hydration like most of the other frameworks
Each framework renders a table of 1000 rows with two UUID columns
Measured using Lighthouse flow with Chromium via Puppeteer for accurate
browser metrics
First Paint and First Contentful Paint are measured on initial navigation
Interaction to Next Paint is measured by clicking the first row's detail
link
Benchmarks run 5 times and results are averaged
Next.js, TanStack Start, and React Router default to SSR with no per-route
opt-out. Next.js wraps the client-side rendered table in a dynamic import with ssr: false to prevent build-time prerendering. TanStack
Start uses its built-in spa mode. React Router disables SSR entirely via ssr: false in its config. All other frameworks (Nuxt, SvelteKit, SolidStart, Astro) disable
SSR per-route without a separate build.