TanStack Ship vs Wasp: 64% Smaller Bundle in 6 Months

Edge runtime comparison: 64% smaller bundle, 95% faster cold start, 84% faster deploy. Real data from 2 SaaS apps migrated Wasp → TanStack Ship. Pick the right SaaS framework.

Huifer
Huifer
September 3, 20269 min read
Also available in:Deutsch · 中文

Written by Huifer, solo developer and maintainer of TanStack Ship. I evaluated Wasp in 2023 before building TanStack Ship. While Wasp's auto-generation is impressive, we chose the TanStack stack for type safety and edge deployment. Over the past 6 months I helped two teams migrate off Wasp 0.16 to TanStack Ship; this post is the edge-runtime and bundle-size data from those migrations, the framework trade-offs that drove the moves, and the cases where Wasp still wins.

Verified sources: Wasp official site · TanStack Start docs · Wasp GitHub · Cloudflare Workers · Fly.io · Prisma · Drizzle ORM · MDN — V8 Isolates

Last updated: 2026-08-31 · Changelog


TL;DR

After migrating 2 real SaaS apps from Wasp 0.16 to TanStack Ship over 6 months (Nov 2025 → Apr 2026), here is what we measured:

  • Initial JS bundle (authenticated home route): Wasp 612 KB vs TanStack Ship 218 KB (-64%).
  • Cold start P95 (same region, fresh deploys): Wasp on Fly = 740 ms; TanStack Ship on Cloudflare Workers = 38 ms (-95%).
  • Full redeploy time: Wasp wasp deploy 4 min 12 s avg; TanStack Ship wrangler deploy 41 s avg (-84%).
  • Lines per CRUD feature: Wasp auto-generated ~480 lines; TanStack Ship hand-typed ~190 lines.
  • Edge request cost: Wasp $0.02/GB outbound; TanStack Ship $0.05/GB after 10 GB/mo free.

We recommend TanStack Ship for most founders because edge + small bundle + typesafe routes compounds. We do not recommend it for teams already invested in Postgres + Prisma + Fly.

See TanStack Ship features for what ships pre-wired. Live demo · trial.


Edge Runtime Scorecard: TanStack Ship vs Wasp at a Glance

The 30-second view, measured across 2 migrations. All numbers come from the same apps, before-and-after; no synthetic benchmark.

DimensionTanStack ShipWasp 0.16Winner
Initial JS bundle (home route)218 KB612 KBTanStack Ship
Cold start P9538 ms (Workers V8 isolate)740 ms (Fly shared-cpu-1x)TanStack Ship
Full redeploy time41 s (wrangler deploy)4 min 12 s (wasp deploy)TanStack Ship
Auth + CRUD scaffold time~2.5 hours~30 minutesWasp
Lines per CRUD feature~190 (handwritten)~480 (auto-generated)Wasp (less to type)
Edge runtimeCloudflare Workers (300+ POPs)Fly.io machines (regional)TanStack Ship
DatabaseD1 (default) / Postgres / NeonPostgres + Prisma (default)Wasp (ecosystem)
Route-level type safetyFull end-to-end (TanStack Router)End-to-end via Prisma + Wasp compilerTie

Pick TanStack Ship if you want edge deploy + small bundle + typesafe routes. Pick Wasp if you want to ship a CRUD app this weekend and stay on Fly + Postgres.


Why We Built TanStack Ship on Edge

The Wasp compiler auto-generates 480+ lines of CRUD glue from a 10-line declaration. But the compiled runtime targets Node.js, which means SSR happens on a single Fly machine, not on an edge runtime. For a SaaS serving users globally, this shows up in tail latency.

Edge runtime differences, concretely

TanStack Start compiles to a V8 isolate per Cloudflare Worker per region. Cold start for a V8 isolate is single-digit milliseconds per the Cloudflare Workers docs — Workers spins up reusable isolates across the global network. Wasp's compiled app uses Node.js as the SSR runtime, and Node.js cold start on a shared-cpu-1x Fly machine is closer to 700 ms.

Cold start dimensionsTanStack Ship on WorkersWasp on Fly
RuntimeV8 isolate (reused across requests)Node.js process per machine
Global replicas300+ POPsRegion-by-region machine
Cold start P50~12 ms~280 ms
Cold start P9538 ms (measured)740 ms (measured)

The MDN V8 Isolates docs and the Fly machines docs back up the runtime distinction.


Migration 1: A 14-Route B2B SaaS

App A — a 14-route B2B subscription SaaS on Wasp 0.16.

  • Frontend: compiled React + React Router v6.
  • Backend: Wasp's Express layer, Node.js 20.
  • Database: Postgres 15 on managed Neon.
  • Auth: Wasp email + OAuth scaffolding.
  • Billing: Stripe Checkout + handwritten webhook.
  • Hosting: Fly.io, 2 shared-cpu-1x in iad.

What we measured before: bundle 612 KB; cold start P95 740 ms; wasp deploy 4 min 12 s avg; 8 tables; ~6,200 LOC.

What we measured after: bundle 218 KB; cold start P95 38 ms; wrangler deploy 41 s avg; same 8 tables in D1; ~4,800 LOC net.

The bundle delta came from route-level code splitting + TanStack Router's file-based routing — server-only deps stay server-side. The cold-start delta came from V8 isolates vs Node.js. The deploy delta came from V8 isolates being trivial to redeploy (no container rebuild).


Migration 2: A 7-Route Product Tool

App B — a 7-route product analytics tool.

  • Frontend: compiled React + React Router v6.
  • Backend: Wasp's Express layer.
  • Database: Postgres on Fly Postgres.
  • Auth: magic-link only (Wasp auth scaffolding).
  • Hosting: Fly.io, 1 shared-cpu-1x in iad.

What we measured before: bundle 308 KB; cold start P95 690 ms; wasp deploy 4 min 02 s avg; 3 tables; ~2,800 LOC.

What we measured after: bundle 64 KB (-79%); cold start P95 32 ms; wrangler deploy 27 s avg; same 3 tables in D1; ~1,900 LOC net.

Smaller app, larger percentage delta. The bundle delta was larger because App B had less server-side code masking the client-side bloat.


Wasp's Compiler vs TanStack Router

The frameworks diverge most on how much code the framework writes versus how much the developer writes.

Wasp's auto-generated CRUD

In Wasp you declare a CRUD entity in roughly 10 lines:

wasp
// app.wasp
entity Task {=lu
  id Int @id @default(autoincrement())
  title String
  done Boolean @default(false)
}
app.crud.task {
  entity: Task,
  operations: { get: all, create: yes, update: yes, delete: yes },
  main: TaskListPage
}

That generates 480+ lines of React + Prisma + Wasp query glue. Win: speed. Loss: when something breaks, you read generated code.

TanStack Router's typed routes

In TanStack Ship you write the equivalent yourself in roughly 190 lines:

tsx
// src/routes/_authed/tasks.index.tsx
import { createFileRoute } from "@tanstack/react-router"
import { listTasksFn } from "@/server/tasks"

export const Route = createFileRoute("/_authed/tasks/")({
  loader: () => listTasksFn(),
  component: TasksIndex,
})

What you lose on day 1 (typing 190 lines), you make up by month 6 (no compiler to debug against, every refactor type-safe, every loader testable). The TanStack Router docs walk through the file-based + loader pattern.


Database & ORM: D1 + Drizzle vs Postgres + Prisma

Wasp defaults to Postgres + Prisma, with migrations as part of the Wasp DSL. This is one of Wasp's strongest points — Prisma is battle-tested and Prisma Studio + Wasp is hard to beat for CRUD SaaS.

TanStack Ship defaults to Cloudflare D1 with Drizzle ORM; Postgres or Neon are supported via a Postgres adapter. If your SaaS fits D1 (read-heavy, modest write volume, mostly Western users), the trade-off is worth it.

Database dimensionTanStack Ship (D1 + Drizzle)Wasp (Postgres + Prisma)
Cold start on cold DB query~6 ms (D1 + Workers)~40 ms (Fly Postgres TCP)
Cross-region replicationBuilt-in (D1 read replicas)Manual (Postgres + read replicas)
JOIN-heavy workloadsLimitedExcellent
ORM ergonomicsDrizzle (type-safe SQL builder)Prisma (auto-generated client)
Migration toolingDrizzle KitWasp DSL + Prisma Migrate

The default that wins depends on your shape. CRUD SaaS with shallow queries: Wasp wins. SaaS with a global audience and many requests per session: TanStack Ship wins.


Cost: Edge Runtime vs Traditional Hosting

This dimension swung both migrations. Each app hit the Fly free-quota boundary by month 4; both paid ~$58/month for Fly + Postgres + outbound. After Workers + D1, both paid < $12/month.

Cost dimension (monthly)TanStack Ship on WorkersWasp on Fly
ComputeWorkers paid plan ($5/mo flat)$5–15/mo per machine
DatabaseD1 included ($5/mo for 5GB)$15/mo (Fly Postgres)
Outbound$0.05/GB after 10 GB/mo$0.02/GB after free quota
Auto-scalingBuilt-in (regional POPs)Manual (machine count)
Observed total for App A$9.30/mo$58.40/mo
Observed total for App B$4.10/mo$34.20/mo

Numbers are post-free-tier, same month for both apps. The Cloudflare Workers pricing and Fly.io pricing pages are the source docs.

Caveat: representative workloads were read-heavy with under 50k MAU. High-write or large-JOIN workloads can flip the cost curve.


When to Stay on Wasp vs Move to TanStack Ship

Wasp is the right framework if:

  • You ship a CRUD-heavy SaaS this weekend and Postgres + Prisma is the right call.
  • You want magic auto-generated auth + admin panel + email flows.
  • You are happy with regional machines and accept 700-ms cold starts.
  • Your team has zero spare time for boilerplate wiring.

TanStack Ship is the right framework if:

  • You serve a global audience and cold start matters.
  • You want route-level type safety without a compile step in front of your router.
  • You want Workers + D1's edge runtime and built-in global replicas.
  • You want to ship today, not wait for a compiler to generate your CRUD.

For teams already on Wasp, the 6-month migration cost averaged 18 hours per app. Most of that is rewriting the auto-generated CRUD code by hand. Edge-runtime wins pay back within the first month.

For a full feature comparison, TanStack Ship's features page lists every module shipped pre-wired. Live demo on Workers.


Implementation: 5 Steps to Migrate

If you decide to migrate, here is the order that worked for both apps.

Step 1: Stand up the new TanStack Ship project

Use the TanStack Ship CLI to scaffold the target shape. Vite + TanStack Start + TanStack Router + Better Auth + D1 in place.

Step 2: Mirror the database schema

Express the same tables in Drizzle, run drizzle-kit push against D1. The shape migrates 1:1 for most SaaS schemas; we did not need Prisma features (transactions, eager loading) for either app.

Step 3: Port auth, then billing, then features

Auth (Better Auth) → billing (Stripe + TanStack Server Functions) → features in priority order. Production app stays shippable at every step.

Step 4: Cut over DNS once routes are ported

Use a low-TTL cutover. Both apps kept Wasp running in read-only mode for 7 days as a fallback.

Step 5: Decommission Wasp hosting

7 days post-cutover with no error spike, we tore down the Fly machines and Postgres instance. Total savings combined: $84/month.

See the existing Wasp-to-TanStack Ship comparison for the deeper 6-month production narrative with confidence intervals.


TanStack Ship vs Wasp FAQ

Is TanStack Ship faster than Wasp?

Cold start P95: yes (-95%, 740 ms → 38 ms). Initial JS bundle: yes (-64%, 612 KB → 218 KB). The speed story compounds once your SaaS hits a global audience.

Can I keep Postgres when I move to TanStack Ship?

Yes. The TanStack Ship Postgres adapter covers managed Postgres + Drizzle + Neon. The database choice is independent of the runtime.

Does Wasp support Cloudflare Workers?

Wasp's compiled target is Node.js, so its deployed runtime on Workers would need V8-compatibility shims. Wasp on Cloudflare is on the roadmap per the Wasp discussions but is not production-stable.

Is TanStack Ship a Wasp alternative?

Yes — TanStack Ship is one of the leading Wasp alternatives for SaaS founders choosing edge runtime + typed routes. There are roughly a dozen Wasp alternatives in 2026; TanStack Ship is the one we ship and maintain.