API 废弃计划:写进契约里的兼容通知

API 废弃计划:写进契约里的兼容通知
Spec Coding 编辑部 · Spec-First 工程实践内容

如何从第一天起就把废弃计划写进 API 契约:Sunset 响应头、废弃时间线、客户沟通节奏,以及真正关键的用量上报步骤。如果一个接口上线时连"怎么死"都没写清楚,那它的设计就还没完成。

发布于 2026-03-09 · ✓ 已更新 2026-05-06 · 阅读约 6 分钟 · 作者:Spec Coding 编辑部 · 审校:编辑与事实核查政策

Deprecation 是上线日的事,不是下线日的事

我从没见过哪个团队能"顺利"下线一个上线时没规划过下线的接口。那些真正成功下线的接口,原始契约里就写好了 sunset 策略。那些失败的案例,通常是跑了六个月的 Slack 宣传,时间线延了两次,最后下线当天还是被 VP 拉进电话会议——因为某个没人追踪的支付集成挂了。

这是结构性原因。接口一旦上线,每个接入的客户都会默认它的形状永远不变。如果你在签约时没告诉他们 v1 有 sunset 时间线,也没承诺会测量他们的调用量并把具体数字邮件发给他们,那你手里根本不是废弃计划,是一份祈祷书。

你本该已经在发的 RFC 标准信号

有三个机器可读的信号。每个已废弃接口的响应都应该同时带上这三个,而你的契约应该承诺:从宣布废弃那一刻起就开始发。

如果你的客户端库不把这些响应头作为警告浮现出来,客户就会漏掉。对于那些不解析新头的老 HTTP 客户端,我会额外加一个 Warning: 299 - "Deprecated API",并且在服务端把每一次调用废弃接口的动作都记下来——客户 ID、接口、时间戳。

没有度量就没办法废弃

这是大多数团队会跳过的一步,但它决定了计划是不是真的。在宣布废弃之前,你需要至少 90 天的、按客户、按接口的调用日志。不是聚合指标,不是 Dashboard,而是一条你能跑出来的查询:客户 X 上周调用了 GET /v1/invoices 41,203 次,分布在这 7 个 IP 上,User-Agent 是这个。

没有这个数据,你 T-6mo 发出去的邮件只能写"您可能受到影响";有了它,邮件就能写"您上周调用该接口 41,203 次,我们检测到以下具体调用点"。前一种会被无视,后一种大概率一小时内就收到对方技术负责人的回复。

带数字的沟通节奏

我给公共 API 的默认节奏是 T-12mo、T-6mo、T-3mo、T-1mo、T-2wk、T-1wk、T-24h。每封邮件都包含该客户过去 30 天在废弃接口上的真实调用量。T-3mo 那封最关键,因为这个时间点接入团队还有足够档期安排正式工作,但又还不足以拖延到最后一刻。

内部 API 可以把窗口压到 3-6 个月,因为消费者在你自己手里。伙伴 API 则完全看契约怎么写——这意味着 sunset 条款必须写进合同,而不是发在博客上。如果合同里没提,那你等于欠了伙伴无限期的支持义务。

宣布之前先把迁移文档写完

这听起来是废话,但违反的人很多。迁移指南必须在第一封废弃邮件发出之前就已经存在、完整、并且包含一段能跑通的代码样例。如果指南是在宣布一周后才上线的,那你等于让客户围绕一个还不存在的目标开始做排期,他们会投诉的。

我会把迁移文档作为 v2 的最后一步来写。如果我写不出一段清晰的迁移说明,那就说明 v2 还没做完。这是一个硬性检查点:客户方一个后端工程师应该能读完文档、把旧字段映射到新字段、估出工作量,而不用提工单。

优雅下线 vs 破坏性变更:双向门和单向门

优雅下线是指:在 sunset 日期之前,老接口继续返回合法数据,只是加上废弃相关的响应头。这是一扇双向门——漏掉邮件的客户仍然能用;如果有大客户卡住了,你可以延时间线;通过调用日志还能发现那些晚反应的客户。

破坏性变更是指:到 sunset 当天,接口直接翻成 410 Gone。这是一扇单向门。只有在老接口本身不兼容、泄漏数据或存在安全漏洞时才该这么做。不要因为你自己懒得维护老 handler 就这么干。"懒得维护"不是够格引发故障的理由。

一个具体例子:废弃 GET /v1/invoices

假设 v2 把分页从 offset 改成 cursor,这是对请求契约的破坏性变更。计划是这样:

验收标准

- Given v1 接口处于废弃窗口期内
  When 任意客户调用 GET /v1/invoices
  Then 响应带有 Deprecation、Sunset 和 Link: rel="deprecation" 三个头
  And 这次调用被记录,包含客户 ID、时间戳、User-Agent
  And 该客户在下一轮计划内废弃邮件中出现,并附带其调用次数

- Given sunset 日期已过
  When 任意客户调用 GET /v1/invoices
  Then 响应为 410 Gone
  And 响应体包含指向 v2 迁移指南的链接
  And 该调用仍被记录,用于 sunset 后的迟到者报表

对废弃本身做测试

合成监控应当验证:所有废弃接口的响应头确实在;Sunset 日期与宣布的日期完全一致;Link 头里的迁移文档返回 200。我见过线上的迁移 URL 直接 404,原因是文档仓库在废弃发布之后被重构过。合成测试一分钟内就能抓到,客户的邮件则要一周之后,而且代价是信任。

什么时候可以破例

安全问题有资格把时间线压短。老接口里的凭证泄漏事件不值得 12 个月的缓冲;一个可以接管账号的漏洞,72 小时内下线是合理的。把这个例外明确写进策略,别让安全团队在事故中还得现场争取。"安全豁免:经工程 VP 批准后 sunset 可短至 24 小时"——这种条款才是让策略真正落地、而不是停留在愿望里的关键。

可复制产物:契约评审包

当工作涉及 API 行为、schema、事件、重试或消费者预期时使用。它会把兼容性和发布证据提前摊开。

API 契约评审包:API 废弃计划:写进契约里的兼容通知

本次要做的决策:
- 确认契约变化是否兼容,消费者需要什么迁移动作,发布后如何观察风险。

责任人检查:
- 产品责任人:
- 工程责任人:
- QA 或运维评审:

范围边界:
- 本次包含:
- 本次不包含:
- 仍需确认的假设:

验收证据:
- 测试或 fixture:
- 日志、指标或截图:
- 人工复核步骤:

契约边界:没有兼容性分类、消费者影响、重试行为和回滚说明,不进入发布。

评审追问:
- 没参加需求会的人还会误解哪里?
- 哪个证据能证明这次改动足够安全,可以发布?

编辑复核记录

复核日期:2026-04-28。本次补充了可复用产物,按相关主题 Hub 检查了文章定位,并收紧下一步链接,让页面更像可操作参考,而不是孤立长文。

关键词:API deprecation · Sunset header · RFC 8594 · RFC 9745 · API versioning · migration guide · API contract

弃用发布清单

在宣布移除日期之前,先把契约计划变成一份可以评审的清单。它应该证明消费者能发现变更、按时迁移,并在漏掉依赖时有恢复路径。

下载:api-deprecation-plan-template.md

需要追踪的证据

真正有用的证据是消费者是否迁走,而不是文档是否完整。持续看旧端点流量、受影响客户的支持工单、迁移文档访问、warning header 上线后的失败请求,以及需要延期的消费者名单。

专题阅读路径

这篇文章归入 API 契约 主题。先读 Hub,再结合下面的清单、模板或工具落到具体项目里。

编辑说明与免责声明

最近复核:2026-04-28。编辑部检查了示例、内链和可复制评审片段,确保内容更适合真实项目使用。

本文用于软件工程教学与实践参考,不构成法律、税务或投资建议。示例场景用于解释规格方法,不对应真实客户数据。