完成只是局部事实
当 API 返回成功时,它证明的是一件范围很窄的事:某个系统根据自己的契约接受或完成了某项操作。它不会自动证明预期的业务结果已经发生。
邮件服务可以接受一封最终没有到达收件人的邮件;承运人接口可以接受一条之后在运营上失败的指令;支付请求可以创建,却没有结算;工作流可以记录下游响应,又在保存自身状态之前崩溃。这些不是罕见边缘场景,而是独立系统、网络、队列与人在不同时间尺度上行动的正常结果。
如果产品把所有事实压缩成一个绿色“已完成”标记,就会误导用户。验证需要独立的状态、界面、证据和负责人。
分开意图、执行、观察与证明
可靠工作流至少需要四类不同记录:
- 意图——用户或策略授权了什么。
- 执行——系统以哪个身份尝试了什么命令。
- 观察——下游系统报告了什么。
- 验证——什么证据支持预期的现实结果。
它们可以互相关联,但不应互相替代。HTTP 201 可以是有效的执行证据,却不是交付证明;Webhook 可以提供有用观察,却不一定是结算的权威来源;人工复核的文件可以验证结果,同时仍保留不确定性。
这个模型会增加状态和界面文案,但这种复杂度值得,因为它与产品要管理的真实世界一致。
重试会改变产品契约
一旦工作流能够重试,“发送请求”就不再是单个动作。系统必须决定哪些失败可重试、等待多久、最多尝试几次、每次是否复用稳定幂等键,以及超过上限后如何处理。
在独立系统之间声称 exactly-once 尤其危险。下游可能已经完成副作用,但调用方丢失了响应。没有共享事务时,调用方无法始终知道重试是否会重复副作用。双方都遵守幂等契约时,可以形成 effectively-once 边界,但这个保证有明确范围和保留期限。
诚实的产品做法是公开边界:持久化尝试、分类响应、在有限次数后停止、把未解决工作移入死信状态,并给操作人员一个受保护且幂等的恢复路径。没有这些决策的重试循环,不是可靠性,而是重复不确定性。
验证证据也会过期
证据曾经有效,不代表它永久有效。文件会到期,状态会被替代,来源系统会修订记录,截图也只能证明界面存在,不能证明其背后的数据。
因此,验证必须包含出处与时间:证据来自哪里、何时检查、覆盖什么范围、是否会过期或暂时不可用、哪些声明依赖它。
这些问题会改变界面设计。产品可能需要“已执行但未验证、已验证、需要复核、已停止”等状态,而不只是一个“已验证”。它还需要在业务声明旁显示证据日期,并把过期结果交回给人。
用户会看到更多细节,但组织也获得了一个能够承认“当前不知道”的系统。
恢复是用户旅程的一部分
故障处理常被当成在正常路径之后补写的运维问题。实际上,恢复本身就是一个包含参与者、权限、决策和副作用的产品旅程。
操作人员需要知道项目为什么停止、已经发生了什么、重放会发生什么,以及是否已有其他人拥有恢复权。客户需要一个不泄露内部或私人信息的安全状态。系统还要阻止旧重放覆盖更新的决定。
这就是耐久台账、租约、栅栏、版本化决策和受保护审批端点的价值。它们不是基础设施装饰,而是让恢复可以理解,并避免“修复一次故障”又制造第二次故障。
验证会改变成功的衡量方式
如果产品只衡量完成了多少请求,就会优化吞吐量。如果它衡量已验证结果、过期证据、重复抑制、死信年龄和恢复所有权,就会优化可信完成。
这种变化会暴露不舒服的事实:有些结果验证更慢;有些集成提供的证据比预期弱;有些“成功”自动化仍需人工复核。这些发现很有价值,因为它们揭示的是真实运营系统,而不是仪表盘偏好的故事。
CargoMesh 在物流参考系统中建模独立的执行与验证状态;n8n Reliability Lab 使用本地夹具展示有界重试、幂等、死信、审批与重放。两个项目都没有把本地测试变成生产保证。它们共同说明一个原则:产品并不是行动后就结束,而是在能够负责任地解释之后发生了什么时才算完成。