हिन्दी
Everyone designs the upgrade path; few design the rollback path in advance — especially the database schema. Notes from the release that taught me.essay · standmeet2026.10.15 · essay
2026.10.15·3 min read#essay#operations

Design the Way Back

Everyone designs the upgrade path; few design the rollback path in advance — especially the database schema. Notes from the release that taught me.

发布要设计回程

每次发布打一个 tag。一次发布是历史上的一个固定点,不是一条会动的分支。这部分是基本纪律,多数团队都有。

多数团队跳过的,是回程。

大家都设计升级路径。但如果回退是可能的——在任何要紧的系统上,它必须可能——那么回退路径就必须同时设计,用同样的认真程度。尤其是数据库 schema。一个只能往前跑的迁移,是你给自己挖的坑,而且会在最糟糕的那个早上被发现。

这是我从自己的一次发布里学到的,2026 年 9 月的 v0.1.33。那次构建把我的后端 URL 泄进了应用里。应用于是把自己的调用代理回自己身上,用户到处报错,而每一个健康检查都说系统没问题。

最糟的还不是这个 bug 本身。产品内的升级按钮走的正是同一条代理——于是正常的修复路径,被它本该修复的那个故障一并打坏了。而在底下,更新器一直在跟随 latest 标签,而 compose 文件里钉的是另一个版本:正在跑的东西,悄悄偏离了声称的东西。

恢复是绕过应用、从托管层进来的。我改了镜像 tag,重新部署,看着旧版本重新应答。

那个早上留下了三条规则,后来 v0.1.151 因为迁移顺序错误而崩溃循环,又给它们划了一遍重点。

一切钉版。什么都不许跟随 "latest"。

一次坏发布,不能堵住自己的回滚路。回程必须独立于被回滚的东西本身,而且必须被测试过,不许只是假设它存在。

分发保持去中心化。不要一口气把新版本推进每个人的机器。客户端拉自己要跑的版本;一个团队可以把自己钉在原地。基建允许的话,先发一个小切片。这样就永远不会有"所有人同时换版"的那一刻——坏版本是几个人往回退一步的事,而不是所有人一觉醒来身处其中的事。

回程若是预先设计好的,坏发布的第一小时就不是一场救援。它是一个流程。