39.1 成本模型与单位经济
一句话
成本模型的产出不是“这个月花了多少”,而是每单/每用户/每 GB·月的成本,以及它随规模怎么变;只有单位成本低于单位收入,增长才不等于放大亏损。
三个误区,先拆掉
| 误区 | 现实 |
|---|---|
| 成本 = 云账单 | 云账单通常只占总成本 10%–25%,人力、支付通道、物流、获客才是大头。只盯账单会得出“降本=买更便宜的机器”,而真正的杠杆在别处 |
| 量大就一定便宜 | 只有固定成本占比高时才对。阶梯成本(每 15 万单加一档机器)让单均成本有下限,恒定边际成本决定这个下限在哪 |
| 毛利率高就是好生意 | 毛利率不含获客。毛利率 91%、CAC 回本 24 个月的生意,比毛利率 30%、回本 2 个月的生意危险得多 |
成本的三种形状,决定单位成本的走向
所有成本项只分三类,形状决定“量翻倍时单位成本怎么动”:
| 形状 | 例子 | 翻倍后总成本 | 翻倍后单均成本 | 结论 |
|---|---|---|---|---|
| 固定 | 基线 DB、监控、CEO 工资 | 不变 | 减半 | 规模效应最强,但也最容易“按最小规格买完就忘了它不增长” |
| 阶梯 | 每 15 万单加一组应用实例、每 30 万单加一个分片 | 按档跳 | 阶梯下降,收敛到档单价 ÷ 档容量 | 单位成本有下限,买不满一档就是浪费 |
| 线性 | 出口流量、对象存储、日志、支付通道费 | 同比 | 不变 | 规模效应为零。它是单位成本的“地板”,也是单位经济的真实边际 |
🔑 降本的正确顺序:先删(需求不存在)→ 再压缩(线性项的单位价格,如出口流量走 CDN、日志降采样)→ 再摊薄(把固定项用满)→ 最后才动架构。 反过来做(先上多云、先重构)通常花了钱没降本,因为线性项没动。
单位经济:四个数,一个判据
| 数 | 公式 | 回答什么 |
|---|---|---|
| 单位贡献毛利 | 单价 − 变动成本(变动成本 = 支付 + 履约 + 客服 + 基础设施线性项) | 每卖一单给公司留下多少钱去打固定成本和获客 |
| 盈亏平衡量 | 固定成本 ÷ 单位贡献毛利 | 卖多少单才不亏,与“流水多大”无关 |
| CAC 回本周期 | 获客成本 ÷ 每用户月贡献毛利 | 拉新多久回本,决定“能不能加速投放” |
| LTV / CAC | (月贡献毛利 ÷ 月流失率) ÷ CAC | 一用户终身价值是获客成本的几倍,经验阈值 ≥3 |
判据只有一句:单位贡献毛利为正、LTV/CAC ≥ 3、回本周期小于现金储备能撑的月份数。三条缺一条,规模化就是把亏损放大。
可运行的模型:三桶成本 + 单位经济
示例参数(不是任何厂商报价,也不是行业基准,只用来演示口径);真实模型只需要把参数换成自己的账:
package main
import "fmt"
// 三个桶是成本模型的最小结构:固定、阶梯、线性。
// 单位成本随规模的形状,完全由"固定项占比"和"阶梯粒度"决定,与账单总额无关。
type infra struct {
baseMonthly float64 // 固定:基线容量(最小 DB、监控、工具位),与量无关
stepSize float64 // 阶梯:每多少单需要加一档
stepMonthly float64 // 阶梯:每档多少钱
linearPerOrder float64 // 线性:每单多少(出口流量、日志、对象存储)
}
func (in infra) monthly(orders float64) float64 {
steps := 0.0
if orders > 0 {
steps = float64(int((orders + in.stepSize - 1) / in.stepSize)) // 向上取整:容量不能按小数买
}
return in.baseMonthly + steps*in.stepMonthly + orders*in.linearPerOrder
}
func main() {
// 示例参数:用于演示口径,不是任何厂商报价,也不是行业基准
const (
price = 120.0 // 客单价(元)
payRate = 0.006 // 支付通道费 0.6%
logistics = 8.0 // 物流(元/单)
service = 1.5 // 客服与售后(元/单)
linearInfra = 0.045 // 基础设施线性部分(元/单)
monthlyFixed = 348000.0 // 研发 300k + 运维 40k + 办公 8k
cac = 120.0 // 获客成本(元/新客)
churn = 0.10 // 月流失率
ordersPerUser = 0.5 // 每用户每月下单次数
)
pn := price * payRate
varCost := pn + logistics + service + linearInfra
margin := price - varCost
fmt.Println("【一】单笔订单:变动成本与贡献毛利")
fmt.Printf("客单价 %8.2f 元\n", price)
fmt.Printf("支付通道费 %.1f%% %8.2f 元\n", payRate*100, pn)
fmt.Printf("物流 %8.2f 元\n", logistics)
fmt.Printf("客服与售后 %8.2f 元\n", service)
fmt.Printf("基础设施线性部分 %8.2f 元\n", linearInfra)
fmt.Printf("变动成本合计 %8.2f 元 占客单价 %.1f%%\n", varCost, varCost/price*100)
fmt.Printf("贡献毛利 %8.2f 元 毛利率 %.1f%%\n\n", margin, margin/price*100)
in := infra{baseMonthly: 12000, stepSize: 150000, stepMonthly: 5500, linearPerOrder: linearInfra}
volumes := []float64{300000, 600000, 1200000, 2400000}
fmt.Println("【二】基础设施月账单:固定 + 阶梯 + 线性(基线 12000,每 15 万单加 5500)")
fmt.Printf("%-10s %-6s %10s %10s %10s %10s %10s\n", "月订单", "档数", "固定", "阶梯", "线性", "合计", "单均")
for _, v := range volumes {
steps := float64(int((v + in.stepSize - 1) / in.stepSize))
stepCost := steps * in.stepMonthly
linCost := v * in.linearPerOrder
total := in.monthly(v)
fmt.Printf("%-10.0f %-6.0f %10.0f %10.0f %10.0f %10.0f %10.3f\n",
v, steps, in.baseMonthly, stepCost, linCost, total, total/v)
}
fmt.Println("\n【三】单位成本与边际成本:为什么“量翻倍单位成本降一半”是错的")
fmt.Printf("%-10s %12s %12s %12s\n", "月订单", "单均成本", "边际成本", "较上一档降")
prev := 0.0
for i, v := range volumes {
avg := in.monthly(v) / v
var marginal float64
if i == 0 {
marginal = in.monthly(v) / v
} else {
marginal = (in.monthly(v) - in.monthly(volumes[i-1])) / (v - volumes[i-1])
}
drop := 0.0
if prev > 0 {
drop = (prev - avg) / prev * 100
}
fmt.Printf("%-10.0f %12.4f %12.4f %11.1f%%\n", v, avg, marginal, drop)
prev = avg
}
fmt.Println("\n【四】盈亏平衡与单位经济(月流失 10%、每用户月下单 0.5 次)")
fixedAt600k := in.monthly(600000) + monthlyFixed
be := fixedAt600k / margin
fmt.Printf("60 万单时的总固定成本(含阶梯) %12.0f 元/月\n", fixedAt600k)
fmt.Printf("盈亏平衡单量 %12.0f 单/月\n", be)
monthMargin := margin * ordersPerUser
ltv := monthMargin / churn
fmt.Printf("每用户月贡献毛利 %12.2f 元\n", monthMargin)
fmt.Printf("LTV = 月贡献毛利 / 月流失率 %12.2f 元\n", ltv)
fmt.Printf("LTV / CAC %12.2f (≥3 视为健康)\n", ltv/cac)
fmt.Printf("CAC 回本周期 %12.2f 月\n", cac/monthMargin)
fmt.Println("\n【五】共享成本怎么摊:按 CPU-秒 分给三条业务线")
type line struct {
name string
cpuS float64
share float64
}
lines := []line{{"订单", 7.2e6, 0}, {"搜索", 4.8e6, 0}, {"推荐", 3.6e6, 0}}
var totalCPU float64
for _, l := range lines {
totalCPU += l.cpuS
}
const sharedMonthly = 42000.0 // 网关、配置中心、可观测性等共享平台
for i := range lines {
lines[i].share = lines[i].cpuS / totalCPU
}
fmt.Printf("%-6s %12s %8s %12s\n", "业务线", "CPU-秒/月", "占比", "分摊(元/月)")
for _, l := range lines {
fmt.Printf("%-6s %12.0f %7.1f%% %12.0f\n", l.name, l.cpuS, l.share*100, l.share*sharedMonthly)
}
}
本机运行结果(GO111MODULE=off go run main.go,Go 1.27.1 darwin/arm64):
【一】单笔订单:变动成本与贡献毛利
客单价 120.00 元
支付通道费 0.6% 0.72 元
物流 8.00 元
客服与售后 1.50 元
基础设施线性部分 0.04 元
变动成本合计 10.27 元 占客单价 8.6%
贡献毛利 109.73 元 毛利率 91.4%
【二】基础设施月账单:固定 + 阶梯 + 线性(基线 12000,每 15 万单加 5500)
月订单 档数 固定 阶梯 线性 合计 单均
300000 2 12000 11000 13500 36500 0.122
600000 4 12000 22000 27000 61000 0.102
1200000 8 12000 44000 54000 110000 0.092
2400000 16 12000 88000 108000 208000 0.087
【三】单位成本与边际成本:为什么“量翻倍单位成本降一半”是错的
月订单 单均成本 边际成本 较上一档降
300000 0.1217 0.1217 0.0%
600000 0.1017 0.0817 16.4%
1200000 0.0917 0.0817 9.8%
2400000 0.0867 0.0817 5.5%
【四】盈亏平衡与单位经济(月流失 10%、每用户月下单 0.5 次)
60 万单时的总固定成本(含阶梯) 409000 元/月
盈亏平衡单量 3727 单/月
每用户月贡献毛利 54.87 元
LTV = 月贡献毛利 / 月流失率 548.67 元
LTV / CAC 4.57 (≥3 视为健康)
CAC 回本周期 2.19 月
【五】共享成本怎么摊:按 CPU-秒 分给三条业务线
业务线 CPU-秒/月 占比 分摊(元/月)
订单 7200000 46.2% 19385
搜索 4800000 30.8% 12923
推荐 3600000 23.1% 9692
逐条读这份输出:
- 单均成本从 0.122 降到 0.087,靠的是把量做到 8 倍,只降 28.6%;而边际成本恒定在 0.0817(= 档单价 5500 ÷ 档容量 15 万 + 线性 0.045)。这就是“规模效应有地板”:单均成本只会无限接近边际成本,永远不会低于它。谁跟你说“量大就便宜”,先问边际成本是多少。
- 阶梯是硬边界:30 万单买 2 档、60 万单买 4 档,档数按
ceil(单量/15 万)跳。若实际量只有 16 万单却买了 2 档,第 2 档的 5500 元就是纯浪费——买容量前先算量 ÷ 档容量的余数。 - 盈亏平衡 3727 单/月看起来低(单均毛利 109.73 元、固定成本 40.9 万),这说明高毛利业务“卖得少也不亏”;但它不说明增长赚钱——CAC 120 元、月贡献毛利 54.87 元,回本 2.19 个月,LTV/CAC 4.57 才勉强支撑投放加速。换成 CAC 400 元,LTV/CAC 立刻掉到 1.37,此时增长就是放血。
- 分摊口径会改变结论:按 CPU-秒,订单线吃 46.2%(19385 元);若改按请求数分摊、而搜索的请求更轻,订单线的份额可能升到 60% 以上。同一笔成本,口径不同,问责对象不同——所以分摊规则必须先写清、后算账,不能事后挑一个对自己有利的。
⚠️ 示例参数里物流只占 8 元、没有仓储与退换货,所以毛利率 91.4% 偏高。真实实物电商把退货率 15%、逆向物流、包装仓储加进去,贡献毛利率通常掉到 20%–40%。成本项列全比算得准更重要——漏一项,单位经济就是假的。
云账单怎么变成单位成本:先选分母
| 分母 | 适合 | 陷阱 |
|---|---|---|
| 每 1000 请求 | 无状态 API、网关 | 请求大小差异 100 倍时失真,需再加“每 GB 出流量” |
| 每订单 / 每交易 | 交易型业务 | 免费用户与付费用户混算,要看“每付费单”与“每活跃用户”两条 |
| 每活跃用户(MAU) | 社交、内容 | 不说话的用户也在吃存储与推送成本 |
| 每 GB·月 | 存储、日志、数仓 | 必须同时看“容量单价”和“请求/取回费”,见 39.3 存储分级 |
| 每租户 | B 端 SaaS | 大租户补贴小租户,必须做“分层租户成本曲线” |
选择规则的唯一判据:分母的变动要能解释成本变动的 70% 以上。解释不了,就换分母或拆成两个。
什么时候不该算单位经济
- 内部工具 / 研发平台:用户是员工,没有收入侧,算 LTV 没有意义;看“每工程师每月的平台成本”和“省下的工时”就够。
- 强合规/审计系统:成本由监管要求决定,单位成本再高也得做;此时该算的是“满足同一条款的最低成本方案”。
- 探索期产品(< 1000 用户):样本太小,单位经济噪声大于信号;先看“单次实验成本”和“结论产出率”。
反模式
| 反模式 | 后果 |
|---|---|
| 用云账单代替成本模型 | 漏掉人力、支付、物流、获客,降本方向从一开始就错 |
| 把一次性投入摊进月成本假装便宜 | 前 12 个月好看,第 13 个月成本跳升,预算崩 |
| 只算平均不算边际 | 以为“再加量还能降 30%”,实际边际成本恒为 0.08,加量不降本 |
| 毛利率里漏掉退货与补贴 | 真实毛利率被高估 10–30 个百分点,越卖越亏还以为在赚 |
| 分摊口径事后调整 | 同一个团队这季度 19k、下季度 8k,问责失效,团队开始“优化口径”而不是优化成本 |
| 拿单均成本做跨业务对比 | 客单价差 10 倍的两个业务,单均成本没有可比性;要对比就用“成本占收入比” |
关联
- 前置:4.2 成本-收益分析(该不该投的判断)、5.6 云成本结构(计费维度与优化顺序)
- 并列:39.3 存储分级(把“每 GB·月”这一项算透)
- 下游:39.6 成本驱动的架构决策(待补:单位成本如何反过来改架构)
- 并列:35.2 SLA / SLO / SLI / 错误预算(可靠性也是成本项:多一个 9 的单价)
自检
Q1 团队把月订单从 30 万做到 240 万(8 倍),单均基础设施成本只从 0.122 降到 0.087。老板问“为什么规模效应这么弱”,正确答案是什么?
▸ 答案:因为这项成本的边际成本恒定在 0.0817(阶梯档单价 5500 ÷ 15 万 + 线性 0.045),单均成本只能从 0.122 收敛到 0.0817,理论下限就在那里,8 倍量降 28.6% 已经是极限。要再降只有两条路:① 压低边际成本本身(降档单价、优化线性项——出口走 CDN、日志降采样);② 把固定项占比调高(换更少更大规格的机器),但换完边际成本会跳,得重算一遍。规模效应不是无限的,它的天花板就是边际成本。
Q2 毛利率 91.4%、LTV/CAC 4.57,看起来是门好生意。哪三个数一变,结论就翻转?给出翻转后的算术。
▸ 答案:① CAC 从 120 涨到 400:LTV/CAC = 548.67/400 = 1.37 < 3,投放立刻停止;② 月流失率从 10% 升到 25%:LTV = 54.87/0.25 = 219.5,LTV/CAC = 1.83 < 3,同时回本周期不变但用户只活 4 个月;③ 退货率 30%:每单期望增加 0.3 × (逆向物流 8 + 不退的通道费 0.72) ≈ 2.62 元,再叠加仓储 6 元,贡献毛利从 109.73 掉到约 101,毛利率掉到 84%——毛利仍高,但此时若 CAC 已是 400,结论同样翻转。判据是三条同时看,任何一条恶化都会把“好生意”变成“放血增长”。
Q3 一次账单显示:出口流量费用涨了 3 倍,订单量只涨了 30%。先查什么?按什么顺序查?
▸ 答案:先查分母是否换了——按“每订单 GB”看出口流量是否真的涨;再按顺序查三个高频原因:① 缓存命中率下降(发布改了 Cache-Control、CDN 回源比例上升);② 响应体变大(新增字段把列表接口从 30KB 撑到 200KB);③ 客户端重试放大(超时设置不当导致同一请求打 2–3 次,账单按字节算,重试全收费)。顺序是“先看单位成本、再看单请求体积、最后看请求数”,因为前两个是设计问题(改一次永久省),最后一个是故障问题(会自愈)。
Q4 共享平台月成本 4.2 万,应该按 CPU-秒、请求数还是人头分摊?说出你的选择和它带来的行为。
▸ 答案:按 CPU-秒(本例订单 46.2%、搜索 30.8%、推荐 23.1%)——它跟“谁消耗了共享资源”最接近,且业务方能通过优化自己代码影响这个数。按人头分摊的后果是:人多的团队多付钱,于是团队倾向少招人、把共享成本转嫁给“人头少但用量大”的团队,激励完全错位。按请求数分摊的后果是:大请求(图片、导出)与小请求同价,导出类功能被隐性补贴。无论选哪个,规则必须提前公示并至少稳定两个季度,否则团队会开始优化口径而不是优化成本。