Subscription based software 是否可行?
结论
这种模式完全可行,也已被大量商业软件采用。不过,问题中描述的模式更准确地说是 usage-based pricing(按量计费)或 transaction-based pricing(按交易计费),而不只是传统意义上的 Subscription。
它通常适合以下场景:
- transaction 的定义清楚,能够稳定、准确地计量;
- 软件能为每笔 transaction 带来明确的商业价值;
- 客户的使用量与收入或业务规模大致正相关;
- 供应商可以防止漏记、重复计费和数据篡改;
- 客户可以预测、核对和控制账单。
这种模式并不一定比永久许可证、按席位订阅或 upgrade fee 更好。难点通常不在软件开发本身,而在于如何确定计费单位、建立可靠的 metering 系统,并让客户接受这种成本结构。
先区分几种商业模式
常见的软件收费方式包括:
| 模式 | 收费依据 | 典型特点 |
|---|---|---|
| Perpetual license | 一次性许可证 | 客户可长期使用某个版本,维护和升级可能另收费 |
| Subscription | 按月或按年 | 只要订阅有效,就可继续使用 |
| Per-seat subscription | 用户数或席位数 | 容易理解和预算,但不一定反映实际使用量 |
| Usage-based pricing | API 调用量、数据量或计算资源 | 使用越多,费用越高 |
| Transaction-based pricing | 订单、支付、文档或业务交易数量 | 收费与客户业务活动直接关联 |
| Hybrid pricing | 固定订阅费加用量费 | 兼顾收入稳定性与业务增长 |
因此,“每笔 transaction 收取费用,patch 和 upgrade 包含在内”本质上属于按量收费,也可以与固定订阅费组合使用。
为什么这种模式能够运作
收入会随客户的使用规模增长
永久许可证通常在成交时获得大部分收入,后续收入依靠维护合同或版本升级。按交易收费可以带来持续收入,客户的使用规模扩大后,供应商的收入也会增加。
如果软件直接参与订单、支付、物流、报税或文档处理,客户一般更容易接受这种收费关系:
customer value ≈ transaction volume × value per transaction
software fee ≈ transaction volume × unit price
只要软件费用在每笔业务价值中所占的比例足够低,供应商和客户的利益就能保持大致一致。
客户无须单独决定是否升级
在 upgrade fee 模式下,一些客户会拒绝付费升级,供应商因此需要长期维护多个版本。订阅或按量收费一般会把维护和升级包含在服务内,从而减少版本碎片。
这会给开发团队带来一些实际好处:
- 安全修复可以更快部署;
- 无须长期支持大量旧版本;
- 数据迁移路径更加统一;
- 测试矩阵更容易控制;
- 发布计划不必围绕”大版本收费节点”制定。
持续收入可以支持长期开发
产品发布并不意味着软件维护结束。操作系统变化、安全漏洞、法规调整和第三方 API 变更都会持续产生费用。Recurring revenue 可以让人员配置和维护计划更稳定。
不过,按量收入本身未必稳定。客户的交易量可能存在季节波动,经济下行或客户流失也会让收入迅速减少。
为什么它不适合所有软件
“一次 transaction”可能很难定义
最容易产生争议的问题往往是:什么才算一笔可计费交易?
例如,一张订单经历了以下过程:
创建订单 → 修改订单 → 取消订单 → 重新提交 → 拆成两个包裹
这到底是一笔、两笔还是五笔 transaction?测试数据、失败请求、重试请求、退款和内部调拨是否收费,也要提前写清楚。
如果计费单位无法用一句话解释清楚,销售、开发、财务和客户都会遇到麻烦。
客户不喜欢无法预测的账单
固定许可证或按年订阅可能更贵,但预算比较明确。按交易收费则会把业务波动直接反映到账单上。
大客户的使用量增长到一定程度后,尤其容易觉得自己因为业务成功而受到”惩罚”。他们还可能担心:
- 突发流量产生高额费用;
- 软件缺陷导致 transaction 被重复提交;
- 测试和灾难恢复产生计费数据;
- 供应商单方面调整单价;
- 客户无法独立验证 true-up 结果。
因此,常见做法是设置阶梯价格、费用上限、预付额度或年度承诺,而不是简单地用固定单价乘以交易数量。
计量和审计系统成本不低
一旦费用取决于 transaction 数量,计量模块就成了财务基础设施,不能再按普通日志功能处理。它必须应对:
- 重试和重复事件;
- 延迟到达的数据;
- 时区和结算周期;
- 退款与冲正;
- 离线运行;
- 多租户隔离;
- 数据保留与审计;
- 价格变更;
- 合同中的例外条款。
计量错误带来的后果不只是程序异常,还可能造成错收费用、收入损失或合同纠纷。
客户可能绕过计费点
当价格与某个技术事件绑定后,客户自然会设法减少这个事件。有时这只是正常优化,有时则会改变产品的使用方式。
例如,按 API request 收费可能促使客户批量提交;按生成文件数收费可能促使客户合并文件;按订单收费可能让客户先在外部系统聚合订单,再统一导入。
计费单位应尽量对应客户获得的价值,不能只选择最容易统计的技术指标。
本地部署会增加实现难度
SaaS 可以在服务端统一记录用量。本地部署或离线软件则需要把计量结果安全地传回供应商,由此会产生一系列问题:
- 客户是否允许发送业务元数据;
- 无网络环境如何结算;
- 本地管理员能否修改计量记录;
- 计量服务故障是否应该阻止核心业务;
- 客户能否查看并导出原始数据。
对关键业务系统而言,通常不应因为计费服务暂时不可用而停止客户交易。更稳妥的方案是在本地记录用量,异步上报,并在服务恢复后完成对账。
从开发者角度看,主要变化是什么
商业模式不会自动改善软件架构,但会改变开发团队的责任范围。
采用按量收费后,团队除了交付业务功能,还要维护一条完整的计费链路:
业务事件
→ 用量采集
→ 去重与校验
→ 价格计算
→ 账期汇总
→ 客户对账
→ 发票或扣款
这条链路需要具备与核心业务相同级别的可观测性和测试保障。不能只在应用日志里搜索记录,再交给财务人员手工统计。
一个可靠的计量设计示例
假设每个成功处理的订单计为一次 billable transaction。业务系统应为每个事件提供稳定的唯一标识,并通过幂等写入避免重试造成重复计费。
{
"event_id": "evt_01JABC123",
"customer_id": "cus_10042",
"event_type": "order.processed",
"occurred_at": "2026-08-31T09:30:00Z",
"quantity": 1,
"source_transaction_id": "order_88421"
}
数据库可以对 event_id 建立唯一约束:
CREATE TABLE usage_events (
event_id VARCHAR(64) PRIMARY KEY,
customer_id VARCHAR(64) NOT NULL,
event_type VARCHAR(64) NOT NULL,
occurred_at TIMESTAMP NOT NULL,
quantity DECIMAL(18, 6) NOT NULL,
source_transaction_id VARCHAR(128) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
写入时使用幂等逻辑:
INSERT INTO usage_events (
event_id,
customer_id,
event_type,
occurred_at,
quantity,
source_transaction_id
)
VALUES (
:event_id,
:customer_id,
:event_type,
:occurred_at,
:quantity,
:source_transaction_id
)
ON CONFLICT (event_id) DO NOTHING;
计费不能只依赖当前价目表,否则价格调整后,历史账单也可能随之变化。结算时应保存当时实际使用的价格规则和计算结果:
charge = billable_quantity × unit_price
阶梯价格可以按以下方式计算:
前 10,000 笔:0.10 元/笔
接下来 40,000 笔:0.08 元/笔
超过 50,000 笔:0.05 元/笔
例如当月共有 60,000 笔:
charge
= 10,000 × 0.10
+ 40,000 × 0.08
+ 10,000 × 0.05
= 4,700 元
这里的单价仅用于示例。实际价格需要根据产品价值、成本和合同确定。
推荐的落地步骤
1. 先定义客户价值,再定义技术事件
先确认客户为什么愿意付费,再选择计费单位。如果客户从成功订单中获得价值,就不应对失败请求、健康检查或内部重试收费。
合适的计费单位一般有以下特点:
- 客户容易理解;
- 供应商可以客观测量;
- 用量与客户获得的价值正相关。
2. 写清所有边界情况
开发前应先确定计费规则,至少覆盖:
- 成功、失败和取消的 transaction;
- 重试和重复提交;
- 测试环境与生产环境;
- 退款、撤销和冲正;
- 跨结算周期的迟到事件;
- 客户合并、拆分或迁移;
- 免费额度和最低消费。
合同、产品界面和程序实现都应采用同一套规则。
3. 让客户可以自行核对
客户应当能够查看:
- 当前账期的累计用量;
- 用量分类和对应的时间范围;
- 单价及阶梯;
- 免费额度或折扣;
- 可下载的明细;
- 预计账单和费用预警。
如果只有供应商能看到统计结果,客户很难信任 true-up。
4. 将计量与收费分开
计量回答”发生了多少可计费事件”,定价回答”这些事件值多少钱”。不要把单价直接写进业务流程。
Metering: customer A used 12,500 transactions
Pricing: first 10,000 at price X, remaining 2,500 at price Y
Billing: generate statement and collect payment
将三者分开后,价格调整和不同合同会更容易支持,计费规则的修改也不容易影响核心交易。
5. 用混合定价降低双方风险
很多产品更适合采用:
monthly charge = base subscription + usage charge
固定费用为供应商提供最低收入,用量费用则覆盖客户规模增长带来的成本,并反映相应价值。还可以搭配:
- Minimum commitment;
- Volume discount;
- Annual cap;
- Prepaid credits;
- Overage pricing;
- Enterprise negotiated pricing。
与完全依赖 transaction 数量相比,这种方式通常更容易预测。
6. 正式收费前先运行影子计量
上线初期可以记录用量但暂不收费,同时将统计结果与业务数据库、客户记录和人工样本核对。确认系统能够正确处理重复事件、退款、时区和账期边界后,再进入真实结算。
对产品开发可能产生的负面激励
收费方式也会影响开发优先级。
在 upgrade fee 模式下,公司可能倾向于把功能集中到大版本中,以此增加客户升级的理由。订阅模式有利于持续交付,但也可能带来另一个问题:只要客户继续续费,公司就未必有足够动力进行重大改进。
按交易收费还可能让团队优先开发能够增加交易量的功能,却忽略性能、可维护性和用户体验。因此,产品决策还需要参考客户留存、可靠性、安全性和支持成本,不能只看 transaction volume。
需要特别注意的事项
- 不要直接把普通 application log 作为账单依据。日志可能被采样、丢失、重复或清理。
- 不要接受客户端未经校验而自行提交的最终用量,否则数据容易被修改。
- 不要根据数据库的当前状态反推历史交易量。订单一旦被删除或修改,历史数据可能无法复原。
- 不要在计费服务短暂故障时阻断关键业务,应使用持久化队列和异步重试。
- 不要频繁修改 transaction 的定义。技术上可能只是改了一个字段,商业上却可能相当于涨价。
- 涉及支付、医疗、通信或个人数据时,还要根据部署地区评估税务、隐私、数据保留和审计要求。具体要求取决于行业和司法辖区。
最终判断
从 professional developer 的角度看,这是一种合理且成熟的收费模式,但不会自动降低软件开发的难度。
如果产品天然具有定义清楚、可审计且与客户价值一致的 transaction,按量收费通常很有效。它可以支持持续维护,减少升级阻力,并让供应商的收入随客户业务增长。
如果 transaction 定义模糊,客户难以预测费用,软件主要在离线环境中运行,或者用量与客户价值没有直接关系,那么按席位订阅、固定年费、永久许可证加维护费或混合定价可能更合适。
最终决定成败的不是”Subscription based software”这个名称,而是计费单位是否公平、计量系统是否可靠,以及客户能否清楚地理解并验证这笔费用的来源。
备注:内容仅供参考。
