设计 SaaS 数据库架构

第一周做出的错误数据库决策会在未来几年一直困扰你。

SaaS 创始人需要一个能够处理多租户、计费和增长的模式(schema)。如果你做错了,半年后你就得重写整个系统。

以下是构建生产级模式的方法。

1. 选择你的租户策略

你必须隔离不同客户之间的数据。

• 行级(共享数据库):复杂度低。最适合大多数初创公司。在每个查询中使用 WHERE organization_id = ? 过滤器。 • Schema 级(独立 Schema):复杂度中等。适用于合规性需求。 • 数据库级(独立数据库):复杂度高。最适合企业级客户。

对于 90% 的新产品来说,行级多租户是正确的选择。

2. 正确的实体层级结构

不要直接向用户计费。用户会流失,但组织会留存。

层级结构应该如下所示: User ── MemberOf ── Organization ── Subscription ── Invoice

• Users:仅将此表用于身份识别。使用 UUID 以防止攻击。 • Organizations:这是你的租户边界。务必将订阅(subscriptions)与组织关联。 • Memberships:使用关联表(join table)将用户与组织连接起来。将角色(roles)存储在这里,而不是用户表中。

3. 计费与订阅

永远不要使用像 is_active 这样的简单布尔值。这会导致数据混乱。

为订阅使用状态机。常见的状态包括: • trialing • active • past_due • canceled • expired • incomplete

这让你能够处理支付失败和宽限期,而无需手动修复数据。

4. 金额与发票

请遵循以下严格规则以避免财务错误:

• 永远不要使用 FLOATREAL 来处理金额。使用整数来存储分(cents)。例如,$29.99 变为 2999。 • 使用 invoice_line_items 表。你需要它来进行税务报告和退款。 • 如果你根据客户使用产品的程度进行收费,请使用 usage_events 表。

5. 性能优化技巧

• 为外键建立索引。 • 为状态列建立索引。 • 为时间戳列建立索引。 • 避免 N+1 查询。使用 JOIN 在一次查询中获取组织和订阅数据。

一个好的模式在正常工作时是无感的,但在失效时则是灾难性的。

为组织而构建。使用状态机。以整数形式存储金额。

Source: https://dev.to/feidou/designing-saas-database-architecture-users-organizations-subscriptions-and-billing-df

Optional learning community: https://t.me/GyaanSetuAi