订阅制与按使用计费:从第一天起要存储哪些数据
从数据建模角度解释订阅制与按使用计费:计量器、限额、发票、按比例分摊,以及从第一天起需要保存的记录。

为什么定价模型需要数据计划
定价不仅是你网站上的一个页面。它决定了你必须记录什么、如何报告,以及是否能在数月后解释一笔费用。当你在订阅制与按使用计费之间做出选择时,你也在决定计费数据的形态。
一个简单的订阅通常只需少量信息就能计算:套餐、计费周期、开始日期和折扣。按使用计费需要更多:实际发生了什么、何时发生、属于哪个客户,以及这些使用如何转化为金额。没有这些记录,你仍能发送发票,但无法为其辩护。
后来再加上使用计费而没有规划,通常会在三个方面出问题:
- 你缺乏可信的使用历史,客户因此质疑费用。
- 团队对“使用量”的定义各不相同,使分析沦为猜测。
- 财务无法审计发票,因为原始输入缺失或被覆盖。
目标很无聊但至关重要:每次都能以相同方式计算出相同的发票。这意味着你可以从存储的事实(套餐条款、计量规则、使用事件以及当时生效的确切价格版本)回放计算过程。
“建模视角”只是把计费描述为可以拼装的构件,即便你不是工程师也能理解。想象一个团队聊天产品:
- 订阅:每个 workspace 每月 $99
- 使用:超过 50,000 条消息后每条 $0.01
为了日后支持,你的数据必须能回答:哪个 workspace、哪个月、多少消息、包含了多少,以及哪些价格规则当时生效。
订阅与按使用:实践中的差异
订阅按访问收费,按使用计费按消费收费。一旦出现升级、降级、按比例分摊以及现实世界的边缘情况,它们的行为会截然不同。
订阅的关键问题是客户在某段时间内是否有权使用产品。你主要跟踪套餐、席位数、计费周期以及发票是否已支付。使用量仍然重要,但通常以限额(软或硬)形式出现,而不是作为逐项列出的行目。
按使用计费的关键问题则变为:具体发生了什么、何时发生?你需要可靠的计量、清晰的计费规则以及能解释每笔费用的方式。即便你的界面只展示一个数字(例如 “1,243 API calls”),其背后也必须是一组一致且可审计的事件。
许多 B2B SaaS 团队采用混合定价:基础费用覆盖一部分配额,再对超额部分计费。
常见的混合模式
大多数混合模型可归为几种常见形态:
- 平台基础费加按席位收费
- 基础费加包含单位(消息、任务、API 调用)加超额费率
- 分级套餐加使用附加(仅在启用时计费)
- 最低承诺加使用额度扣减
可预测性对需要预算审批和稳定月度支出的客户很重要。按量付费适用于价值随活动增长的场景(例如“每处理一张发票”),或者当客户试用时希望风险低。
套餐会不断变化。价格、捆绑与包装会演进。以易于扩展的方式设计计费:能新增计量器、引入新分级或改变“包含”的定义,而无需改写历史。一个实用规则是:把客户在收费时的套餐和定价条款保存下来,而不仅仅记录它们当前的状态。
定义可可靠衡量的计量器
计量器是你要收费的确切对象,要写明以保证两个人计数结果一致。它包含三部分:事件(发生了什么)、单位(计数什么)与时机(何时计数)。
大多数争议从此处产生。一方认为按结果收费,另一方按可测活动收费。
让计量器不含糊
选择映射到真实产品行为且能自动记录的计量器。常见示例:
- 席位(可以登录的活跃用户)
- API 调用(成功请求或所有请求)
- 存储(某一时点的 GB,或周期内的平均值)
- 消息(发送、送达或打开)
- 计算分钟(某个作业运行的时间)
然后定义哪些计入、哪些不计。如果按 API 调用计费,就要决定重试是否计入、4xx/5xx 响应是否计入,以及内部集成调用是否计入。
时机与单位同样重要。席位通常以计费期内某一时点的快照计数更合适。API 调用通常在窗口内求和。存储更棘手:客户期望为“你存了多少”付费,通常意味着按时间平均计算,而不是按峰值计费。
还要决定作用范围:按 account 还是按 workspace/project。简单规则是:如果团队可以单独计费,计量器就应按 workspace。
限额、分级与授权
授权是基于客户购买内容而允许其做什么的规则。它回答例如:能添加多少用户?哪些功能被启用?每月允许多少容量?授权位于访问与计费之间:它决定产品允许什么,而计量记录实际发生了什么。
将授权与计量逻辑分离。授权应可读且稳定(套餐、附加项、合同条款)。计量会随着产品演进(新增事件、新计量器)而变化,你不希望每次计量器变更都冒着破坏访问的风险。
硬限制、软限制与超额计费在界面上可能看起来类似,但行为截然不同:
- 硬限制在达到上限后阻止操作。
- 软限制允许操作但发出警告并标记以便后续跟进。
- 超额计费允许操作并对额外使用收费。
- 宽限期会临时把硬限制当作软限制处理。
- 试用与免费层通过授权生效,但定价通常在某个日期或阈值之前为零。
提前决定超出限额时如何处理。举例:Starter 套餐包含 5 个席位和每月 10,000 次 API 调用。如果邀请第 6 个用户,你是阻止邀请、对超出席位收费,还是允许并给予 7 天宽限?每个选择需有规则,能在发票与支持日志中展示。
把授权存为有时间边界的记录:客户、套餐或附加项、开始与结束时间戳、限额值以及执行模式(硬、软、超额)。这样能确保访问决策与计费决策一致。
可审计的发票与计费周期
发票不仅仅是 PDF。它是能回答:谁被收费、为何收费、针对哪些日期并依据哪些规则的审计线索。如果你更改了价格,仍应能精确重建旧发票。
从几个核心记录开始:Customer、Subscription(或 Contract)、Billing Period 以及包含行项的 Invoice。每个行项应指回其来源:套餐费用、使用汇总或一次性费用。正是这种关联让发票在出现争议时可解释。
计费周期需要锚点与时区。“每月”并不足够。存储周期锚点日期(例如每月 15 日 00:00)以及用于划分周期的时区。保持一致,否则在夏令时变更时会出现一天偏差的错误。
可审计的发票通常需要:
- 每张发票与每个行项都有 period_start 与 period_end
- 该发票使用的价格版本(套餐/价格 ID)
- 不可变总额:小计、税费、折扣、应付金额与货币
- 任何基于使用的行项的确切使用窗口
- 外部支付引用(如支付处理器的 charge ID),在适用时
收入确认与收费相关但不相同。预付订阅费通常在服务期内按比例确认,而使用通常在交付时确认。即便仅保留高层信息,也要存足够的日期以便日后支持。
把贷项通知单、退款与调整当作一等记录处理,绝不编辑旧发票。如果客户在计费期中升级,创建一条调整行或贷项通知,引用原发票并说明所用的按比例规则。
幂等键对发票生成与付款尝试至关重要。如果一个任务运行两次,你希望只产生一张发票、一笔扣款并有清晰日志。
按比例分摊与期中变更
期中变更是计费争议的高发地。如果有人在 20 号升级、暂停一周然后取消,你需要把这些操作转换为发票上能看懂的数字。
决定允许哪些变更及何时生效。许多团队选择升级立即生效以便客户立刻获得价值,但把降级延后到续订以避免复杂退款。
选择一个你能解释的按比例策略
按比例可以按天、按小时或不按比例。越精确,你需要记录越多的时间戳、四舍五入规则与边缘情况并对其进行测试。
尽早锁定策略选择:
- 升级立即按比例,降级延后到续订
- 使用日级按比例(比小时更简单,通常也足够公平)
- 定义四舍五入规则(例如四舍五入到最接近的分)
- 决定暂停如何处理(退还时间或延长周期)
- 设定取消时的退款策略(全额、部分或不退)
将按比例建模为发票行项
避免隐藏计算。把按比例明确表示为发票上的调整,例如对新套餐剩余时间的借项和对旧套餐未使用时间的贷项。每个行项应指向导致该项的具体变更事件(change_id),并包含按比例窗口(start_at、end_at)、数量/时间基准和税类。
计量器在套餐变更时还需决定:计量是否重置、继续累积或拆分为段?简单且可审计的方法是按套餐版本对使用进行分段。例如:客户在月中从 10 个席位升级到 25 个席位。你保留使用事件原样,但在计价时按当时生效的授权期间对它们分组。
决定哪些操作可逆。一个实用做法是将使用事件一旦接受视为最终,而订阅变更仅在发票最终化前可逆。存储变更事件与发票调整,以便在规则演进时能干净地重新生成发票。
从第一天起必须存储的数据
如果等到客户抱怨后再设计计费数据,你会陷入猜测。无论你选择订阅、按使用或混合 B2B SaaS 定价模型,最安全的起点是一组能在事后审计的记录。
从清晰的客户层级开始。在 B2B SaaS 中,付款方通常是公司账户,但使用发生在 workspace 或 project 内,操作由个人用户触发。存储这三层(account、workspace、user)并记录谁做了什么。计费争议常常变成“这是哪个团队做的?”。
一个支持真实发票與清晰调查的最小计费数据库设计包括:
- 账户与组织结构:account、workspace(或 project)、users、roles、账单联系人与税务字段(如需)
- 订阅:套餐、状态、开始/结束日期、续订设置、取消原因以及开始时应用的价格版本
- 价格目录:产品、套餐组件(基础费、席位、计量器)、分级、货币与生效日期
- 使用计量数据:不可变的追加式事件日志,带时间戳、workspace、user(如有)、计量器名、数量与唯一幂等键
- 发票制品:计费周期边界、行项、总额、税费/折扣调整以及使用的输入快照
不要只依赖聚合计数。为速度保留计数器,但把事件日志当作事实来源。一个简单规则是:事件是不可变的,纠正以新事件形式出现(例如负数量),且每个事件都关联到特定的计量器定义。
示例:客户说他们上月的“API 调用”翻倍。如果你能按 workspace 与天拉出原始事件,就能展示峰值来源或发现集成环路。
步骤:从使用事件到发票
难点不在数学,而在于能在数月后仍然解释清楚结果,即便套餐、价格与客户发生了变化。
1) 先有可时光旅行的价格目录
建立带生效日期的产品、套餐、计量器与价格。绝不覆盖旧价格。如果客户在三月被收费,你必须能用三月的目录重新运行三月账单。
示例:“API Calls” 从 4 月 1 日起价格为 $0.002。三月发票仍应使用旧费率。
2) 快照客户在周期内的授权
在每个计费期开始(或变更发生时),存储授权快照:套餐、包含单位、限额、分级规则、折扣与税务设置。把它看作该期我们所承诺的内容。
3) 摄取使用事件并尽早验证
使用应以不可变事件形式到达:时间戳、客户、计量器、数量与用于去重的唯一 id。在入口处验证基础项(缺失计量器、负数量、不可能的时间戳),并记录原始事件,即便同时也保存清洗后的版本。
然后分两步计算:
- 将事件聚合为每个客户、计量器与计费期的总量(并保留聚合版本)
- 使用目录和授权快照(包含单位、超额价、分级)把总量计价为费用
生成引用精确输入(目录版本、快照 id、聚合 id)的发票行项。
最后,锁定发票。存储计算输入与输出,标记为最终,并在晚到事件到来时阻止其更改。晚到事件应计入下一张发票或作为单独调整并附清晰审核注释。
客户与内部报告需求
客户不关心你选择了订阅还是按使用计费。他们关心的是你的数字是否与他们自己的匹配,以及能否在发生前预测下一笔费用。
面向客户的报告最好是一个简单的计费首页,能在无需支持单的情况下回答几个问题:
- 我在用哪个套餐?包含哪些内容?
- 本期我用了多少?如何计数?
- 我的限额是多少?超限会怎样?
- 计费周期何时结束?预计下次账单是多少?
- 在哪里能查看历史发票和付款?
在内部,支持与财务需要能解释一个数字,而不仅仅展示它。这意味着要能发现峰值、追踪变更,并把预览计算与最终发票区分开。
将账单预览与发票分开。预览可在晚到使用或计量器定义改进时重新计算,但发票必须不可变。
内部报表应便于标记异常(突增的使用、负使用、重复事件)、从原始使用与规则重现发票行项,并查看期内的套餐变更与发票按比例规则。
审计轨迹比大多数团队想象的重要。若客户说在某日升级,你需要时间戳、执行者(用户、管理员、自动化)以及套餐、席位、限额与计量率的精确前后值。
在保留策略上,长期保存原始使用事件与最终化的发票制品是实用的。规则是:如果某条数据能改变收费金额或帮助在争议中辩护,就将其不可变地保存。
导致计费争议的常见陷阱
大多数计费争议并非出于价格本身,而是当你无法解释发票上的某个数字,或相同输入后来产生不同总额时发生。
常见错误是仅保存月度总量。没有原始事件,你无法回答“是哪一天把我们推过阈值?”之类的问题。要保留事件,然后再做聚合。
另一个常见问题是在未版本化计量器定义的情况下改变其含义。“活跃用户”可能起初定义为“至少登录过一次”,后来变为“创建了记录”。如果不对计量器定义进行版本控制,客户会把旧发票与新发票对比,而你无法证明当时适用的规则。
争议通常来自如下模式:
- 仅在 UI 强制授权(后端仍允许额外使用或阻止有效使用)
- 用一个时间戳字段处理所有用途(事件时间、摄取时间、计费周期时间混淆)
- 忽略时区(本地时间 00:30 的使用进入了错误的日或月)
- 忘记计费锚点(有些客户在每月 1 号计费,有些在注册日计费)
- 缺乏套餐、价格与限额变更的审计轨迹
示例:一位东京客户在本地时间 31 号升级。如果你只存 UTC 时间戳而没有计费锚点,升级在系统中可能显示为 30 号,从而把按比例与使用移入错误周期。
失去信任最快的方式是无法重现旧发票计算。存储输入(事件、版本、锚点与应用的价格),以便即便产品变动,你仍能重新运行相同逻辑并得到相同结果。
上线计费前的快速检查
上线前做一项演练:随机选一个客户,仅用存储的数据重建其最后一张发票。如果你需要“当时代码做了什么”,说明你没有审计轨迹。
确保每个计量器都不含糊。计量器需要明确单位(请求、席位、GB、分钟)、可信来源(哪个服务发出)与时间窗口(每日、每计费期、每月)。如果你不能一句话解释计量器,客户不会信任它。
能捕捉大多数计费问题的快速检查包括:
- 你能从输入重放发票:套餐版本、价格、使用总量、税费、折扣与按比例参数
- 使用事件是追加式、不可变且去重(幂等键或事件 id)
- 套餐与价格变更带生效日期版本(不覆盖旧价格)
- 按比例规则以明文记录并有测试覆盖
- 支持能用相同保存的事实快速回答“我为什么被收费?”
示例:客户在 18 号把席位从 10 提升到 25,并在 23 号达到使用阈值。你的系统应显示 (1) 每个日期哪个套餐版本生效,(2) 席位变更事件与时间戳,(3) 所用的按比例公式,以及 (4) 汇总到最终总量的使用事件。
下一步:在不把自己逼入绝境的情况下实现
从小处开始,但不要模糊。最安全的路径是能在未来回答一个问题的最小数据模型:我们为什么收取这笔金额?
在第一次改价前尽早原型你的计费模式与管理界面。如果等到销售要求新分级或期中升级,你会在太多地方打补丁。
一个实用的分工是:让 Stripe 处理扣款、收据与付款重试,但把 rating(如何把使用转成行项)保留在你自己的系统中。这意味着你要存原始使用事件、价格版本以及用于生成发票预览的计算结果。
一个保持灵活的简单上线计划:
- 选择 1-2 个你能可靠衡量的计量器(例如每日活跃席位与 API 调用)
- 从第一天起对定价规则进行版本化,以便旧发票仍与旧规则一致
- 构建内部计费管理面板以查看使用、覆盖、贷项與争议
- 添加基本客户门户视图:当前套餐、本期使用、预计账单
- 把每张发票当作可审计的快照,而不是重新计算的猜测
如果你想快速推进而不写大量自定义后台代码,可以在 AppMaster 中建模这些实体,并使用其可视化工具构建管理与门户界面,同时把 PostgreSQL 作为事件与发票的事实来源。
具体示例:你用一个席位计量器上线。三个月后你新增存储 GB。如果计量器、授权与定价规则有版本控制,你就能在不破坏旧发票的情况下引入新计量器,支持团队也能在几分钟内解释任何行项。
常见问题
从确定你日后需要证明什么开始:为什么客户被收取了这笔费用。订阅需要套餐、周期和授权历史;按使用计费需要不可变的记录,说明发生了什么、何时发生以及适用的是哪套价格规则。
如果你不能从存储的输入中重放发票,就无法可靠地回答争议或审计。最稳妥的做法是存储有时间边界的套餐条款、带生效日期的价格版本、原始使用事件,以及发票最终化时使用的确切计算输出。
一个好的计量器是两个人可以以相同方式计数的东西。定义事件、单位和时间窗口,并写清哪些计入哪些不计(例如重试、失败请求或内部调用),以避免中途改变含义。
硬限制会阻止操作,软限制会警告但允许,超额计费会允许并对额外使用收费。为每个授权选择一种行为,并以带开始/结束时间戳的规则形式存储,以便支持、产品与计费做出一致决策。
它们解决不同问题:授权控制客户允许做什么,计量记录实际发生了什么。分离二者可以避免计量器更改意外破坏访问,同时也让发票更易解释。
存储追加式不可变的使用事件日志作为事实来源,同时可选地保留聚合以提升速度。事件应包含时间戳、客户范围(如 workspace)、计量器名、数量和唯一幂等键,防止重复计费。
绝不覆盖旧价格或套餐规则;新增带生效日期的版本。再在发票上记录适用的价格版本(通常也记录到授权期间),这样即使包装变更也能精确重建旧发票。
月度计费需要计费锚点和时区,而不仅仅是“每月”。一致地存储 period_start 与 period_end,并明确区分事件时间与摄取时间,以避免时区和夏令时引发的偏差。
选择一句话就能解释清楚的策略,并把数学以显式发票行项建模(贷项与借项,关联变更事件与按比例窗口)。日级按比例通常是常见默认,因为比小时级更易测试与辩护。
将最终发票视为不可变快照,晚到的使用作为新的调整或计入下期并附说明。预览可随时重新计算,但已最终化的发票不应在新事件到来时改变。


