独立产品数据模型:小型 SaaS 也需要清楚的边界
小型 SaaS 容易被误解成“不需要设计”。一个人开发、用户不多、功能很轻,好像直接建几张表就能跑。可独立产品一旦开始收费、协作、同步和导出,数据模型的边界就会变得很重要。早期偷懒,后期会变成迁移成本。
我不主张一开始就上复杂架构,但我会认真区分账户、工作区、项目、资源、权限和订阅。边界清楚,小产品才有生长空间;边界混乱,再极简的功能也会慢慢打结。
一、先确定产品的核心对象
假设做一个 AI 创意笔记工具,核心对象可能是:用户、工作区、项目、素材、生成记录、导出记录。不要把所有东西都塞进 notes 表。表少不等于简单,语义清楚才是简单。
erDiagram
USER ||–o{ WORKSPACE : owns
WORKSPACE ||–o{ PROJECT : contains
PROJECT ||–o{ MATERIAL : stores
PROJECT ||–o{ AI_RUN : generates
PROJECT ||–o{ EXPORT_JOB : exports
这张关系图不复杂,但已经表达了关键边界:用户可以拥有工作区,工作区包含项目,项目里有素材和 AI 调用记录。以后要做团队协作、项目迁移或用量统计,都有位置可放。
二、订阅和用量不要混进业务表
收费产品一定会遇到额度、套餐、试用、续费和退款。如果把这些字段散落在用户表里,后面会很难处理。订阅和用量应该是独立模块。
CREATE TABLE subscriptions (
id TEXT PRIMARY KEY,
workspace_id TEXT NOT NULL,
plan TEXT NOT NULL,
status TEXT NOT NULL,
current_period_end TIMESTAMP NOT NULL
);
CREATE TABLE usage_events (
id TEXT PRIMARY KEY,
workspace_id TEXT NOT NULL,
event_type TEXT NOT NULL,
amount INTEGER NOT NULL,
created_at TIMESTAMP NOT NULL
);
用事件记录用量,比只保存一个余额字段更容易审计。用户问“为什么额度没了”,你能查到每次 AI 调用、导出和生成。独立产品不一定要做重型账务系统,但基本可解释性要有。
三、AI 调用记录要能复盘
AI 产品的数据模型里,生成记录非常重要。至少要记录模板版本、模型版本、输入摘要、输出、用户是否采纳、错误信息和耗时。它既是质量分析依据,也是成本控制依据。
type AiRun = {
id: string;
projectId: string;
templateId: string;
templateVersion: number;
model: string;
inputHash: string;
outputPreview: string;
accepted: boolean | null;
latencyMs: number;
tokenUsage: {
input: number;
output: number;
};
};
注意这里用 inputHash 和 outputPreview,而不是默认保存全部输入输出。创意素材可能敏感,是否完整保存应由产品策略决定。能复盘和尊重隐私,需要一起设计。
四、删除和导出要从第一天考虑
独立产品很容易忽略数据删除。用户删除项目时,是软删、硬删,还是进入回收站?AI 调用记录是否一起删除?导出文件是否保留?这些问题越晚处理越麻烦。
我的做法是给核心对象统一 deleted_at,并建立后台清理任务。导出则使用异步 job,记录状态和下载有效期。
data_lifecycle:
soft_delete_days: 30
export_url_ttl_hours: 24
ai_run_retention_days: 90
hard_delete_scope:
– materials
– generated_outputs
– exported_files
小产品也要给用户安全感。能导出、能删除、能解释数据去向,会让用户更放心地把真实工作放进来。
五、总结
独立产品的数据模型不必复杂,但必须边界清楚。账户、工作区、项目、素材、AI 调用、订阅用量和数据生命周期,都应该有自己的位置。
小型 SaaS 的优雅,不是表少,而是每个表都知道自己为什么存在。这样的结构不会妨碍快速上线,反而能让后续迭代更安静。



