SaaS 应用
从规划到增长,构建并上线多租户 SaaS 产品。
规划与架构
定义范围、选择技术栈、设计数据模型和多租户架构。
为什么
SaaS 规划决定了未来数年的可扩展上限、成本结构和团队速度。一开始就正确处理多租户模型、计费和数据隔离,可避免后续痛苦的迁移。错误的技术栈选择可能导致 6 个月以上的返工。
何时使用
在编写任何生产代码之前。小团队通常 2-4 周,复杂产品 1-2 个月。仅一次性原型可跳过规划。
如何做
1. 定义问题和目标用户
- 写一页 PRD:问题、目标用户、核心流程、成功指标
- 列出 MVP 的 5 个必备功能;其余暂缓
2. 选择技术栈
- 前端:Next.js/Remix(SSR 利于 SEO + 快速交互)
- 后端:Node.js 或 Python(选团队最熟悉的)
- 数据库:PostgreSQL(多租户就绪,JSONB 灵活)
- 认证:Clerk/Auth0(不要自己建认证)
- 托管:Vercel/Fly.io(自动扩缩,按用量付费)
3. 设计多租户架构
- 共享数据库共享 schema(行级 tenant_id)— 最简单,可扩至约 1000 租户
- 共享数据库独立 schema — 隔离更好,复杂度中等
- 独立数据库 — 隔离最强,运维成本最高
4. 设计数据模型
- 核心实体:Tenant、User、Subscription、BillingEvent
- 每个表加 tenant_id 列 + 索引
- 公开 ID 用 UUID(不泄露顺序号)
5. 规划计费和限制
- 选择定价模型:按席位、按用量或分级
- 第一天就集成 Stripe(后期难以改造)
- 按套餐层级定义速率限制
示例
PRD:面向小型开发团队的任务管理
目标:5-50 人工程团队
MVP 功能:看板、任务、评论、1 个集成(GitHub)
技术栈:Next.js + tRPC + PostgreSQL + Clerk + Vercel
多租户:共享 schema,每表加 tenant_id
Schema 草图:
tenants (id, name, plan, stripe_customer_id)
users (id, tenant_id, email, role)
projects (id, tenant_id, name)
tasks (id, tenant_id, project_id, assignee_id, status)
计费:Stripe + 按席位($10/用户/月)
限制:Free=3 项目,Pro=无限,Enterprise=SSO+审计
常见问题
- ⚠过度工程:0 个租户时就为 1 万租户设计 — 从共享 schema 开始
- ⚠跳过计费:在现有应用中改造 Stripe 需 2-4 周痛苦
- ⚠查询无租户隔离:漏一个 WHERE tenant_id = ? 就跨租户泄露数据
- ⚠选前沿技术:未经验证的框架调试成本远超节省
最佳实践
- ✓先写 PRD 再选技术栈 — 技术追随需求,而非反过来
- ✓在 ORM/查询构建器层强制 tenant_id,而非每个手写查询
- ✓第一周就集成 Stripe,即使定价未定 — 数据模型需要它
- ✓第一天就用功能开关,解耦部署与发布
开发与测试
构建 MVP,配备 CI/CD、自动化测试和渐进式增强。
为什么
SaaS 开发是马拉松,不是短跑。没有第一周就建立的 CI/CD 和测试覆盖,技术债务快速复利。有付费客户期望 99.9% 可用性时,每个未测试功能都是负债。
何时使用
规划完成后。MVP 通常 3-6 个月。先做风险最高的功能(计费、多租户)以尽早验证假设。
如何做
1. 第一天就建 CI/CD
- GitHub Actions:每个 PR 跑 lint + 类型检查 + 测试
- 合并到 main 自动部署 staging
- 手动提升到生产
2. 按优先级构建核心功能
- 认证 + 租户引导(第 1-2 周)
- 核心领域功能(第 2-8 周)
- 计费集成(第 8-10 周)
- 打磨 + 边界情况(第 10-12 周)
3. 边开发边写测试
- 业务逻辑单元测试(目标 80%+ 覆盖率)
- API 端点集成测试
- 关键路径 E2E 测试(注册、支付、核心流程)
- 每个 PR 跑全量测试(目标 < 5 分钟)
4. 实现渐进式增强
- 服务端渲染 HTML 无 JS 也能工作
- 交互元素渐进式 hydrate
- 所有异步操作有加载态
- 每个路由段有错误边界
5. 建立可观测性
- 错误追踪:Sentry(免费版覆盖早期阶段)
- 分析:PostHog(可自托管,产品分析)
- 可用性监控:Better Stack 或 UptimeRobot
示例
CI 流水线 (.github/workflows/ci.yml):
on: pull_request
jobs:
- lint (eslint --max-warnings=0)
- type-check (tsc --noEmit)
- test (vitest run --coverage)
- e2e (playwright test --shard=1/3)
全部通过才能合并
测试结构:
src/__tests__/unit/ — 业务逻辑
src/__tests__/integration/ — API 端点
e2e/critical-paths.spec.ts — 注册、支付、核心流程
部署:
PR 合并 -> staging(自动)
打 tag -> production(手动审批)
回滚:vercel rollback(30 秒)
常见问题
- ⚠前 3 个月无 CI — 每次部署都是手动测试的赌博
- ⚠只测正常路径 — 边界情况(空态、并发编辑、支付失败)在生产中崩溃
- ⚠无模块边界的单体 — 一处变更破坏无关功能
- ⚠无错误追踪 — 客户比你先发现 bug
最佳实践
- ✓CI 必须在 5 分钟内 — 开发者会跳过慢 CI 直接推 main
- ✓用 Stripe 测试模式端到端测试计费流程,包括 webhook 和失败
- ✓小步勤部署 — 每周 10 次小变更远胜周五一次大部署
- ✓第一天就装 Sentry — 你需要在客户之前知道错误
上线与增长
发布到生产、获取首批客户、建立增长指标。
为什么
上线是假设与现实的碰撞点。没有正确的埋点,你无法区分'产品不行'还是'营销不行'。前 100 个付费客户验证你的整个论点 — 尽快到达。
何时使用
MVP 功能完整且 CI/CD 全绿时。不要等完美 — 80% 就上线,基于真实反馈迭代。
如何做
1. 上线前检查清单
- 生产环境用真实数据测试
- DNS + SSL 配置好(Cloudflare 前置)
- 隐私政策 + 服务条款上线
- 支持渠道就绪(邮件或 Intercom)
- 分析 + 错误追踪验证
2. 软上线(亲友)
- 邀请 20-50 友好用户
- 观察关键 bug 和 UX 困惑
- 每个用户做 30 分钟访谈
- 修复阻塞问题后再公开上线
3. 公开上线
- 发到 Product Hunt、Hacker News、相关 subreddit
- 写上线博文,讲你的'为什么'
- 提供早鸟价(前 3 个月 5 折)
- 准备 demo 视频或交互式引导
4. 埋点增长指标
- AARRR 漏斗:获客、激活、留存、收入、推荐
- 定义激活事件(如'创建第一个项目')
- 每周追踪每步转化率
- 建立同期群留存表
5. 基于数据迭代
- 周回顾:漏斗最大泄漏在哪?
- 每周修一件事,衡量影响
- 每月访谈 5 个流失用户 — 他们的原因就是你的路线图
示例
上线日检查清单:
[x] 生产部署:v1.0.0
[x] Cloudflare DNS + SSL:已激活
[x] /privacy 和 /terms:已上线
[x] [email protected]:已监控
[x] Sentry + PostHog:接收事件
[x] Stripe:正式模式(非测试)
指标看板(PostHog):
获客:各上线渠道独立访客
激活:24 小时内创建首个项目的比例
留存:D7、D30 同期群留存
收入:MRR、ARPU、流失率
推荐:邀请发送 / 接受
第 1 周结果:
2000 访客,200 注册,80 激活,12 付费
最大泄漏:注册 -> 激活(60% 流失)
行动:简化引导,加空态模板
常见问题
- ⚠无分析上线 — 无法修复无法衡量的东西
- ⚠大爆炸式上线到 1 万用户 — 服务器崩溃,首印象毁掉
- ⚠无激活定义 — '注册数'是虚荣指标,不是增长信号
- ⚠忽视流失用户 — 他们有最有价值的反馈但没人问
最佳实践
- ✓上线前定义激活 — 这是预测长期成功的指标
- ✓先软上线给 20 用户 — 在数千人看到前修复关键问题
- ✓每周追踪 AARRR — 每步 1% 改进复利为 50%+ 收入增长
- ✓每月致电 5 个流失用户 — 定性反馈指导定量修复