錯誤資料庫決策的15倍代價:決策時機的教訓
我測量了一個資料庫決策在三個生產系統中的成本。遷移成本在三年累積的資料和綱要依賴關係下增長了15倍。
TL;DR
大多數工程師在決策時機上本末倒置:他們花好幾天反覆斟酌可逆的選擇(該用哪個 API 客戶端函式庫),卻在幾分鐘內做出不可逆的決策(在衝刺規劃會議中敲定資料庫綱要)。Ray Dalio 和 Jeff Bezos 從不同角度描述了相同的框架:可逆決策應該快速做出,因為延遲的代價比不完美更高。不可逆決策則值得投入與其風險相稱的分析。我在三個系統中親身學到了這個教訓——早期的綱要捷徑最終累積成六位數的遷移成本。證據關卡在程式碼層級落實了這項區分:每一項並非瑣碎的變更,都需要與其可逆程度相稱的證據。
讓我學到教訓的那次遷移
在ZipRecruiter的第一年,我接手了一個系統,原始團隊選擇了反正規化的綱要來加速初期開發。這個決策在當時是合理的:快速上線,之後再正規化。但「之後」從未到來。
到了第二年,已有三個服務依賴於這個反正規化的結構。到了第三年,該綱要已累積了14個月的生產資料、預設反正規化佈局的外鍵關係,以及六個在任何結構性變更時都會崩壞的報表查詢。
第一個月的遷移成本大約是兩個工程天。第十二個月時,大約兩週。到了第三十六個月,估計需要三個月的專職工程時間,加上滾動部署和雙寫邏輯以避免停機。這就是15倍的乘數效應:不是因為問題變得更難,而是因為影響範圍隨著每個月累積的依賴關係不斷擴大。1
框架
可逆決策:幾分鐘內決定
為原型選擇前端框架。選定變數命名慣例。為測試環境選擇雲端區域。決定先寫哪篇部落格文章。
這些決策有個共同特徵:無論何時改變方向,改變的成本大致相同。延遲只會浪費時間,不會改善結果。2
我的判斷標準: 如果下週我能用不到一天的工作量撤銷這個決策,那就現在決定。
建立這個網站時,我花了大約十分鐘選擇 HTMX 而非 React。如果 HTMX 選錯了,在一個使用伺服器端渲染模板的個人網站上切換框架只需要一個週末。低廉的逆轉成本意味著速度比分析更重要。
不可逆決策:花幾天決定
為客戶資料選擇資料庫引擎。定義外部系統依賴的 API 契約。選擇一個將有86個掛鉤建立其上的掛鉤架構。
這些決策會產生複利效應。逆轉的成本隨時間增長,通常呈指數級。3
我的判斷標準: 如果撤銷這個決策的成本每六個月翻倍,我就投入與風險相稱的分析。品味基礎設施這個專題彙整了本框架所屬的更廣泛決策原則。
我的 .claude/ 掛鉤架構就是一個正確處理不可逆決策的例子。在撰寫任何掛鉤之前,我花了兩週設計掛鉤生命週期模型(PreToolUse、PostToolUse、Stop,以及另外三個)。該設計現在支援橫跨 git 安全、遞迴控制、哲學執行、品質關卡和可觀測性的86個掛鉤。在這個時間點改變生命週期模型將需要重寫每一個掛鉤。前期的分析已經多次回本。4
五個我做對和做錯的決策
做對:選擇純 CSS 而非 Tailwind
類型: 可逆。花費時間: 20分鐘。
我為這個網站選擇了使用自訂屬性的純 CSS 而非 Tailwind。如果選錯了,我可以在一個週末內遷移到 Tailwind。這個決策花了20分鐘:我重視學習 CSS 基礎而非框架生產力。兩年後,我很慶幸選擇了純 CSS,因為每一次最佳化(達到滿分的 Lighthouse 分數)都需要理解 CSS 實際上做了什麼。但這個決策無論怎麼選都不會有太大的後果。這與品質是唯一的變數背後的原則相同:當做對的成本與做錯的成本相當時,就預設選擇做對。
做對:投資掛鉤架構設計
類型: 不可逆。花費時間: 兩週。
現在有86個掛鉤依賴於這個生命週期模型。前期設計投入的每一個小時都值得。
做錯:倉促制定部落格內容綱要
類型: 不可逆。花費時間: 30分鐘。
我在一次會議中定義了部落格文章的 ContentMeta 資料類別:title、slug、date、description、tags、author、published。我沒有包含 category、series、hero_image、scripts 或 styles。之後每次新增都需要修改解析器、更新每個使用該中繼資料的模板,並重新測試整個部落格流程。三個月內的五次新增所耗費的總時間,超過了當初仔細設計綱要所需的時間。
做錯:糾結部落格文章順序
類型: 可逆。花費時間: 在規劃會議中花了兩小時。
我花了兩小時決定先寫哪些部落格文章。順序是完全可逆的。我應該直接開始寫任何一篇,然後根據過程中學到的經驗再重新排序。
做對:審慎的共識閾值設計
類型: 不可逆。花費時間: 一週。
我的審議系統使用任務自適應的共識閾值:安全決策85%、功能80%、重構65%、文件50%。如果這些設定錯誤,要麼會阻擋正當的工作(閾值過高),要麼會批准危險的變更(閾值過低)。在確定之前,我針對實際的任務歷史記錄測試了每個閾值。
常見的本末倒置
工程師花好幾天選擇 API 客戶端函式庫(可逆、低切換成本),卻在衝刺規劃會議中設計資料庫綱要(不可逆、高遷移成本)。
管理者也是如此:花好幾週評估專案管理工具(可逆),卻在一夜之間重組團隊(不可逆、高人員成本)。5
這種本末倒置之所以發生,是因為可逆決策在當下感覺很重要(團隊可能會評判我的函式庫選擇),而不可逆決策感覺很抽象(遷移是三年後的事)。這些直覺恰好完全相反。新創驗證框架把同樣的洞見落實到產品決策上:先驗證成本最低的假設,再依逆轉成本按比例投入分析。
每次決策前的兩個問題
- 六個月後逆轉的成本是多少? 如果答案是「微不足道」,現在就決定。
- 延遲是否能改善可用的資訊? 如果等待不會產生新的資料,現在就決定。
只有在兩個條件都支持等待時才進行深入分析:逆轉成本高昂且隨著時間會出現更好的資訊。6其他所有事情都立即決定。Past Year Review 則提供了與之對應的回顧做法:決策做出之後,衡量哪些產生了正向的複利、哪些消耗了精力,再把這些證據回饋到未來的時機判斷中。這屬於品味基礎設施的一部分,它規範了本站所記錄的所有工作中決策是如何做出的。
關鍵要點
給工程師的建議: - 原型的技術堆疊選擇是可逆的;用幾分鐘而非幾場會議來做決定 - 資料庫綱要和 API 契約在規模化後是不可逆的;根據將有多少系統依賴該決策,按比例投入前期分析 - 追蹤您的決策成本;測量15倍的遷移乘數改變了我評估前期投資的方式
給管理者的建議: - 工具和流程變更通常是可逆的;快速試行並迭代 - 團隊結構和招聘決策有很高的逆轉成本;按比例進行審慎分析 - 當團隊花一週選擇一個函式庫時,問問逆轉成本是否值得這麼長的討論時間
常見問題
我該如何判斷一個決策是可逆還是不可逆?
用兩個標準來檢驗。(1)六個月後逆轉的成本是多少?如果答案是「微不足道」(不到一天的工作量),這個決策就是可逆的。(2)撤銷這個決策的成本是否每六個月翻倍?如果是,這個決策在規模化後就是不可逆的。資料庫綱要、API 契約和掛鉤架構都屬於不可逆決策,因為累積的依賴關係會讓逆轉成本隨時間呈指數級上升。而原型的框架選擇和變數命名慣例則是可逆的。
常見的決策時機本末倒置是什麼?
工程師和管理者都會系統性地在可逆決策上花費過多時間(挑選 API 客戶端函式庫、評估專案管理工具),卻在不可逆決策上投入不足(在衝刺規劃中設計資料庫綱要、一夜之間重組團隊)。這種本末倒置之所以發生,是因為可逆決策在當下感覺很重要,而不可逆決策感覺很抽象,但這些直覺恰好完全相反。
一個資料庫決策為何在三年內修復成本會高出15倍?
因為當初為了加速初期開發而選擇的反正規化綱要,在三年間不斷累積依賴:三個服務依賴於這個結構,14個月的生產資料預設了這個佈局,還有六個報表查詢會因結構性變更而崩壞。第一個月的遷移成本是兩個工程天。到了第三十六個月,估計需要三個月的專職工程時間,外加帶有雙寫邏輯的滾動部署。
每次決策前應該問哪兩個問題?
(1)六個月後逆轉的成本是多少?如果微不足道,現在就決定。(2)延遲是否能改善可用的資訊?如果等待不會產生新的資料,現在就決定。只有在兩個條件都支持等待時才進行深入分析:逆轉成本高昂,而且隨著時間會出現更好的資訊。其他所有事情都立即決定。
參考文獻
-
作者對ZipRecruiter三個生產系統資料庫遷移成本的分析。遷移成本在三年累積的資料和綱要依賴關係下增長了15倍。 ↩
-
Bezos, Jeff, “2015 Letter to Shareholders,” Amazon, 2016.「第一類和第二類決策」框架。 ↩
-
Dalio, Ray, Principles: Life and Work, Simon & Schuster, 2017. 關於決策時機和極致透明的核心框架。 ↩
-
作者的掛鉤架構設計過程。橫跨6個生命週期點的86個掛鉤,記錄於 “Claude Code hooks”。 ↩
-
Kahneman, Daniel, Thinking, Fast and Slow, Farrar, Straus and Giroux, 2011. 關於決策疲勞和認知偏誤的研究。 ↩
-
Taleb, Nassim Nicholas, Antifragile, Random House, 2012. 關於選擇權和不確定性下決策的框架。 ↩