背景

2024 年 Q4,团队需要为产品添加实时协作功能。类似 Figma/Notion 的多人同时编辑。

时间压力:

  • 距离 Demo Day 还有 2 个月
  • 投资人期望看到”协作”功能
  • 竞品已经有了这个功能

技术选项:

  • 集成现成方案:如 Yjs, ShareDB, Liveblocks
  • 自建协作引擎:完全自主开发

表面上看,集成方案明显更快。但 6 个月后回看,事情没那么简单。

可选方案

方案 A:集成 Yjs(看起来最快)

Yjs:开源 CRDT(无冲突复制数据类型)库,广泛使用。

预估时间:

  • 集成:2 周
  • 测试:1 周
  • 上线:3 周

优点:

  • 开箱即用,文档完善
  • 社区活跃,问题容易解决
  • 已被 Figma/Linear 等大公司验证

隐藏成本(我们当时没看到):

  1. 定制困难

    • Yjs 的数据结构是固定的(Text, Array, Map)
    • 我们的数据模型不完全匹配
    • 需要写大量适配层
  2. Bundle 体积

    • Yjs 核心库:~50KB(gzipped)
    • 加上 WebSocket 和编码器:~80KB
    • 我们原本的前端 bundle:200KB → 280KB(+40%)
  3. 调试困难

    • 出问题时,需要深入理解 CRDT 算法
    • 文档覆盖不了所有边缘情况
    • 社区回答:“这是预期行为”(但不符合我们的需求)

方案 B:集成 Liveblocks(付费方案)

Liveblocks:专门做实时协作的 SaaS,类似 Firebase。

预估时间:

  • 集成:1 周
  • 测试:1 周
  • 上线:2 周

优点:

  • 最快的方案
  • 托管服务,不需要运维
  • 开箱即用的 UI 组件(光标、存在感)

隐藏成本:

  1. 价格不透明

    • 免费版:100 个活跃用户/月
    • 增长版:$99/月,500 个活跃用户
    • 我们有 2000 个日活用户 → $499/月起
    • 如果到 10000 DAU:$2499/月
  2. 供应商锁定

    • 数据存在他们的服务器
    • API 是专有的,迁移成本高
    • 如果他们涨价或倒闭,我们被动
  3. 功能受限

    • 只支持他们定义的数据结构
    • 不能定制冲突解决策略
    • 不能接入我们的认证系统(需要改造)

方案 C:自建协作引擎(我们最终的选择)

预估时间:

  • 设计:2 周
  • 开发:6 周
  • 测试:2 周
  • 上线:10 周

优点:

  • 完全符合我们的数据模型
  • 没有供应商锁定
  • 没有额外的订阅成本
  • 完全掌控

隐藏成本:

  • 需要深入学习 CRDT/OT 理论
  • 需要建立运维基础设施
  • 需要长期维护

判断逻辑

1. 时间成本 vs 长期成本

方案集成时间6 个月后总成本2 年后总成本
Yjs3 周3 周 + 4 周适配 + 2 周调试 = 9 周9 周 + 定制需求积压
Liveblocks2 周2 周 + $2994(6个月费用)2 周 + $12000(2年) + 迁移成本
自建10 周10 周10 周 + 少量维护

关键洞察:

“快速集成”的成本不是一次性的,而是复利式增长的。

2. 真实的时间线(回顾)

Yjs 方案(我们先试的):

  • Week 1-2:集成基本功能 ✅
  • Week 3-4:发现数据结构不匹配,写适配层 ⚠️
  • Week 5-6:处理边缘情况(并发冲突、撤销/重做) ⚠️
  • Week 7:用户反馈”有时候编辑会丢失” 🚨
  • Week 8-9:深入调试 Yjs 内部逻辑,发现无法满足需求
  • 结论:放弃 Yjs,转向自建

自建方案:

  • Week 1-2:学习 CRDT 理论,设计数据结构
  • Week 3-8:开发核心引擎
  • Week 9-10:测试和优化
  • Week 11:上线
  • 6 个月后:稳定运行,零技术债

实际总时间:9 周(Yjs) + 11 周(自建) = 20 周

如果一开始就自建,只需要 11 周。

3. 决策框架:什么时候该自建?

我们总结了一个矩阵:

判断维度倾向集成倾向自建
是否核心竞争力
定制化需求
长期维护意愿
成本敏感度不敏感敏感
时间压力极高(<2周)可控(>1月)

实时协作对我们来说:

  • ✅ 核心竞争力(产品卖点之一)
  • ✅ 高度定制(独特的冲突解决策略)
  • ✅ 愿意长期维护
  • ✅ 成本敏感(Liveblocks 太贵)
  • ⚠️ 时间可控(可以推迟 1 个月)

结论:自建是正确的选择。

4. 真实案例:其他公司的选择

Figma:自建

  • 原因:实时协作是核心价值
  • 结果:性能和体验都是行业最佳
  • 成本:投入了专门的团队,持续优化

Notion:先集成后自建

  • 2016-2018:使用 Firebase
  • 2019:因为成本和性能问题,自建
  • 现在:完全自主的协作引擎

Linear:集成 Yjs

  • 原因:协作不是核心卖点,工程管理才是
  • 结果:快速上线,效果够用
  • 成本:接受 Yjs 的一些限制

关键洞察:

不是”自建 vs 集成”的对错,而是”在这个阶段,对这个团队,什么是最优解”。

决策

我们选择:方案 C(自建协作引擎)

具体实施

1. 架构设计

[客户端]
  ↓ WebSocket
[协作服务器]

[PostgreSQL + Redis]
  • 使用 OT(Operational Transformation) 而非 CRDT
    • 原因:OT 对我们的文档模型更友好
    • 权衡:需要中心化服务器,但我们本来就有

2. 技术选型

  • 后端:Node.js + Socket.io
  • 算法:改进版的 OT(参考 Google Docs 的论文)
  • 存储:PostgreSQL(文档历史)+ Redis(实时状态)

3. 分阶段交付

  • Phase 1(4 周):基本的多人编辑
  • Phase 2(3 周):冲突解决和撤销/重做
  • Phase 3(3 周):性能优化和压力测试

4. 风险缓解

  • 提前 2 周和利益相关方沟通,调整预期
  • 并行进行产品其他功能开发
  • 设置”最小可用版本”(MVP)阈值

后果与反思

6 个月后的数据

技术指标:

  • 延迟:平均 50ms(低于 Yjs 的 100ms)
  • 冲突解决准确率:99.8%
  • 服务器成本:$120/月(vs Liveblocks 的 $499/月)

产品指标:

  • 协作功能使用率:65%(超出预期)
  • 用户反馈:“比竞品流畅”
  • NPS 提升:+12 分

团队收获:

  • 3 个工程师深入理解了分布式协作算法
  • 建立了可复用的实时通信基础设施
  • 增强了团队信心:“我们能解决硬问题”

意外的好处

1. 成为招聘亮点

在招聘时,候选人对”自建实时协作引擎”很感兴趣。

“大多数公司直接用 Firebase,你们敢自己做,说明技术实力强。” - 一位 Senior 候选人

2. 衍生的技术能力

基于协作引擎,我们还做了:

  • 实时通知系统
  • 活动流(Activity Feed)
  • 多人在线状态

这些功能如果用 Liveblocks,需要额外付费。

3. 产品差异化

因为完全自主,我们可以做一些竞品做不到的功能:

  • 自定义冲突解决策略
  • 细粒度的权限控制
  • 与我们的版本控制系统深度集成

如果重来一次

我会改变的:

  1. 不浪费 9 周在 Yjs 上

    应该一开始就做更深入的技术评估,而不是”先试试看”。

  2. 更早引入技术顾问

    我们在 Week 5 才意识到 CRDT vs OT 的选择很关键。应该更早请教专家。

  3. 更激进的 MVP 定义

    我们花了 3 周做”完美的撤销/重做”,但上线后发现用户很少用。应该先上基础功能。

我不会改变的:

  • 选择自建的决策
  • 投入时间深入理解理论
  • 分阶段交付的策略

更深层的思考:速度的陷阱

这次经历让我重新思考”快”的定义。

两种”快”:

  1. 局部快(Local Speed)

    • 从开始到第一个版本上线的时间
    • 这是”集成方案”擅长的
  2. 全局快(Global Speed)

    • 从开始到达成最终目标的时间
    • 包括迭代、调试、重构的总时间

关键洞察:

局部最优 ≠ 全局最优

集成方案的隐性成本:

看起来的成本:2 周集成
实际的成本:
  2 周集成
  + 4 周适配
  + 2 周调试
  + X 周被迫妥协的功能
  + Y 周技术债务
  = ?

自建方案的成本:

预期成本:10 周
实际成本:10 周
未来成本:可控

决策原则:什么时候该自建?

经过这次经历,我总结了一个决策树:

问题 1:这是你的核心竞争力吗?

  • 是 → 继续
  • 否 → 集成

问题 2:你能否接受供应商的限制?

  • 能 → 集成
  • 不能 → 继续

问题 3:你有时间和资源自建吗?

  • 有 → 自建
  • 没有但可以争取 → 推迟上线时间,自建
  • 完全没有 → 集成

问题 4:6 个月后你还想维护这个功能吗?

  • 想 → 自建
  • 不想 → 集成

延伸思考:技术债务的本质

技术债务不仅是”写得不好的代码”,更是”不合适的依赖”。

依赖外部库/服务本身就是债务:

  • 你依赖他们的更新节奏
  • 你依赖他们的决策
  • 你依赖他们不倒闭

自建虽然慢,但负债更清晰:

  • 知道哪里有坑
  • 知道如何填坑
  • 知道坑的深度

类比:

集成方案像是租房:快速入住,但受制于房东。 自建方案像是买房:前期投入大,但长期收益高。


Decision Date: February 2, 2025 Decision Maker: CTO + Engineering Team Lead Stakeholders: 全体工程团队、产品团队 Status: ✅ Validated(6 个月数据证明决策正确) Next Review: August 2025 Total Cost: 10 周开发 + 约 $2000 服务器成本(vs Liveblocks 的 $12000) ROI: 节省 $10000,获得完全掌控