上線後的三十秒:先想清楚怎麼退
上線後的三十秒:先想清楚怎麼退 週一早上 9 點,你改了一行支付閘道的超時設定,按下 Enter,部署完成,掃過日誌,清爽。你鬆了口氣,繼續去開別的會。 30 分鐘後,支付回呼開始排隊,超時錯誤一片。你才想起來回答那個問題: 怎麼退? 如果答案是「回頭再重新部署一次」,那你其實沒有復原方案,你只是在假設復原會自動…

驗證報告
上線後的三十秒:先想清楚怎麼退
週一早上 9 點,你改了一行支付閘道的超時設定,按下 Enter,部署完成,掃過日誌,清爽。你鬆了口氣,繼續去開別的會。
30 分鐘後,支付回呼開始排隊,超時錯誤一片。你才想起來回答那個問題:怎麼退? 如果答案是「回頭再重新部署一次」,那你其實沒有復原方案,你只是在假設復原會自動發生。
這項技能不討論架構,只給一個 2 分鐘的預檢清單。
什麼時候用
- 部署程式碼、改設定、開啟 feature flag、執行資料庫遷移
- 在共享環境(staging、生產環境、「大家共用的那台伺服器」)動手
- 會向外發送訊息、寫入外部系統、修改資料的情況
什麼時候不用
- 本地小實驗,崩潰重跑零成本
- 一次性文案,錯了重寫就行
- 純讀取操作(查日誌、看資料)
三種都不佔,就別走流程——別把流程本身當成工作量。
檢查清單(2 分鐘)
- 寫出復原指令。 真的寫下來——commit message、工單、Slack 都算。說不清具體指令,就沒有復原方案,只有一句願望。
- 估計復原耗時。 30 秒一個 revert 和 40 分鐘資料重建是兩個風險量級。超過 10 分鐘的「復原」不是復原,是二次事故應變計畫——這種情況應該改用灰度發布或開關,而不是賭一把。
- 留現場。 git tag、設定 diff、資料表備份。「前面那個版本我記得」= 沒有備份。
- 副作用能不能撤銷? 訊息發了、快取落了、下游資料表寫了——這些退不掉。副作用不可逆時,問題不在復原方案不夠好,而在操作本身該改成可逆(先乾跑、先灰度)。
- 記下舊值。 超時從 5s 改成 30s?在工單裡寫「舊值:5s」。人類記憶在凌晨 3:17 不可靠。
常見坑
坑一:把備份當復原。 備份存在不等於恢復快。恢復腳本半年沒跑過、備份在異地、要審批才能拉回來——這些都很常見。復原的驗收標準是「現在能不能 10 分鐘內復原」,不是「有沒有備份」。
坑二:flag 沒驗證就上線。 feature flag 本身也是個變更。關閉 flag 後服務能不能正常啟動、會不會報空指標,沒人測過。flag 當保命符之前,先讓它單獨測一次。
坑三:復原程式碼,資料沒復原。 新程式碼寫新欄位,revert 之後舊程式碼去讀舊資料表,欄位對不上。資料庫變更要向後相容,要么標「不可復原」,兩種都行,混著來最危險。
坑四:打算了但沒落字。 開會時說「先灰度再復原」,動工到上線忘復原這一半。復原方案必須和應用方案的完整度一樣:同樣的工時、同樣的文件位置、同樣的驗收細節。事故時你有時間看的往往只有落字的。
一個 10 秒自檢
「炸了之後 10 分鐘能退嗎?」 能 → 有一條指令、一個備份引用、一段耗時估計。不能 → 先去把它變能,再上線。
發布前工單模板
## 復原
指令: <revert <hash> / 改回 X=5s / 關 flag: pay-timeout>
預估耗時: <N 分鐘>
現場: <備份/快照位置>
不可逆副作用: <有:xxx / 無>
五條都填不出,就紅燈。
舉例:一條超時的復原長什麼樣
工單:把支付回呼超時從 5 秒改成 30 秒。復原區塊應該長這樣:
- 指令:設定面板把
pay.cb.timeout從 30 改回 5,或跑config rollback --key pay.cb.timeout - 預估耗時:2 分鐘
- 現場:改動前截圖存工單附件
- 不可逆副作用:無——因為這是一條設定,不是資料遷移
對比一個危險的版本:「復原:重新部署前一份映像檔」。問題在於這個動作要多長沒人測過、前一份映像是多少天前的不清楚、期間新資料寫入狀態怎麼辦沒人想過。看起來有方案,三個問號都懸著。第二種寫法才是把坑填了。
尾聲
復原方案的價值不在出事那天,而在動手之前:它就是那一小段寫出來的話,逼著你在 14:00 把「退路」想清楚。寫不出來的那一刻,是上線前資訊量最大的一刻。
怎麼用
先在隔離環境中按記錄步驟重現,再決定是否採用這項技能。
實測效果
實驗室只記錄可重現結果,不把未經驗證的說法寫成結論。
踩坑
套用前核對權限、輸入、回復步驟和證據是否完整。
適用場景
適合環境條件與本報告證據範圍一致的任務。
不適用場景
缺少必要證據、隔離條件或回復控制時不要使用。