本文由 Huifer 撰写,Solo 开发者,TanStack Ship 维护者。 TanStack Ship 最初是我自己 Micro-SaaS 产品的脚手架。过去 18 个月我用它上线了 3 个 Micro-SaaS 产品——合计 $2K MRR——并在 4 次生产事故后对它进行了重建。本文是这几次上线后的实测笔记:成本测算、运行时取舍、14 天上线 playbook,以及什么时候该选不同的技术栈。
信息来源: TanStack Start 文档 · Cloudflare Workers 定价 · Cloudflare D1 · Cloudflare R2 定价 · Stripe 定价 · Resend 定价 · Better Auth · Drizzle ORM
最后更新:2026-05-18 · 更新日志
TanStack Ship for Micro-SaaS:$8/月成本测算与实测笔记
TL;DR: 18 个月内我用 TanStack Ship 上线了 3 个 Micro-SaaS 产品,1k MAU 下托管账单是 $8/月。以下内容:Micro-SaaS 为什么需要不同于 VC 融资 SaaS 的运行时、与 Next.js + Vercel 的逐项成本对比、3 个坦诚取舍、14 天上线 playbook,以及什么时候该选另一个脚手架。完整模块拆解见功能页面;定价见价格页面。
Micro-SaaS 为什么需要不同于 VC 融资 SaaS 的架构
Micro-SaaS 是付费用户少于 1 万的产品——通常少于 1000 人。经济模型在五个地方与 VC 融资 SaaS 不同。以下五个差异解释了为什么我的三个存活产品存活了下来。
1. 成本是硬性上限,不是优化目标
在 VC 融资 SaaS 中,$500/月的 Vercel 账单相对于 $500 万 ARR 只是零头。在 Micro-SaaS 中,你的客户付 $19/月或 $190/年。你的托管预算大约是 MRR 的 10–15%,而不是 5%。一个 MRR $2000 的 Micro-SaaS 能负担的总成本是 $200–$300/月。超过这个上限的每一块钱都是从你自己口袋里掏的。
2. 冷启动很关键,因为流量呈尖刺状
处于早期增长的 Micro-SaaS,90% 的流量来自一次上线事件。流量峰值打在冷区域。Vercel 250ms 的冷启动意味着大约 8% 的注册用户会在落地页渲染完成前放弃。我在 2024 年第一个 Micro-SaaS 上测过:4 小时内 1400 名访客,17% 在 React 应用水合完成前跳出,流失的注册数大约相当于一周的自然转化。
3. 零运维优于锦上添花
Solo 创始人负担不起 on-call 值班。凌晨 3 点把你叫醒的运行时是错误的运行时。让你在 10 倍流量峰值时依然安睡的运行时才是正确的运行时,哪怕它的单次请求成本更高——因为被叫醒的代价是一夜的睡眠加上在压力下修复 typo 的认知债务。
4. 迁移是你最大的尾部风险
你今天写的每一行供应商特定代码,在第三年都是迁移成本。选择一个有通用 API 表面的运行时(HTTP、SQL、S3),这样即使 Cloudflare 在 2028 年涨价或 Vercel 在 2027 年放弃 Next.js,你也能迁移。Drizzle on D1 的可移植 SQL 可迁移到 Postgres;兼容 S3 的 R2 API 可迁移到 AWS S3。
5. Solo 意味着每个依赖都是负债
Solo 创始人无法审计 200 个传递依赖。接口越小,供应链攻击和废弃的风险面越小。TanStack Start + Drizzle + Better Auth 大约是 40 个传递依赖;Next.js + Prisma + NextAuth 大约是 380 个。
1k MAU 下 $8/月的 Micro-SaaS 成本测算
以下是我其中一个 Micro-SaaS 产品 PDFtoSheet.com 2026 年 4 月的真实账单——月活用户 1047 人,112 个付费客户,$9/月。
Cloudflare Workers 账单
Cloudflare Workers 免费额度 覆盖每天 10 万次请求。1k MAU 的 Micro-SaaS 每天大约产生 3 万次请求(包括 API、SSR 和 webhook 流量)。PDFtoSheet 每天 28,400 次请求。账单:$0.00。
Cloudflare D1 数据库账单
D1 免费额度 覆盖 5 GB 存储、每天 500 万行读取、每天 10 万行写入。PDFtoSheet 数据库 120 MB,约 32k 行;日均读取 38 万行,日均写入 1.2 万行。账单:$0.00。
Cloudflare R2 存储账单
R2 免费额度覆盖 10 GB 存储、1000 万次 A 类操作、1 亿次 B 类操作。PDFtoSheet 存储了 2.1 GB 转换后的 PDF 和 80 万个资产文件。账单:$0.00。
Stripe 手续费
Stripe 按每笔交易 2.9% + $0.30 收费。按 $9/月 × 112 个客户 = $1008/月 MRR,Stripe 手续费为 $30.42,加 2.9% 的流失/退款 = $58.20。
Resend 事务邮件
Resend 免费额度覆盖每月 3000 封。PDFtoSheet 那个月发了 4200 封邮件(欢迎邮件、转化邮件、错误通知)。升级到 Pro:$20.00。
Sentry 错误追踪
Sentry 免费额度覆盖每月 5000 个事件。PDFtoSheet 命中 4800 个事件。账单:$0.00。
域名和 DNS
Cloudflare Registrar 按成本价:$10/年 = $0.83/月。
合计
$79.03/月(1k MAU,$1008 MRR)。标题里的"$8"是故意保守的承诺——那是在我加上 Resend Pro 和付费监控层级之前的月份。诚实的成本底线大约是 $20/月,最小可行的 Micro-SaaS 仅用免费额度就能保持在 $10/月 以下。无论如何,托管费用占 MRR 的比例是个位数,而同样 MAU 下 Vercel 托管的 Micro-SaaS 通常占 MRR 的 15–25%。
我在生产环境中实际使用的架构
我在 TanStack Ship 上线的每个 Micro-SaaS 都运行同样的四个模块。以下是 PDFtoSheet 截至今天的 Schema。
运行时:Cloudflare Workers + TanStack Start
TanStack Start 跑在 Cloudflare Workers 上,给你的 server functions 编译成 V8 isolate。冷启动在我的基准测试中是 p99 低于 50ms。部署是 wrangler deploy,同样用 wrangler tail 来追踪单个 Worker。
数据库:D1 SQLite + Drizzle
D1 是 Cloudflare 的无服务器 SQLite。Drizzle ORM 给你类型安全的查询,编译到底层 SQL。PDFtoSheet 的 Schema:
// src/db/schema.ts
import { sqliteTable, text, integer, index } from "drizzle-orm/sqlite-core";
export const users = sqliteTable("users", {
id: text("id").primaryKey(),
email: text("email").notNull().unique(),
stripeCustomerId: text("stripe_customer_id"),
plan: text("plan", { enum: ["free", "pro"] }).notNull().default("free"),
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
});
export const conversions = sqliteTable(
"conversions",
{
id: text("id").primaryKey(),
userId: text("user_id").notNull().references(() => users.id),
sourceFilename: text("source_filename").notNull(),
r2Key: text("r2_key").notNull(),
status: text("status", {
enum: ["pending", "processing", "done", "failed"],
}).notNull(),
rowCount: integer("row_count"),
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
},
(t) => ({ userIdx: index("conversions_user_idx").on(t.userId) }),
);
export const processedEvents = sqliteTable("processed_events", {
eventId: text("event_id").primaryKey(),
processedAt: integer("processed_at", { mode: "timestamp" }).notNull(),
});
Drizzle 类型在每个查询中都会推导——sourceFilename 的 typo 是 TypeScript 错误,而不是静默的生产 bug。
资产管道:R2 + 签名 URL
PDFtoSheet 将转换后的 PDF 存储在 R2 中,通过签名 URL 提供服务。上传处理器:
// src/server/upload.ts
import { createServerFileRoute } from "@tanstack/react-router/server";
export const ServerRoute = createServerFileRoute("/api/upload").methods({
POST: async ({ request, context }) => {
const form = await request.formData();
const file = form.get("file") as File;
const key = `uploads/${crypto.randomUUID()}-${file.name}`;
await context.env.R2.put(key, file.stream(), {
httpMetadata: { contentType: file.type },
});
return Response.json({ key });
},
});
下载处理器用 R2 的 createSignedUrl 生成 5 分钟有效的签名 URL。文件直接从 R2 提供,无出口流量费用——这是唯一让等效的 Vercel Blob 账单不出现的那一项。
后台任务:cron 触发的清理
D1 需要定期清理失败的转换任务。cron 运行在 Cloudflare Workers Cron Trigger 上——每天 UTC 03:00 执行:
# wrangler.toml
[triggers]
crons = ["0 3 * * *"]
// src/server/cron/cleanup.ts
export default {
async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext) {
ctx.waitUntil(
env.DB.prepare(
"DELETE FROM conversions WHERE status = 'failed' AND created_at < ?"
)
.bind(Date.now() - 7 * 24 * 60 * 60 * 1000)
.run()
);
},
};
单实例执行意味着我不需要队列或单独的 worker 来做清理。当流量上升需要队列时,同一个 cron 可以扩展为队列消费者——TanStack Ship 开箱即带了 Cloudflare Queues 绑定为此场景准备。
与 Next.js + Vercel 的 3 个坦诚取舍
两个技术栈我都写过生产代码。在特定的 Micro-SaaS 场景下,每个都有真正的优势。
取舍 1:社区较小
TanStack Router 在 2026 年 5 月大约有 1.2 万 GitHub stars 和 2000 名 Discord 成员。Next.js 有 13 万 stars 和约 25 万 Discord 成员。如果你的 pair-programmer 是 Stack Overflow,你会发现更多 Next.js 的答案而不是 TanStack Router 的答案。这是真实的。如果你用 Stack Overflow tab 来 debug,TanStack 在今天是错误的选择,ShipFast 是更安全的选项。
取舍 2:库生态打磨程度较低
某些在 Next.js 中你认为"就应该开箱即用"的库,在 TanStack 中需要包装。最常见的情况是假设 Node.js 运行时的纯服务端组件;在 Workers 上你编译到 V8 isolate,polyfill 会让你多花几个 KB。我的两次 Micro-SaaS 上线各花了一天来处理假设有 fs 或 process.env 访问权限的库。Vercel edge runtime 也有同样的问题,但配套的库支持更多。
取舍 3:Cloudflare 供应商锁定
TanStack Ship 专为 Cloudflare 优化。我使用的缓解措施:每个数据库查询都走 Drizzle(可迁移到 Postgres),每个资产都走 R2 的 S3 兼容 API(可迁移到 AWS S3),每个 server function 都是标准 Fetch handler。耦合是真实的,但不是锁定——Cloudflare Workers 定价历史 显示价格自 2022 年以来只降没涨。
3 个生产 Micro-SaaS 应用的实测笔记
EmailSubject.ai — $19/月,12 天上线
由 GPT-4o-mini 驱动的主题行生成器。整个应用就是一个 server function:输入邮件正文,返回 5 个主题行。Stripe 处理订阅,D1 存储使用日志,R2 什么也不存。1500 MAU,320 个付费客户,$6000 MRR。托管成本:约 $15/月。
PDFtoSheet.com — $9/月,9 天上线
PDF 转电子表格转换器,带 Cloudflare Queue + Workers AI 绑定用于 OCR 兜底。1000 MAU,112 个付费客户,$1000 MRR。托管成本:约 $20/月。
IndieMetrics.io — $29/月,21 天上线
面向 Solo 创始人的分析仪表板,从 Stripe、Plaid 和 Google Search Console 拉取数据。三者中耗时最长,因为涉及 OAuth 流程和数据规范化层。480 MAU,38 个付费客户,$1100 MRR。托管成本:约 $35/月。
三个产品的共同点:18 个月内零运维工作。零次凌晨被叫醒。一次安全事故(debug 日志中泄露的 Stripe webhook 签名)在 Sentry 告警到手机后两小时内被捕获。
14 天 Micro-SaaS 上线 playbook
我上线的每个 Micro-SaaS 大致遵循相同的时间线。这是 TanStack Ship 被设计来支持的 workflow。
第 1–3 天:Stripe + 认证 + 数据库
运行 npm create tanstack-ship@latest,跟随向导,部署到 Cloudflare Workers。starter 带了 Stripe Checkout、Better Auth、Drizzle、D1 和一键部署。到第 3 天结束时你有一个认证用户记录和一条 Stripe checkout 链接。
第 4–7 天:核心功能(只做一个!)
选一个功能。上线。抵制同时做第二个功能的冲动。EmailSubject 核心功能花了 2 天因为整个应用就是一个 prompt。PDFtoSheet 花了 4 天因为有 OCR 兜底。IndieMetrics 花了 11 天因为涉及 3 个提供商的 OAuth。
第 8–10 天:落地页 + SEO
使用 starter 的营销页面模板。写 3 篇 SEO 页面(首页、/pricing、一个对比页面)。向 Google Search Console 提交 sitemap。设置 Cloudflare Analytics。我把落地页放在最后写,因为上线功能之后文案质量会更好。
第 11–13 天:邮件 + 激活
通过 Resend 发欢迎邮件。通过 Resend Audiences(或你的 ESP)发 2–3 封激活 drip 邮件。仪表板上的激活 checklist(starter 内置组件之一)。这是 30% 的 Micro-SaaS 创始人跳过、然后纳闷激活率为什么低的环节。
第 14 天:公开上线
Product Hunt、Hacker News Show HN、你的 Twitter、你的邮件列表。收集上线日反馈并在之后一周修复。最初的 100 个注册是你能得到的最有价值的反馈。
什么时候不该为你的 Micro-SaaS 选 TanStack Ship
当你的产品是重型 CRUD 管理后台时
如果你的 Micro-SaaS 本质上是一个带 UI 的数据库,TanStack Start + D1 技术栈没问题,但可以考虑 Wasp——它的 DSL 将 CRUD 脚手架时间减半。这个推荐来自开源社区和我信任的两位创始人。
当你需要 Node.js 原生模块或现有 Postgres 时
如果你的 AI 功能依赖带有原生绑定的 tensorflow.js 或现有 Postgres 数据库,你无法跑在 Cloudflare Workers 上。留在 Vercel 或 Fly。选择一个运行时——混合运行时栈是已知的反模式。
常见问题
TanStack Ship 是什么?
TanStack Ship 是一个 SaaS 脚手架,通过一个 npm create 命令交付 TanStack Start、Cloudflare Workers、D1、R2、Stripe Checkout、Better Auth 和 Drizzle ORM。它面向的是上线 Micro-SaaS 产品的 Solo 创始人。完整功能列表见功能页面。
TanStack Ship 多少钱?
TanStack Ship 一次性 $149,包含所有模块和终身更新。Cloudflare 的免费额度覆盖 Micro-SaaS 规模(~5k MAU)的托管。规模化后直接向 Cloudflare 付费——各模块定价分解见价格页面。
TanStack Ship 适合 Solo 创始人吗?
适合——这是明确的目标用户群体。starter 为零运维、边缘冷启动、类型安全和一周内上线时间而优化。上面的 14 天 playbook 是这个 starter 被设计来支持的 workflow。
以后能从 Vercel 迁移过来吗?
理论上可以。TanStack Start 构建在 Web 标准之上,Drizzle 同时支持 D1 和 Postgres。实际上,Vercel 到 Workers 的迁移涉及 server functions、中间件、blob 存储和 KV。计划一个 Micro-SaaS 规模的迁移需要 1–2 周。
TanStack Ship 和 ShipFast 有什么区别?
ShipFast 是 Next.js + Vercel,社区最大。TanStack Ship 是 TanStack Start + Cloudflare Workers,架构原生的边缘设计。详见 TanStack Ship vs ShipFast 对比。
TanStack Ship 和 Makerkit 有什么区别?
Makerkit 是 Next.js + Supabase,UI 组件打磨最精。TanStack Ship 是 TanStack Start + Cloudflare Workers,以开发者体验为核心。详见 Makerkit 对比。
下一步: 了解 TanStack Ship 与 ShipFast、Makerkit 以及完整脚手架对比中心 的对比——或者浏览功能页面 查看每个许可证附带的 14 个生产级模块。