回到文章列表
    疑難雜症·2026-07-15

    那個只在週一早上壞掉的 API

    詭異 bug 最難的不是修,而是重現。當錯誤只在特定時間、特定使用者、特定裝置出現時,工程師需要的不是更多 log,而是一套系統化的排查思路,從最不可能的地方開始懷疑。

    那個只在週一早上壞掉的 API

    有一種 bug,永遠只在你不在電腦前的時候出現。使用者截圖傳來,QA 重現不了,正式環境的 log 一片乾淨。你懷疑是使用者亂點,但問題就是每週固定回來一次。

    這類「幽靈 bug」在整合型系統裡特別常見。電商串金流、串物流、串 ERP,每一個介面都是一顆可能鬆掉的螺絲。真正棘手的地方不是修,而是讓它願意在你面前壞一次

    先分清楚:是隨機,還是你以為它隨機

    工程師講「這個 bug 隨機發生」時,九成的情況是還沒找到觸發條件。真正隨機的錯誤很少,多半是某個維度沒被記錄下來。

    常見被忽略的維度:

    • 時間:週期性排程、憑證過期、跨時區換日、月底結算
    • 使用者狀態:session 剛過期的瞬間、剛換過密碼、剛升級方案
    • 資料狀態:某張表剛好在某個大小、某個欄位第一次出現 null
    • 上游服務:第三方 API 那邊剛好在部署、限流剛好被打到

    舉個例子,假設一個訂單系統每逢週一早上就有幾筆訂單卡住。第一直覺是流量高,但擴容之後沒改善。真正的原因可能是週末排程跑的資料同步任務在週一清晨才完成,導致某段時間內快取跟 DB 不一致——這種問題你盯著應用程式 log 是永遠找不到的,因為錯誤根本不在應用層。

    排查的第一步,不是加 log,而是把所有能想到的維度列出來,然後看哪些你其實沒在觀測

    從最不可能的地方開始懷疑

    工程師的直覺通常會先懷疑自己最近改過的程式碼,這在多數情況下是對的。但當一個 bug 已經找了兩三天還沒頭緒,代表直覺路徑已經走完了,該換方向。

    這時候的經驗法則是:懷疑那些「應該不會壞」的東西

    # 示意:一段看起來人畜無害的重試邏輯
    def call_payment_api(order):
        for attempt in range(3):
            try:
                return payment.charge(order)
            except TimeoutError:
                continue
        raise PaymentFailed()
    

    這段程式碼看起來沒問題,但如果金流 API 是非冪等的,timeout 之後重試就可能造成重複扣款。而扣款成功但回應 timeout 的情境,通常在測試環境永遠遇不到,只會在正式環境某個網路抖動的瞬間發生一次。

    類似的「隱形假設」還有:

    • 資料庫 transaction 假設不會被外部呼叫打斷
    • 前端假設 API 永遠回傳同樣的欄位順序
    • Log 假設寫入不會失敗、所以沒處理 exception
    • 快取假設 TTL 到了就一定會重抓,沒考慮 thundering herd

    真正的除錯功力不在會用什麼工具,而在看到一段程式碼時,能列出它背後有多少個沒明說的假設。每一個沒明說的假設,都是未來的 bug。

    我們的觀察

    處理過夠多整合案的團隊都有一個共識:詭異 bug 通常不詭異,只是觀測不足。與其花時間猜,不如先補齊 log、trace ID、上下游時間戳,讓下一次它出現時你能看清楚全貌。修 bug 是一次性的,但把系統變得可觀測,會長期回本。而在報價客製化系統時,我們通常會建議客戶把可觀測性當成第一版就要有的功能,而不是等到出事才加。

    #除錯#工程實務#系統整合#效能調校

    下一步

    需要把這裡的觀點落地到自家系統?

    協和數位專做客製化電商、AI Agent 與雙平台 APP。第一次諮詢免費,會幫你拆解可行性與優先順序——即使最後沒合作也沒關係。

    寫信給我們 →