Next.js & React

TanStack Start vs Next.js in 2026: Same App, Real Benchmarks

TanStack Start 1.0 is stable, so I built the same store in Start and Next.js 16.4 and benchmarked both. Start served 2.9× to 8.6× more dynamic requests, shipped 20% less JS and built 3.9× faster. Next.js won on static pages.

TanStack Start vs Next.js cover: requests per second for SSR list, product page and API routes, plus build time 1.3 s vs 4.9 s and client JS 109 KB vs 135 KB
On this page
  1. TL;DR: is TanStack Start faster than Next.js?
  2. What is TanStack Start?
  3. How I benchmarked TanStack Start and Next.js
  4. Server performance: how many requests can each handle?
  5. Bundle size, hydration and client navigation
  6. Build time, dev server and deployment
  7. Developer experience: what's different day to day?
  8. Should I switch from Next.js to TanStack Start?
  9. How do I migrate from Next.js to TanStack Start?
  10. Common mistakes when comparing Next.js and TanStack Start
  11. Key takeaways

TanStack Start vs Next.js got a lot more interesting on October 13, 2026, when TanStack Start 1.0 went stable. I built the same small store in both frameworks, with the same routes, data, components and Tailwind styles, and measured them on one machine. TanStack Start served 2.9× more server-rendered list pages, 4.6× more product pages and 8.6× more JSON API calls per second than Next.js 16.4. It also shipped 20% less JavaScript and built 3.9× faster. Next.js still won where it was designed to win: a prerendered page, and a far bigger set of built-in tools.

Here are the numbers, how I got them, and how I'd choose between the two in 2026.

TL;DR: is TanStack Start faster than Next.js?#

On the server, yes, by a wide margin in my tests. Every route that rendered per request was 2.9× to 8.6× faster on TanStack Start, with much lower tail latency. On the client the gap is smaller: 109 KB of gzipped JavaScript against 135 KB, and an interactive button 35 ms sooner on a throttled CPU. Next.js led only on its prerendered home page, because it serves static HTML while Start rendered that page on every request.

Same app, Node 24.22, 2 coresNext.js 16.4.2TanStack Start 1.169.3Difference
Home page, req/s3,220 (static)2,920 (SSR)Next +10%
Product list, 100 items, SSR, req/s220637Start 2.9×
Product page, SSR, req/s5122,341Start 4.6×
JSON API route, req/s2,16518,515Start 8.6×
p99 latency, product list754 ms194 msStart 3.9× lower
Server memory at idle94 MB60 MBStart −36%
Client JS on /products, gzip135 KB, 7 files109 KB, 3 filesStart −20%
Interactive button, 4× CPU throttle324 ms289 msStart −35 ms
Production build4.86 s1.26 sStart 3.9×
Dev server, first page2.96 s1.52 sStart 1.9×
Deploy output38 MB1.4 MBStart 27× smaller

If you mostly ship content that can be cached, these server numbers matter less. If you run a dashboard, an API-heavy app or anything that renders per user, they matter a lot.

What is TanStack Start?#

TanStack Start is a full-stack React framework built on TanStack Router. It adds server-side rendering, streaming, typed server functions, server routes for raw HTTP and middleware, and it builds with Vite (or Rsbuild). The 1.0 announcement calls it ready for production after a long release-candidate phase, and the first stable package was @tanstack/react-start 1.169.0.

The big design difference from Next.js is the component model. In Next.js App Router, pages and layouts are React Server Components by default and you opt into client code with "use client". In Start, components are ordinary React components that render on the server and hydrate on the client. You put work on the server explicitly with createServerFn() or a route loader. Server Components in Start exist, but they are experimental and off by default, so treat them as a preview, not a reason to pick it.

How I benchmarked TanStack Start and Next.js#

I wanted a fair app, not a hello world. Both apps have:

  • Home page: a heading and a link. Next.js prerenders it as static HTML; Start has no static prerender by default, so it renders it per request.
  • Product list: 100 products rendered on the server on every request, with a timestamp so neither framework can cache it. In Next.js that's an async Server Component with await connection(). In Start it's a route loader calling a GET server function.
  • Product page: one product plus a client-side "Add to cart" counter, so both frameworks must hydrate interactive code.
  • JSON API: a route returning 20 products. A Next.js route handler with dynamic = "force-dynamic", and a Start server route.

Versions: Next.js 16.4.2 with Turbopack and React 19.3.0, TanStack Start 1.169.3 with Vite 8.3.4, Nitro and React 19.3.1, Tailwind 4 in both. Both ran on Node 24.22 in production mode: Next.js as its standalone server.js, Start as its Nitro Node output. A quick check with next start gave the same results (2,377 req/s on the API, 534 on the product page).

The server was pinned to 2 CPU cores with taskset, and the load generator oha ran on 6 other cores of an 8 vCPU Xeon VM. Each run used 64 connections for 10 seconds after a 4 second warm-up, and every number is the median of 3 runs on a fresh server process. All runs returned 100% HTTP 200. Client metrics came from Playwright and Chromium: script bytes on each page (gzip level 6), and the time from navigation to a working button click with a 4× CPU slowdown, median of 6 runs.

This is a small synthetic store, not your app. Your database, auth and caching will usually dominate. Treat these as the cost of the framework layer itself.

Server performance: how many requests can each handle?#

TanStack Start vs Next.js server throughput on the same four routes, requests per second and p99 latency

Server-rendered pages. The product list is where per-request rendering cost shows. Start served 637 pages per second with a p99 of 194 ms; Next.js served 220 with a p99 of 754 ms. On the lighter product page, Start served 2,341 per second versus 512. My reading is that Next.js does more work per request: it renders the Server Component tree to the RSC payload and then renders HTML from it, and it embeds that payload in the page. You can see that in the HTML: the 100-item list was 92 KB raw in Next.js and 60 KB in Start (8.5 KB versus 6.4 KB gzipped).

API routes. This was the biggest gap. A Start server route answered 18,515 requests per second; a Next.js route handler answered 2,165. That's 8.6×. Start's server routes are close to a plain handler on Nitro, while every Next.js request goes through the full Next server and router. For context, Hono on raw Node served 73,000 JSON requests per second on the same 2 cores in my Hono vs Express benchmark, so neither framework is the right place for a hot, high-volume API.

Static pages. Next.js led here: 3,220 versus 2,920 requests per second. Next serves the prerendered HTML file, while Start rendered the home page with React each time and still came within 10%. This is the important caveat for Next.js: anything you can make static or cache, with "use cache" or prerendering, skips most of the per-request cost. I covered how to do that in Next.js "use cache".

Memory. Next.js idled at 94 MB and peaked at about 504 MB under the SSR list load. Start idled at 60 MB and peaked at 363 MB. Both are fine for a small VPS, but on a 1 GB box running several apps, Start leaves more room.

Bundle size, hydration and client navigation#

TanStack Start vs Next.js client JavaScript, HTML size, time to interactive, build time, dev server start and deploy size

On /products, Next.js loaded 7 script files totalling 135 KB gzipped (453 KB raw). Start loaded 3 files totalling 109 KB gzipped (337 KB raw). Most of both is React and React DOM, so the difference is framework runtime: about 26 KB gzipped.

With Chromium's CPU throttled 4×, the "Add to cart" button on a fresh product page became interactive in 289 ms on Start and 324 ms on Next.js. Client-side navigation from the list to a product took 160 ms on Start versus 182 ms on Next.js. Start made 2 requests per navigation (the route chunk and the server function), while Next.js made about 10.

So on the client, Start is faster, but not dramatically. On a real app with a large component library, your own code will outweigh this 26 KB.

Build time, dev server and deployment#

Production build: Next.js took 4.86 s (5 clean runs, including its TypeScript check) and Start took 1.26 s with Vite. Running tsc --noEmit separately on the Start app took another 1.54 s, so even with a type check added, Start's build was about 1.7× faster.

Dev server: from launching the dev command to the first fully rendered /products page, Next.js took 2.96 s cold and 2.91 s warm. Start with Vite took 1.52 s cold and 1.45 s warm.

Deploy output: Next.js standalone output was 38 MB because it traces and copies the parts of node_modules it needs, including Next itself. Start's Nitro output was 1.4 MB, fully bundled. In a Docker image that difference is real, but small next to a Node base image. My Next.js Dockerfile guide shows how to keep the Next.js side lean. Installed node_modules were 354 MB for the Next.js app and 152 MB for Start.

Developer experience: what's different day to day?#

Numbers aside, the daily work feels different:

  • Data loading. Next.js fetches data inside async Server Components. Start uses route loaders and server functions, usually with TanStack Query for client caching. If you already use TanStack Query, Start will feel natural.
  • Server code. Next.js has Server Actions and route handlers; I compared them in Server Actions vs Route Handlers. Start has createServerFn() with validators, GET or POST, and middleware that runs on both client and server.
  • Type safety. Start's router generates types for every path, param and search param, so a broken link is a type error. Next.js has opt-in typedRoutes, which covers links but not validated search params.
  • Caching. Next.js has a framework cache (Cache Components, "use cache", cacheLife). Start has no server data cache: you use HTTP headers, a CDN, or your own store. That's simpler to reason about and more work for content sites.
  • Built-ins. Next.js ships next/image, next/font, metadata APIs and a huge ecosystem of examples. In Start you bring your own image and font handling.
  • Hosting. Next.js runs best on Vercel and works anywhere with Node or Docker, as I do with Coolify. Start deploys through Nitro or plugins to Node, Bun, Cloudflare Workers, Netlify, Vercel and Railway.

One gotcha I hit in Next.js: my generated project wired Tailwind 4 through a turbopack.rules entry for *.css in next.config.ts (the @tailwindcss/turbopack loader). When I overwrote the config to add output: "standalone", the CSS came out empty and the Tailwind compiler ended up in the client bundle: 280 KB of gzipped JavaScript instead of 135 KB. If you edit that file, keep the rules block, and check your bundle after config changes.

Should I switch from Next.js to TanStack Start?#

Pick TanStack Start if:

  • your app renders per user or per request (dashboards, SaaS, internal tools), so server cost matters
  • you want typed routes and search params, explicit server functions and no framework-level cache
  • you like Vite, or want to deploy to Cloudflare Workers or a small VPS without Vercel
  • you already use TanStack Query, Router or Table

Stay with or pick Next.js if:

  • your site is mostly content that can be prerendered or cached, where Next served static pages fastest
  • you rely on React Server Components today, or on next/image, next/font and the metadata API
  • hiring, templates and third-party SDK examples matter more than raw speed
  • you host on Vercel and want its integration

For an existing, healthy Next.js app, I wouldn't rewrite just for these numbers. Cache what you can first. For a new interactive app, Start 1.0 is now a serious default. The official TanStack Start vs Next.js page has a fair feature-by-feature comparison too.

How do I migrate from Next.js to TanStack Start?#

The rough steps I'd follow, based on building the same app in both:

  1. Move app/ routes to src/routes/ files using createFileRoute. Dynamic segments change from [id] to $id.
  2. Replace data fetching in async Server Components with a route loader that calls a createServerFn().
  3. Remove "use client" directives. Every component in Start is a normal component.
  4. Turn route handlers into server routes with server: { handlers: { GET } }.
  5. Replace Server Actions with POST server functions, and add an input validator.
  6. Replace next/link with TanStack Router's Link (to plus typed params), and next/image and next/font with your own components or plain tags.
  7. Add Nitro (or a hosting plugin) to vite.config.ts for your deploy target.

Migrate one representative route end to end first, including auth and a mutation, before committing the whole app.

Common mistakes when comparing Next.js and TanStack Start#

  • Comparing a static Next.js page to an SSR Start page and calling Next faster. Make the rendering mode the same on both sides, or report it, as I did for the home page.
  • Forgetting to copy .next/static into the standalone folder. Next's standalone server doesn't serve client assets without it, so hydration silently never happens. My first client test showed a 30 second timeout for exactly this reason.
  • Benchmarking dev mode. Always build and run with NODE_ENV=production.
  • Running the load generator on the same cores as the server. Pin them apart or your numbers mostly measure contention.
  • Leaving devtools in production. Check that router and query devtools aren't in your client bundle.

Key takeaways#

  • TanStack Start 1.0 went stable on October 13, 2026, and its Server Components support is still experimental.
  • On the same app and 2 cores, Start served 2.9× more SSR list pages, 4.6× more product pages and 8.6× more API calls than Next.js 16.4.
  • Next.js won on its prerendered static page, 3,220 versus 2,920 req/s, so caching closes the gap for content you can cache.
  • Start's p99 on the 100-item SSR page was 194 ms versus 754 ms, and it idled at 60 MB versus 94 MB.
  • Start shipped 20% less client JavaScript (109 KB vs 135 KB gzipped) and became interactive 35 ms sooner on a throttled CPU.
  • Start built in 1.26 s versus 4.86 s and its dev server answered in 1.5 s versus 3.0 s.
  • Choose Start for per-request, interactive apps and typed routing; choose Next.js for cacheable content, RSC and its built-ins.

Related: if you're weighing other parts of your toolchain too, see Oxlint vs Biome vs ESLint and React Compiler in Next.js.

Questions