
The short answer
Start with the lightest framework that does the job. For an API, a site or server-rendered pages, that’s Hono or Astro. Choose Next.js when you need something on the short list below.
We built one shop twice, in Next.js and in Hono, with the same pages and the same output. The catalog page used 129 ms of CPU in Next.js and 9 ms in Hono: 93% less. The browser downloaded 145 KB of JavaScript for the Next.js shop and none for the Hono shop.
We have a stake in this: Eurobase runs all seven frameworks, and every plan includes a monthly CPU budget for Workers. That’s why we measured on real deployments, and the method is at the end.
Decide in 30 seconds
| Your app | Pick |
|---|---|
| A JSON API or a webhook | Hono |
| Server-rendered pages with little or no interactivity | Hono |
| A marketing site, a blog or docs | Astro |
| Content pages with a few interactive parts | Astro |
| An interactive app with little JavaScript in the browser | SvelteKit |
| An interactive app, and your team writes Vue | Nuxt |
| A React app with routes and data loaders | React Router |
| A React app with typed routes and server functions | TanStack Start |
| A large React app built on server components and Server Actions | Next.js |
| An app that depends on a library built for Next.js | Next.js |
If your app already works in Next.js and fits your CPU budget, keep it.
One shop, built twice
The shop has 400 products, a header, navigation and a footer, a stylesheet, a catalog, product pages, a static About page and a JSON report on 2,000 orders. Data lives in memory, so there’s no database in these numbers. Every page renders on each request, except About.
Both versions returned the same <main> markup and the same JSON, apart from a timestamp. The Next.js shop uses server components, and we wrote no client components for it. The Hono shop uses its own JSX.
| CPU per request | Next.js | Hono | Less with Hono |
|---|---|---|---|
| Home, 12 products | 28.0 ms | 3.8 ms | 86% |
| Catalog, 400 products | 128.7 ms | 9.0 ms | 93% |
| Product page | 30.1 ms | 3.2 ms | 89% |
| Static About page | 17.9 ms | 0.04 ms | 99% |
| JSON report on 2,000 orders | 16.7 ms | 7.5 ms | 55% |
| Size and speed | Next.js | Hono | Less with Hono |
|---|---|---|---|
| Worker size, compressed | 1,059 KB | 23 KB | 98% |
| JavaScript on a first visit | 145 KB | 0 KB | 100% |
| Catalog first visit, all downloads | 176 KB | 11 KB | 94% |
| Catalog HTML, uncompressed | 283 KB | 82 KB | 71% |
| Catalog time to first byte, median | 168 ms | 77 ms | 54% |
| First request on a cold start, median | 1,800 ms | 975 ms | 46% |
- Next.js sends each page twice
- The catalog HTML holds the products once as markup and again as data for React in the browser. That’s why it weighs 283 KB against 82 KB, with the same visible page.
- A static Next.js page still runs your Worker
- The About page is prerendered in both shops. Hono’s is a file served without running your Worker. In Next.js, a request runs the Worker and returns the cached page, which used 18 ms of CPU.
- The JavaScript buys something
- With 145 KB in the browser, the Next.js shop can move between pages without a full reload, and it’s ready for interactive components. The Hono shop loads a new page on each click.
- Your own code shrinks the gap
- The JSON report does the same sums in both shops and renders nothing. That’s where the gap is smallest: 55%. The more of a request is your own work, the less the framework matters.
How far your CPU budget goes
Workers plans include a monthly CPU budget for the whole workspace. Dividing each budget by the measured CPU of the catalog page gives the views it covers, if the catalog were your only page:
| Plan | CPU per month | Next.js views | Hono views |
|---|---|---|---|
| Free | 3,000 s | 23,000 | 332,000 |
| Starter | 30,000 s | 233,000 | 3,329,000 |
| Pro | 100,000 s | 776,000 | 11,098,000 |
Calculated from unrounded CPU, then rounded down. Startup CPU doesn’t count, and neither do files served without running a Worker.
The Free plan also limits each request to 50 ms of CPU. A 129 ms page is over that limit, so each view draws on a 2 s reserve that refills at 50 ms per second. Once the reserve is empty, the request gets a 503. The same page in Hono stays inside the limit. Paid plans allow 30 s per request.
All seven frameworks
For this comparison we built a smaller app in each framework: a small dynamic page, a page listing 400 rows, a static page and a JSON report. It has no header or stylesheet, so its numbers are lower than the shop’s. Compare frameworks within this table, not with the shop.
| Framework | Small page | 400 rows | JSON | Static page | JavaScript | 400-row HTML |
|---|---|---|---|---|---|---|
| Next.js | 26.0 | 102.6 | 15.7 | 18.6 | 141 KB | 237 KB |
| TanStack Start | 8.5 | 36.3 | 10.7 | 0 | 115 KB | 146 KB |
| React Router | 8.5 | 26.3 | 11.5 | 0 | 119 KB | 144 KB |
| Nuxt | 10.2 | 25.9 | 8.0 | 0 | 75 KB | 138 KB |
| SvelteKit | 4.9 | 13.1 | 8.3 | 0 | 37 KB | 144 KB |
| Hono | 2.9 | 9.2 | 7.3 | 0 | 0 KB | 71 KB |
| Astro | 5.5 | 7.0 | 7.3 | 0 | 0 KB | 71 KB |
The first four number columns are CPU in ms per request. Static pages under 0.1 ms show as 0. JavaScript is the compressed download for the small page on a first visit, and 400-row HTML is uncompressed.
- Hono and Astro send no JavaScript. Their 400-row HTML is about half the size of most others, and under a third of Next.js.
- SvelteKit sends the least JavaScript of the five frameworks that send any.
- Static pages use almost no CPU in every framework here except Next.js.
- On JSON, six frameworks sit between 7 and 12 ms, because most of that time is the report itself.
- A cold start took a median of 1.0 to 1.5 s in six frameworks, and 1.9 s in Next.js.
What you gain by switching
| From | To | Small page CPU | 400-row CPU | JavaScript |
|---|---|---|---|---|
| Next.js | Hono | 89% less | 91% less | 100% less |
| Next.js | Astro | 79% less | 93% less | 100% less |
| Next.js | SvelteKit | 81% less | 87% less | 74% less |
| Next.js | Nuxt | 61% less | 75% less | 47% less |
| Next.js | React Router | 67% less | 74% less | 16% less |
| Next.js | TanStack Start | 67% less | 65% less | 18% less |
| React Router | Astro | 36% less | 73% less | 100% less |
| Nuxt | SvelteKit | 52% less | 50% less | 51% less |
| SvelteKit | Hono | 41% less | 30% less | 100% less |
Calculated from unrounded CPU.
The size of a rewrite matters as much as the saving. React Router and TanStack Start keep your React components, so they’re the shortest move from Next.js, and CPU still drops by 65% to 74%. Hono, Astro and SvelteKit save more, and you rewrite your components.
When Next.js is worth its cost
- Server and client components in one tree
- Server components fetch data on the server, and client components add interactivity inside the same page. For a large React app, that model is the reason to pay.
- Forms that call server code directly
- Server Actions let a form run a server function with no API route to write.
- Cached pages refreshed on demand
- Incremental static regeneration,
use cacheandrevalidateTagrefresh a page when its data changes. On Eurobase, a small cached page still used 18 ms of CPU. - Libraries built for it
- Some tools expect Next.js. Payload CMS, for one, installs inside a Next.js app.
- A team and an app already on it
- What your team already knows is worth something, and a rewrite has its own cost.
If none of these describes your app, you’re paying for features you don’t use. Image resizing isn’t a reason on Eurobase: on Workers, next/image serves each image at its original size.
What you give up with Hono
- Routes and layouts by folder. You write routes in code and compose layouts yourself.
- React. Hono’s JSX isn’t React, so React component libraries aren’t built for it.
- Page changes without a reload. Each click loads a full page.
- Interactivity out of the box. You add client components and their build yourself.
- An image component and a data cache. You choose your own.
- On Eurobase, setup with no config. Hono needs a Wrangler config.
When each framework fits
- Hono
- APIs, webhooks and server-rendered pages. The smallest Worker and no JavaScript in the browser unless you add it.
- Astro
- Sites made of content, with islands of interactivity where you need them. On Eurobase, images on server-rendered pages keep their original size, and Astro sessions don’t work.
- SvelteKit
- Interactive apps with routing built in, for 37 KB of JavaScript where the React frameworks here send 115 KB or more.
- Nuxt
- The full framework for Vue teams, with routing and server routes in one project.
- React Router
- React apps that want routes and loaders without server components.
- TanStack Start
- React apps that want typed routes and server functions. It used the most CPU on the 400-row page after Next.js, so check your longest lists.
- Next.js
- Large React apps that use what’s listed above. On Eurobase, Next.js responses are cached only when your app sends
CDN-Cache-Control, and a Cache Components page renders on each request.
If a coding agent picks for you
This part is our experience, not a measurement: coding agents often reach for Next.js, even for a small site that would do the same job in a lighter framework. So name the framework in your prompt, and ask for Next.js only when your app needs what’s listed above.
How we measured
- Each app ran as a Worker on Eurobase, deployed on 6 November 2026. Eurobase added the adapter during the build, except for Hono, which has its own Wrangler config.
- CPU: 300 requests per page, one at a time from one client in Europe, after 20 warm-up requests. We read the project’s metered Workers CPU before and after, and subtracted what a warm instance adds while idle.
- Time to first byte: taken on the same 300 requests, over a reused connection.
- Downloads: a headless Chromium browser with an empty cache, counting compressed bytes.
- Worker size: the compressed upload size of the shop, built locally with the same adapters.
- Cold start: we waited 16.5 minutes, past the 15-minute idle stop, then opened a new connection, followed by three more. Medians use the first request of each run. That’s 5 samples per shop, 6 for the small Hono and Next.js apps, and 3 for the others.
| Framework | Version | Setup |
|---|---|---|
| Next.js | 16.4.3, React 19.3.0 | Server components, OpenNext adapter 1.20.9 |
| TanStack Start | 1.169.4, React 19.3.1 | Server functions |
| React Router | 8.5.1, React 19.3.1 | Loaders |
| Nuxt | 4.6.3, Vue 3.5.44 | useFetch and a server route |
| SvelteKit | 3.1.1, Svelte 5.57.3 | Server load functions |
| Hono | 4.13.14 | hono/jsx |
| Astro | 7.4.4 | Server output |
What these numbers don’t tell you:
- They describe these frameworks on V8 isolates. Next.js runs here through its adapter, so it will behave differently on a Node.js server.
- These are small apps with data in memory, and one client at a time. We didn’t test concurrent traffic.
- These apps have no interactive parts, so Hono and Astro send no JavaScript. Yours may need some.
- Two of 148 requests in the cold-start runs returned a 503, one on Nuxt and one on React Router. We left them out, so Nuxt has 2 cold-start samples.



