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 deploy4 min 12 s avg; TanStack Shipwrangler deploy41 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.
| Dimension | TanStack Ship | Wasp 0.16 | Winner |
|---|---|---|---|
| Initial JS bundle (home route) | 218 KB | 612 KB | TanStack Ship |
| Cold start P95 | 38 ms (Workers V8 isolate) | 740 ms (Fly shared-cpu-1x) | TanStack Ship |
| Full redeploy time | 41 s (wrangler deploy) | 4 min 12 s (wasp deploy) | TanStack Ship |
| Auth + CRUD scaffold time | ~2.5 hours | ~30 minutes | Wasp |
| Lines per CRUD feature | ~190 (handwritten) | ~480 (auto-generated) | Wasp (less to type) |
| Edge runtime | Cloudflare Workers (300+ POPs) | Fly.io machines (regional) | TanStack Ship |
| Database | D1 (default) / Postgres / Neon | Postgres + Prisma (default) | Wasp (ecosystem) |
| Route-level type safety | Full end-to-end (TanStack Router) | End-to-end via Prisma + Wasp compiler | Tie |
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 dimensions | TanStack Ship on Workers | Wasp on Fly |
|---|---|---|
| Runtime | V8 isolate (reused across requests) | Node.js process per machine |
| Global replicas | 300+ POPs | Region-by-region machine |
| Cold start P50 | ~12 ms | ~280 ms |
| Cold start P95 | 38 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:
// 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:
// 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 dimension | TanStack Ship (D1 + Drizzle) | Wasp (Postgres + Prisma) |
|---|---|---|
| Cold start on cold DB query | ~6 ms (D1 + Workers) | ~40 ms (Fly Postgres TCP) |
| Cross-region replication | Built-in (D1 read replicas) | Manual (Postgres + read replicas) |
| JOIN-heavy workloads | Limited | Excellent |
| ORM ergonomics | Drizzle (type-safe SQL builder) | Prisma (auto-generated client) |
| Migration tooling | Drizzle Kit | Wasp 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 Workers | Wasp on Fly |
|---|---|---|
| Compute | Workers paid plan ($5/mo flat) | $5–15/mo per machine |
| Database | D1 included ($5/mo for 5GB) | $15/mo (Fly Postgres) |
| Outbound | $0.05/GB after 10 GB/mo | $0.02/GB after free quota |
| Auto-scaling | Built-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.