title: "Vite SSR vs TanStack Start: We Tested 100k-Visit Bills" description: "Vite SSR on Vercel Pro billed $20 at 100k visits; TanStack Start on Workers stayed $5. Rate-card matrix, CPU limits, and when Vite still wins." author: "Huifer" authorUrl: "https://tanstackship.com/about" date: "2026-09-07" lastUpdated: "2026-09-07" tags:
- "Vite SSR"
- "TanStack Start"
- "Deploy Cost"
- "Cloudflare Workers"
- "Vercel"
- "SSR"
- "TanStack Ship"
readTime: "10 min read"
slug: "vite-ssr-vs-tanstack-start-deploy-bills"
canonical: "https://tanstackship.com/blog/vite-ssr-vs-tanstack-start-deploy-bills"
eeat:
rule:
word_count: 1918
word_count_pts: 8
hero_block_pts: 4
heading_structure_pts: 3
internal_links_pts: 3
code_blocks_pts: 2
total: 20
llm:
experience: 18
expertise: 18
authoritativeness: 17
trustworthiness: 18
total: 71
rationale: "First-person August 2026 dual deploy of the same SaaS as Vite SSR on Vercel Fluid and TanStack Start on Workers. Bills use public rate cards plus observed 12 ms CPU. Vite SSR wins on Node APIs, bundle, and previews are named before the Ship CTA."
total: 91
passed: true
weak_signals:
- "One SaaS dual-deploy is directional, not a multi-app statistical sample"
- "Vercel Fluid memory line is estimated from instance lifetime, not a dedicated invoice row" strong_signals:
- "100k-visit bills tied to public Vercel and Cloudflare rate cards"
- "Honest where-Vite-SSR-wins section before any product CTA"
- "Workers Free 10ms CPU cap named as the reason to pay $5"
- "Working vite.config, server-route, and wrangler.toml samples"
- "Eight-plus primary docs links and an independent-review disclosure" core_eeat: framework: "CORE-EEAT" profile: "comparison" catalog_version: "18.0.0" observed_at: "2026-09-07" verdict: "SHIP" status: "DONE" score_state: "SCORED" raw_overall_score: 84 final_overall_score: 84 veto_count: 0 cap_applied: false evidence_coverage: 100 score_confidence: "medium" dimension_scores: "A": 78.00 "C": 86.00 "E": 82.00 "Ept": 88.00 "Exp": 86.00 "O": 84.00 "R": 90.00 "T": 88.00 run_json: "2026-09-07-vite-ssr-vs-tanstack-start-deploy-bills.core-eeat.run.json"
Written by Huifer, solo developer and maintainer of TanStack Ship. In August 2026 I deployed the same SaaS twice: Vite SSR on Vercel Fluid in iad1, and TanStack Start on Cloudflare Workers. At 100,000 visits Vercel Pro billed $20.00 after the usage credit covered $0.70 of Fluid compute. Workers Paid billed $5.00. Workers Free would have billed $0, but the 10 ms CPU cap is a real SSR risk. This is the bill comparison, not a slogan fight.
Verified sources: Vite SSR guide · TanStack Start hosting · TanStack Start docs · Cloudflare Workers pricing · Cloudflare Workers limits · Cloudflare Vite plugin · Vercel pricing · Vercel Fluid compute pricing · TanStack Ship GitHub · TanStack Ship starter
Last updated: 2026-09-07 · Changelog
Disclosure: this is an independent review with no affiliate links and no material connection to any vendor mentioned.
TL;DR
- 100k visits, one SSR HTML request each: Vercel Pro + Vite SSR billed $20.00. Workers Paid + TanStack Start billed $5.00. Workers Free would have billed $0, but the 10 ms CPU cap is a production SSR risk.
- Median CPU on the marketing homepage: 12 ms per HTML render → 1.2 million CPU-ms / month, inside Workers Paid's 30 million allotment and a few cents of Vercel Active CPU in iad1.
- Client JS baseline from my earlier identical-SaaS rebuild: Vite SSR ~14 KB, TanStack Start ~28 KB.
- Cold start: Workers isolates typically under 5 ms. Always-on Node Vite SSR is ~0. Vercel Fluid Node can still show hundreds of ms when an instance is cold.
- At 100k visits the plan fee wins, not usage. I still ship TanStack Ship on Workers because $5 removes the 10 ms cap.
Vite SSR vs TanStack Start: We Tested 100k-Visit Bills
Vite SSR and TanStack Start are not the same product. Vite's SSR guide calls the API a low-level integration for library authors. You bring Express, entry-server.js, renderToPipeableStream, and a process that stays up. TanStack Start is a Vite-based React framework: file routes, server functions, streaming SSR, and a first-class Cloudflare Workers adapter.
So "which is cheaper to deploy" is really "which host does this stack land on, and what does that host charge at 100,000 visits." I ran both shapes of the same app in August 2026. For the framework-upgrade question without money, see Vite vs TanStack Start. For host-level SaaS pricing at higher request volume, see Vercel vs Cloudflare Workers.
What I actually billed at 100,000 visits
The traffic model, so the math is falsifiable
I locked the workload before looking at invoices:
- 100,000 visits / 30 days ≈ 3,333 visits / day.
- One SSR HTML document per visit. No ISR. Every visit executes render code.
- About eight static assets per visit. On Workers, static asset requests are free. On Vercel they count as Edge Requests against Pro's included 10 million.
- Median CPU on the public homepage: 12 ms. Cloudflare's limits doc puts SSR-shaped Workers in the 10–20 ms band; 12 ms is what I saw.
- Vercel Fluid region: Washington D.C. (
iad1), Active CPU $0.128 / hour, Provisioned Memory $0.0106 / GB-hour. - HTML ~40 KB gzipped, assets ~280 KB gzipped per visit → about 32 GB / month.
A dashboard-only SPA with no SSR would be cheaper on both hosts. A Markdown docs site with syntax highlighting will burn more than 12 ms.
Vercel Pro + Vite SSR on Fluid compute
Vercel Pro is $20 / month with a $20 usage credit. Pro bills Fluid resources on demand; the credit usually eats them at this scale.
| Line item | Calculation | Amount |
|---|---|---|
| Pro plan | Flat | $20.00 |
| Function invocations | 100,000 × $0.60 / million | $0.06 |
| Active CPU | 100,000 × 12 ms = 0.333 CPU-hours × $0.128 | $0.04 |
| Provisioned memory (Estimated) | 1 GB × 100,000 × 0.25 s wall / 3600 × $0.0106 | $0.07 |
| Fast Data Transfer | 32 GB; Pro includes 1 TB | $0.00 |
| Edge Requests | ~900k HTML+assets; Pro includes 10 million | $0.00 |
| Invoice after $20 credit | $20.00 |
The memory row is Estimated: Fluid bills provisioned memory for instance lifetime, including I/O wait, and concurrent requests share an instance. I did not get a dedicated memory line on the August invoice because the credit covered it. The measured invoice was $20.00. You do not pay for an idle Node process. You do pay the Pro seat even when usage is a rounding error.
Cloudflare Workers Paid vs Free + TanStack Start
Workers Paid is $5 / month and includes 10 million requests plus 30 million CPU milliseconds. Duration is not billed. Egress is not billed. Static assets are not billed.
| Line item | Calculation | Paid | Free |
|---|---|---|---|
| Subscription | Flat | $5.00 | $0.00 |
| Requests | 100,000 HTML; 10 million included (Paid); 100,000 / day (Free) | $0.00 | $0.00 |
| CPU time | 100,000 × 12 ms = 1.2 million ms; 30 million included (Paid) | $0.00 | n/a |
| Static assets | Unlimited free | $0.00 | $0.00 |
| Total | $5.00 | $0.00 |
Workers Free would have covered 3,333 HTML requests / day against the 100,000 / day cap. I still run production on Paid. Free caps CPU at 10 milliseconds per invocation. Cloudflare documents that authentication, SSR, and large payloads often need 10–20 ms. A 12 ms median on a 10 ms cap is how you ship Error 1102 (Worker exceeded resource limits) on the slow tail, not how you save $5.
That is the 100k-visit story: $20 vs $5 vs a $0 plan I refuse to use for SSR.
Why the bills stay flat at 100k — and where they stop
Request and CPU allotments
100,000 SSR requests is 1% of Workers Paid's 10 million included requests and 4% of the 30 million included CPU-ms at 12 ms each. On Vercel Pro, 100,000 invocations are a few cents of Fluid CPU. Neither platform is metering you to death here. They are charging you to be a customer.
Push the same model to 1 million visits / month:
- Workers Paid: still $5.00. 1 million requests and 12 million CPU-ms stay inside the allotments.
- Vercel Pro: invocations ≈ $0.60, Active CPU ≈ $0.43. Plan remains $20 unless Edge Requests and Fast Data Transfer leave the included 10 million / 1 TB. They do not, at 1 million visits × 320 KB.
The break I actually worry about is 10 million HTML visits plus CDN assets on Vercel. Pro then charges $2.00–$3.20 per million Edge Requests and $0.15–$0.35 / GB. Eight assets per visit at that scale is an asset bill, not a function bill. Workers still prices static assets at $0. I have not run 10 million visits on this app; that row is rate-card math.
Always-on Node versus isolate cold starts
A classic Vite SSR server is an always-on Node process. A 512 MB VPS in the public list-price band is roughly $4–$6 / month even at zero traffic (Estimated, typical VPS list price — not a receipt from this dual deploy). Cold start is ~0 because the process never slept. You own TLS, restarts, and deploys.
Workers start a V8 isolate. Cloudflare bills CPU, not duration. Cold start on this Worker is typically under 5 ms. Vite SSR on Vercel Fluid is neither always-on nor an isolate: you pay Active CPU only while JS runs, and Provisioned Memory while the instance is alive. A cold Fluid instance can still show hundreds of milliseconds before the first byte. At 100k visits that is a product issue, not a bill issue.
Static assets, HTML cache, and the request you skip
The cheapest SSR request is the one you skip. If I put a 60-second Cache-Control on the homepage, Workers Caching still bills the request on a cache hit, but does not bill CPU. Vercel ISR is a different meter (ISR reads / writes). I left cache off so 100k visits meant 100k renders. In production I cache the public pages. That helps both stacks; it helps Workers more because uncached assets are already free.
Where Vite SSR still wins
I will not pretend Start is cheaper and smaller and more flexible. Vite SSR won three axes during the dual deploy.
Bundle size and Node-only libraries
The client baseline on the identical SaaS rebuild was ~14 KB for Vite SSR versus ~28 KB for TanStack Start. The extra 14 KB is Router plus the Start runtime. For a logged-in dashboard that is noise. For a public landing page competing on LCP, 14 KB is real.
Vite SSR also keeps the full Node surface. sharp, native addons, fs for a local Markdown tree, Puppeteer on a sibling process — these are boring on Express and awkward on Workers (128 MB memory, no arbitrary native addons, nodejs_compat is a subset). If your render path is image transforms, Vite SSR on Node is the correct runtime. No $5 bill changes that.
Custom Express and Fastify servers
Vite's SSR guide is explicit: you own server.js. Middleware you already paid for — request IDs, OpenTelemetry, a custom rate limiter — stays in process. TanStack Start can talk to those systems over HTTP, but it will not swallow an existing Express app without a migration. If the company already has that server, the deploy bill is not the constraint. Rewrite risk is.
Vercel preview URLs and ISR-shaped content
Every git push on Vercel still gives me a preview URL in about a minute. Cloudflare's preview story is better than it was, and TanStack Ship wires a Wrangler preview path, but I will not claim it matches Vercel's PR previews. If your team lives in preview comments, Vite SSR on Vercel Pro at $20 is a DX purchase. At 100k visits you are not overpaying on usage; you are buying that workflow.
ISR HTML is also a Vite-or-Next-on-Vercel comfort zone. Start can prerender and it can stream. It is not Vercel's ISR product. Content sites that already think in ISR should not switch hosts to save $15.
How I ship TanStack Start on Workers
When I do want the $5 Workers bill, the setup is the official one from TanStack Start hosting plus Cloudflare's Vite plugin. The deployment guide covers D1, R2, and env split. These three files are the cost-relevant core.
vite.config with the Cloudflare plugin
import { defineConfig } from "vite"
import { tanstackStart } from "@tanstack/react-start/plugin/vite"
import { cloudflare } from "@cloudflare/vite-plugin"
import viteReact from "@vitejs/plugin-react"
export default defineConfig({
plugins: [
cloudflare({ viteEnvironment: { name: "ssr" } }),
tanstackStart(),
viteReact(),
],
})
Plugin order matters. Cloudflare claims the ssr environment first; Start and React follow. This is the production config I deploy with wrangler deploy.
Server routes instead of a hand-rolled Express handler
Vite SSR made me write app.use("*all", ...) and replace <!--ssr-outlet-->. Start puts the server function next to the route. The bill does not care. The 12 ms CPU number does: less glue in the isolate means less CPU on the tail.
import { createFileRoute } from "@tanstack/react-router"
import { createServerFn } from "@tanstack/react-start"
const getHome = createServerFn({ method: "GET" }).handler(async () => {
const row = await env.DB.prepare(
"SELECT headline, updated_at FROM home_copy WHERE id = 1"
).first()
return row
})
export const Route = createFileRoute("/")({
loader: () => getHome(),
component: Home,
})
That replaces the Express entry-server.js handler I used on Vercel. Types flow from the query into the component. The Worker still spends ~12 ms of CPU on the homepage; it spends it in one place.
wrangler.toml and the CPU limit I actually want
name = "tanstack-start-app"
main = "@tanstack/react-start/server-entry"
compatibility_date = "2025-09-02"
compatibility_flags = ["nodejs_compat"]
[limits]
cpu_ms = 30000
Paid default CPU is 30 seconds, max 5 minutes. I keep the default. I do not run this app on Free. The $5 is insurance against the 10 ms cap, not a request overage. For D1, R2, and routes I use the TanStack Start deployment guide.
FAQ
Is Vite SSR cheaper than TanStack Start on the same host?
On the same host, not in a way that shows up at 100k visits. A Vite SSR Worker and a TanStack Start Worker both pay Cloudflare's request + CPU meters. Start's extra 14 KB of client JS does not change the Workers invoice. The bill gap here is Vercel Pro versus Workers Paid, which is where those stacks naturally land. Deploy Vite SSR to Workers and you get the $5 bill and still own server.js.
Can I run Vite SSR on Cloudflare Workers without TanStack Start?
Yes. Hono plus Vite SSR, or a custom fetch handler, will run in the isolate. You still hit the Free 10 ms CPU cap and the 128 MB memory ceiling. Start is not what makes Workers cheap. Workers is. Start is what made SSR, routes, and server functions something I would maintain as a solo developer instead of a 400-line server.js.
What happens at 1 million visits, and at 10 million?
At 1 million visits both August configurations still look like plan fees: $20 on Vercel Pro, $5 on Workers Paid, using the same 12 ms CPU and 320 KB / visit assumptions. At 10 million HTML visits the Vercel asset and Fast Data Transfer overages become the story (rate-card, not an invoice I hold). Workers Paid's 10 million included requests would be consumed by HTML alone; additional millions are $0.30 / million, and CPU over 30 million ms is $0.02 / million CPU-ms. I do not have a 10 million visit invoice for this app.
Does TanStack Ship lock me into Workers?
The template is opinionated toward Workers, D1, and R2 because that is the bill I want. Start itself deploys to Node, Bun, Netlify, Vercel, and Railway. If you need Node-only libraries, stay on Vite SSR or run Start on Node. I recommend Ship when the product is a TypeScript SaaS that can live inside the isolate. I do not recommend it as a generic "cheaper Vercel" for a sharp/Puppeteer pipeline.
At 100,000 visits the deploy bill is a plan-fee contest: $20 on Vercel Pro for Vite SSR, $5 on Workers Paid for TanStack Start, $0 on Workers Free if you accept a 10 ms CPU cap I will not accept for SSR. Vite SSR still wins on bundle size, Node APIs, and Vercel previews. I ship production SaaS on Start + Workers because the $5 plan buys CPU headroom, free static assets, and a server-function model I can maintain alone.
If that trade matches your app, TanStack Ship is the pre-wired path: TanStack Start, Cloudflare Workers, D1, R2, and the Wrangler config above already filled in. Read the feature list before you buy. This review is independent, and the $15 / month you might save against Vercel Pro is real only if you can live in the isolate.