《独立开发者的商业指南·资本与退出》2.3 合伙人协议与退出机制

两位合伙人各 50%、没有书面退出条款,退出就只能靠谈。用 Nord 的 SDE 34,320 与 4.5 倍估值算 50% 股权 77,220 美元,拆开回购、24 个月每月 3,217.50 美元的分期、33.3% 折价的拖售随售与竞业保密四种机制的现金流压力。

以下情境为教学假设,人物与数字不代表经核实的真实案例。

合伙人退出不是「一个人走、另一个人留下」这么简单。它要同时回答四个问题:股权按什么价格买回、钱什么时候付、公司被整体出售时少数方能不能跟、走的人能不能立刻做同类生意。四个问题各自对应一种机制,也各自对应一笔可以算的现金。

Nord Studio 是这一节的主案例:两位合伙人各 50%,没有期权池,没有书面退出条款。年收入 154,320 美元,SDE 34,320 美元;4.5 倍 SDE 的估值锚是 154,440 美元,3.0 倍 SDE 的买方报价是 102,960 美元。50% 股权按 4.5 倍算是 77,220 美元,按 3.0 倍算是 51,480 美元。

四种机制:一张表看清

机制触发价格基础现金节奏主要风险
回购合伙人主动退出或约定事件4.5× SDE × 50% = 77,220一次性或短期公司现金不够,回购拖垮经营
分期买断同上,但现金分年支付同上,可加利息24 个月,每月 3,217.50违约、公司后续经营恶化
拖售/随售整体出售公司3.0× SDE = 102,960,50% 为 51,480交割时少数方被低价拖走,或无法跟售
竞业与保密退出后 24 个月从买断价中留置 20%12 个月后释放范围过宽、执行成本、补偿不足

Nord 没有书面退出条款,所以四种机制都不是「默认生效」,而是要临时谈。50/50 让谈判更慢:任何一方都可以拒绝,退出价格和付款方式都要求双方同时点头。书面条款的价值不是「限制谁」,而是「把谈判从一次性博弈变成可执行的公式」。

回购:77,220 美元有多重

77,220 美元是 50% 股权按 4.5 倍 SDE 算出来的价格。把它放回 Nord 的现金流里,有三种等价的看法:

口径金额覆盖 77,220 需要
年 SDE34,3202.25 年
年税后可支配现金25,7403.0 年
月均 SDE2,86027 个月

三种口径说的是同一件事:一次性回购要拿走公司两年多的 SDE,或者三年的税后现金。Nord 没有披露现金余额,但仅从流量看,一次性付 77,220 美元就意味着把未来两年的经营缓冲全部押上。回购条款如果写「退出时一次性支付」,等于假设公司随时有两年的 SDE 趴在账上;大多数两人服务型公司没有这个余量。

回购价格也不是只有 4.5 倍一个锚。双方可以约定 3.0 倍到 4.5 倍之间的公式,或者用「过去 12 个月 SDE × 倍数 − 未偿债务」的净值法。价格每降 0.5 倍,50% 股权就少 8,580 美元:4.5 倍是 77,220,4.0 倍是 68,640,3.5 倍是 60,060,3.0 倍是 51,480。四个价格之间的差距,比很多条款的谈判时间更值钱。

SDE 倍数企业价值50% 股权价值与 4.5 倍的差额
4.5×154,44077,2200
4.0×137,28068,640−8,580
3.5×120,12060,060−17,160
3.0×102,96051,480−25,740

分期买断:24 个月,每月 3,217.50

把 77,220 美元分成 24 个月,每月是 3,217.50 美元。这个数字放在 Nord 的月度现金流里,压力立刻显形:

对照金额月供占比
月供3,217.50100%
产品订阅 MRR3,51091.7%
月总收入12,86025.0%
月均 SDE2,860112.5%
月税后现金2,145150.0%

月供是月均 SDE 的 112.5%,是月税后现金的 150%。也就是说,光靠经营现金流,公司每个月都差 1,072.50 美元才能付完这笔买断;差额要靠期初现金、增长或者另一条收入线补。把月供和产品订阅对比更直观:3,217.50 美元相当于产品 MRR 的 91.7%,几乎等于把整条产品线的月收入拿去买断。

累计月份累计支付占年 SDE
619,30556.25%
1238,610112.5%
1857,915168.75%
2477,220225.0%

如果 SDE 下滑,覆盖倍数会更难看。教学敏感度如下:

SDE 情景年 SDE年供 38,610 占比
下滑 20%27,456140.6%
下滑 10%30,888125.0%
基准34,320112.5%
增长 10%37,752102.3%

分期买断的结构要点不是「分几期」,而是「公司现金流断了怎么办」。常见保护包括:以退出方剩余股权作质押、约定公司出售时加速清偿、设置宽限期与违约金、把部分对价与未来收入挂钩。这些条款不改变 77,220 美元的总价,但改变「谁承担经营下行的风险」。

拖售、随售与竞业保密

整体出售走的是另一条价格锚。买方按 3.0 倍 SDE 报价 102,960 美元,50% 股权分到 51,480 美元;和 4.5 倍回购的 77,220 美元相比,少 25,740 美元,折价 33.3%。

路径倍数企业价值50% 所得与回购的差
合伙人回购4.5×154,44077,2200
整体出售3.0×102,96051,480−25,740(−33.3%)

拖售条款允许达到约定比例的股东强制其他股东一起出售;随售条款允许少数股东按同等条件跟着卖。两者保护的方向相反:拖售保护买方「买得到 100%」,随售保护少数方「不被落下」。

在 50/50 的结构里,拖售条款的作用有限,因为任何一方都不到 50% 以上,强制出售仍然要两人同意。但引入第三位股东后就不同了:45/45/10 的结构里,45% + 10% = 55%,已经超过半数;如果拖售门槛写成「超过 50%」,第三人那 10% 就成了关键票。第三人按 3.0 倍卖是 10,296 美元,按 4.5 倍卖是 15,444 美元,差 5,148 美元。随售条款让他至少能按同一每股价格跟卖,而不是被留在没有流动性的 minority 位置上。

竞业与保密:24 个月与 20% 留置

竞业与保密条款把「走的人」和「留下的公司」之间的边界画清楚。Nord 的两位合伙人各拿 48,000 美元年薪(两人工资合计 96,000 美元);买断价 77,220 美元分 24 个月,年均 38,610 美元,相当于原年薪的 80.4%。两年合计 77,220 美元,比原年薪两年 96,000 美元少 18,780 美元。

项金额/期限说明
退出方原年薪48,00096,000 ÷ 2
买断年均38,61077,220 ÷ 2
买断/原年薪80.4%每年少 9,390
24 个月合计缺口18,78096,000 − 77,220
竞业期限24 个月教学假设
留置比例20%15,444 美元
留置期限12 个月覆盖竞业期的一半

20% 的留置是 15,444 美元,只覆盖 24 个月竞业期的前 12 个月。如果违约发生在第 13 到 24 个月,留置已经释放,公司只能靠违约金或诉讼追偿。教学假设违约金为买断价的 25%,即 19,305 美元;它比留置高,但执行成本也更高。

竞业条款的边界要用「范围、期限、地域、补偿」四个维度写清楚。范围太宽,退出方无法谋生,条款容易被挑战;范围太窄,起不到保护作用。对 Nord 这种服务型公司,真正的风险不是「合伙人再开一家公司」,而是「合伙人带走前 3 家客户」,这 3 家占收入 48%。竞业条款只能限制行为,不能替代客户关系和合同承继的安排。

把退出写成代码

下面的 partner-exit.ts 把四种机制里的可计算部分固化成函数:buyoutValue 按 SDE × 倍数 × 股权比例算价格,installmentPlan 算等额分期与最后一期尾差,cashPressure 把月供对照月 SDE 与月税后现金,dragDiscount 算拖售折价,holdback 算留置与释放。

// file: src/capital/partner-exit.ts
// tier: L1
// verify: node --test test/capital/partner-exit.test.ts

import { type Cents } from "../core/money.ts";
import { type Bps, applyRate, divide } from "../core/rate.ts";
import { type Result, fail, ok } from "../core/result.ts";

export type BuyoutTerms = {
  sdeCents: Cents;
  multipleBps: Bps;
  equityBps: Bps;
};

export type InstallmentPlan = {
  monthlyCents: Cents;
  lastCents: Cents;
  months: number;
  totalCents: Cents;
};

export type CashPressure = {
  monthlySdeCents: Cents;
  monthlyAfterTaxCents: Cents;
  paymentToSdeBps: Bps;
  paymentToCashBps: Bps;
  shortfallCents: Cents;
};

export type DragComparison = {
  differenceCents: Cents;
  discountBps: Bps;
};

export type Holdback = {
  heldCents: Cents;
  releasedCents: Cents;
};

/** Equity value = SDE x multiple x equity share. */
export function buyoutValue(terms: BuyoutTerms): Result<Cents> {
  if (!Number.isInteger(terms.sdeCents) || terms.sdeCents < 0) {
    return fail("SDE must be a non-negative integer amount");
  }
  if (!Number.isInteger(terms.multipleBps) || terms.multipleBps < 0) {
    return fail("multiple must be a non-negative integer in basis points");
  }
  if (
    !Number.isInteger(terms.equityBps) ||
    terms.equityBps < 0 ||
    terms.equityBps > 10000
  ) {
    return fail("equity must be between zero and 10000 basis points");
  }
  const enterpriseCents = applyRate(terms.sdeCents, terms.multipleBps);
  return ok(applyRate(enterpriseCents, terms.equityBps));
}

/** Equal installments; the final payment absorbs any rounding remainder. */
export function installmentPlan(
  principalCents: Cents,
  months: number,
): Result<InstallmentPlan> {
  if (!Number.isInteger(principalCents) || principalCents < 0) {
    return fail("principal must be a non-negative integer amount");
  }
  if (!Number.isInteger(months) || months <= 0) {
    return fail("months must be a positive integer");
  }
  const monthlyCents = Math.floor(principalCents / months);
  const lastCents = principalCents - monthlyCents * (months - 1);
  return ok({
    monthlyCents,
    lastCents,
    months,
    totalCents: monthlyCents * (months - 1) + lastCents,
  });
}

/** Monthly payment measured against monthly SDE and monthly after-tax cash. */
export function cashPressure(
  monthlyPaymentCents: Cents,
  annualSdeCents: Cents,
  annualAfterTaxCents: Cents,
): Result<CashPressure> {
  if (!Number.isInteger(monthlyPaymentCents) || monthlyPaymentCents < 0) {
    return fail("payment must be a non-negative integer amount");
  }
  if (!Number.isInteger(annualSdeCents) || annualSdeCents <= 0) {
    return fail("annual SDE must be a positive integer amount");
  }
  if (!Number.isInteger(annualAfterTaxCents) || annualAfterTaxCents < 0) {
    return fail("annual after-tax cash must be a non-negative integer amount");
  }
  const monthlySdeCents = Math.round(annualSdeCents / 12);
  const monthlyAfterTaxCents = Math.round(annualAfterTaxCents / 12);
  if (monthlySdeCents <= 0) {
    return fail("monthly SDE must be positive");
  }
  return ok({
    monthlySdeCents,
    monthlyAfterTaxCents,
    paymentToSdeBps: divide(monthlyPaymentCents, monthlySdeCents),
    paymentToCashBps:
      monthlyAfterTaxCents === 0
        ? 0
        : divide(monthlyPaymentCents, monthlyAfterTaxCents),
    shortfallCents: Math.max(0, monthlyPaymentCents - monthlyAfterTaxCents),
  });
}

/** Gap between a full-price buyout and a lower-multiple drag sale. */
export function dragDiscount(
  buyoutCents: Cents,
  dragCents: Cents,
): Result<DragComparison> {
  if (!Number.isInteger(buyoutCents) || buyoutCents <= 0) {
    return fail("buyout value must be a positive integer amount");
  }
  if (!Number.isInteger(dragCents) || dragCents < 0) {
    return fail("drag value must be a non-negative integer amount");
  }
  return ok({
    differenceCents: buyoutCents - dragCents,
    discountBps: divide(buyoutCents - dragCents, buyoutCents),
  });
}

/** Amount held back from closing and the amount released later. */
export function holdback(
  principalCents: Cents,
  holdbackBps: Bps,
): Result<Holdback> {
  if (!Number.isInteger(principalCents) || principalCents < 0) {
    return fail("principal must be a non-negative integer amount");
  }
  if (
    !Number.isInteger(holdbackBps) ||
    holdbackBps < 0 ||
    holdbackBps > 10000
  ) {
    return fail("holdback must be between zero and 10000 basis points");
  }
  const heldCents = applyRate(principalCents, holdbackBps);
  return ok({
    heldCents,
    releasedCents: principalCents - heldCents,
  });
}

/** Buyout price expressed as years of SDE. */
export function sdeYears(
  principalCents: Cents,
  annualSdeCents: Cents,
): Result<Bps> {
  if (!Number.isInteger(principalCents) || principalCents < 0) {
    return fail("principal must be a non-negative integer amount");
  }
  if (!Number.isInteger(annualSdeCents) || annualSdeCents <= 0) {
    return fail("annual SDE must be a positive integer amount");
  }
  return ok(divide(principalCents, annualSdeCents));
}

代码有四个边界。第一,buyoutValue 的乘法顺序是「SDE × 倍数 × 股权」,每一步都取整到美分;先算企业价值再乘股权,避免两次四舍五入叠加。第二,installmentPlan 用 Math.floor 算月供,最后一期吸收余数;本金不能被月数整除时,最后一期会比前面略大。第三,cashPressure 同时给出「月供 / 月 SDE」和「月供 / 月税后现金」两个比率,因为前者看经营,后者看真实可支配现金。第四,holdback 只算留置金额,不算释放条件;释放条件要写在协议里,不能写在代码里。

小结

  • 退出要同时定价、定时、定边界:价格、付款节奏、拖售/随售、竞业与保密,四种机制各自对应一笔现金。
  • Nord 的 50% 股权按 4.5× SDE 是 77,220 美元,等于 2.25 年 SDE、3 年税后现金、27 个月月均 SDE。
  • 24 个月分期每月 3,217.50 美元,是月均 SDE 的 112.5%、月税后现金的 150%;年供 38,610 美元是年 SDE 的 112.5%。
  • 整体出售按 3.0× SDE 是 102,960 美元,50% 分到 51,480 美元,比 4.5× 回购少 25,740 美元,折价 33.3%。
  • 45/45/10 的结构里,55% 的联盟可以拖售 45%;第三人的 10% 在 3.0× 和 4.5× 之间差 5,148 美元,随售条款决定他能不能跟。
  • 买断年均 38,610 美元是原年薪 48,000 美元的 80.4%;24 个月少 18,780 美元,竞业补偿要单独定价。
  • 20% 留置是 15,444 美元,只覆盖 24 个月竞业期的前 12 个月;后 12 个月要靠违约金或其他担保。

阅读导航:上一节:2.2 期权池与归属 · 下一节:3.1 融资材料:一页纸与数据室 。

常见错误与边界

  1. 没有书面退出条款。 Nord 的 50/50 无退出条款,价格、付款、竞业都要临时谈;谈不成就是僵局,3 个月按 SDE 算是 8,580 美元。
  2. 只谈价格,不谈付款。 77,220 美元一次性付是 2.25 年 SDE;分 24 个月每月 3,217.50 美元,是月税后现金的 150%,现金流压力完全不同。
  3. 用 4.5× 回购价去对比 3.0× 出售价。 两个锚差 25,740 美元,折价 33.3%;谈判时要先确定用哪个锚,再谈倍数。
  4. 把拖售条款当成多数决。 50/50 下拖售仍要两人同意;只有引入第三人、出现 55% 联盟后,拖售才真正能强制少数方。
  5. 忽略随售条款。 没有随售,10% 的第三人可能被留在一个没有流动性的 minority 位置;有随售,他至少能按同一每股价格跟卖。
  6. 竞业期限写 24 个月却不给补偿。 买断年均 38,610 美元只有原年薪的 80.4%;竞业限制越久,补偿缺口越大。
  7. 留置比例覆盖不了竞业期。 20% 留置只覆盖 12 个月,竞业期是 24 个月;后 12 个月没有担保,违约只能追偿。
  8. 把买断价当成竞业补偿。 买断价买的是股权,竞业限制限制的是未来收入;两者要分开定价,否则退出方会觉得「拿钱还被限制」。
  9. 忽略客户集中。 Nord 前 3 家客户占 48%;竞业条款限制不了客户跟着人走,客户合同和关系承继要单独安排。
  10. 把结构算术当成法律意见。 本节只算价格和现金流;合伙协议、竞业条款、拖售随售要由当地执业律师起草。

合伙人退出解决「已经进来的人怎么出去」,下一章解决「新钱进来时要看什么材料」。一个是收尾,一个是开场,但用的是同一张 cap table 和同一套估值锚。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「books」更多文章

  1. 《移动游戏产品的架构·商业化与发行工程》附录 C 商业化与发行评审清单
  2. 《移动游戏产品的架构·商业化与发行工程》附录 B 双案例商业化事实表
  3. 《移动游戏产品的架构·商业化与发行工程》附录 A 商业化与发行术语速查