TL;DR — 2026/6/22,GitHub 第二次無預警把我的帳號停權。但這一次和 4/29 完全不同:更新網站的功能沒有中斷,正在規劃的電子報服務順利上線,部署流程沒被拖住。會不一樣,是因為兩個月前的事故後,我花了兩週重新搭出一套解耦架構。這次是那套韌性系統的檢驗。它通過了考驗,但也暴露一個新的盲區。
6 月 22 日下午,我正在收尾 paulkuo.tw 的電子報訂閱功能。後端已經部署完成,端到端測試也全數通過,我讓 AI 把進度同步到專案儀表板。就在那個時候,對話視窗出現警訊,那行熟悉到有點刺眼的紅字又跳了出來:
Your account was suspended
GitHub 又把我斷線了。
兩個月前,同樣這行字,讓我整整兩週無法正常開發與發文。那天是 4/29,我在創業與超級個體寫了一篇完整的工程紀錄:GitHub 帳號被無預警停權,沒有清楚理由,也沒有事前通知。那一刻,從寫作、版本控管、CI 到部署,整條命脈幾乎一起斷掉。我花了兩週時間,重新搭出一套五層韌性架構,讓網站恢復正常運作。
這次一樣是無預警停權,但結果不同。我要更新網站的功能沒有中斷,電子報功能順利上線,部署流程也沒卡住,整個網站 paulkuo.tw 繼續運作,就像什麼事都沒有發生。
GitHub 這次並沒有比較友善。一樣冷酷,一樣突然,一樣是 403,一樣沒有事先通知。不一樣的,是中間我們規劃的系統。第一次事故發生時,那套架構還不存在;第二次事故發生時,它成功擋下了 GitHub 停權的衝擊。
GitHub 第二次停權,到底斷了什麼?又沒有斷什麼?
停權後,我去看系統哪一層被影響。被卡住的,主要是「記錄與同步」這一類;真正負責「運行與發布」的核心流程沒停。

實測下來,被擋的有三個部分:git push 到 GitHub 主倉庫失敗、GitHub 上的專案儀表板同步中斷、所有依賴 GitHub 身份的操作(命令列工具與 API)全部回 403。
但照常運行的部分更多,也更關鍵。程式碼照樣推到 Codeberg 和 GitLab 兩個獨立的 git host,這部分完全沒有受到影響。工作歷程 commit,三個遠端原本都應該收到,GitHub 被擋,Codeberg 和 GitLab 都正常接住了。部署流程走的是 wrangler,直接推到 Cloudflare,用的是 Cloudflare 自己的 token,和 GitHub 帳號沒有任何關係。網站、電子報、API 全部都在 Cloudflare 上正常運行。專案儀表板的 Notion 鏡像也沒事,因為它讀的是程式碼倉庫裡的檔案,而不是 GitHub API。
目前的系統架構是:綁在 GitHub 身份上的功能自然會被擋住;不經過 GitHub 的環節,都活了下來。這是 4/29 之後那兩週,我花力氣重建的東西。
為什麼這次部署完全沒有受影響?
4/29 那次,我學到的教訓:很多人以為自己只是把程式碼放在 GitHub,其實連部署命脈也一起交了出去。
我以前的部署鏈是這樣:push 到 GitHub,GitHub Actions 被觸發,接著 Cloudflare Pages 自動部署。看起來很方便,也很標準。但問題是,GitHub Actions 是這條鏈的必經之路。帳號一旦被停權,整條鏈就從中間斷掉。程式碼在我自己的機器上,但「發布」已經不在我的控制裡。
上次被停權時,我有內容、有檔案、有網站,卻發不出去。所以重建時我把部署鏈拆開。現在的流程是:本地 build,透過 wrangler 直接推送到 Cloudflare Pages,使用 Cloudflare 自己的 API token。這條鏈上,沒有任何一個環節需要 GitHub 存活。
因此 6/22 即使 GitHub 帳號被停,電子報的後端和前端仍然照常 deploy、照常驗證、照常上線。我甚至是在帳號被停權之後,才回頭確認網站狀態:訂閱頁正常、表單可用、寄信流程完整走完。那時我清楚感覺到這才叫解耦。GitHub 在不在線,已經不再決定我的網站能不能發布。
📊 兩次停權對照
- 4/29 第一次:整條命脈斷線,花了兩週才重建完成,恢復發文。
- 6/22 第二次:網站零中斷,當天照常上線新功能。
- 兩次事件:中間那套五層解耦架構,在第二次停權發生時,當了我的保險。
但這次也戳出了一個我沒蓋到的盲區
如果故事停在這裡,它只是一個「我建了一套有用的系統」的案例。但真實事故照出來的,從來不只是你做對的部分,還有你沒想到、甚至沒看見的地方。
這次被挖出來的,是一個我原本以為有備援、其實沒有的環節。
要把進度同步出去的時候,我手上有兩個 AI 在幫忙,各自用不同的方式連到 GitHub。我一直把它們當成兩條獨立的路:這條不行,還有那條。結果 GitHub 帳號一被停,兩條同時掛掉。原因說穿了很簡單:兩個 AI 用的方式不一樣,但最後都得拿「我的 GitHub 帳號」去開門。GitHub 停掉的是整個帳號這個身份,底下所有用這個帳號的工具,自然一起失效。
打個生活一點的比方。你家廚房一個水龍頭、浴室一個水龍頭。有天廚房沒水,你想沒關係,去浴室接就好,結果浴室也沒水。因為這兩個水龍頭,牆壁裡接的是同一根總水管、同一個總閥。你平常看不到牆裡的管路,所以一直以為它們是兩個各自獨立的水源。我那兩條備援路,就是那兩個水龍頭。
這種狀況叫「同源單點」,是一種假冗餘。它比完全沒有備援更危險,因為它給你一種錯誤的安全感。沒有備援的時候,你至少知道自己在裸奔;假冗餘是讓你以為自己穿了盔甲,直到被打中那一刻,才發現那是紙板。
這件事讓我看到一個更大的問題:系統越複雜,那根「總水管」就藏得越深,我們越看不到它。我們看到的是兩個水龍頭、兩個工具、兩個看起來各自獨立的選項,它們卻在我們看不見的地方,接到同一個點。看不見不代表不存在,看不見的依賴往往最危險,因為你連它會跟著一起壞都不知道。
要解決的問題越多,系統會往更複雜的方向走。每多接一個服務、每多加一個工具,背後那張依賴圖就多幾條線,而那張圖已經沒有人完整看得見了。這是上一篇提到的「正常事故」理論講的事:在一個足夠複雜、又彼此牽動的系統裡,意外遲早都會發生,差別只在何時。沒有人能在事前看清所有的連動,因為連動本身會隨著系統演化不斷長出來。
而複雜性的風險,往往來自節點之間那些看不見的耦合。一條你以為獨立的備援路徑,可能跟主路徑共用同一個失效源。風險不藏在工具裡,藏在工具之間的關係裡。
複雜本身,就是一種藏起來的風險。
它也讓我想起三哩島事故的一個細節:操作員盯著「指令已發送」的指示燈,以為閥門關上了,其實閥門卡在開的位置。那盞燈顯示的是「我送出了指令」,至於閥門真正的狀態,是另一回事。假冗餘是同一種錯覺,它讓你看見兩條路,而那兩條路底下,是同一個會一起斷掉的根。
韌性沒有完成的一天,只有一次次被現實驗證
4/29 那次事故,教我怎麼建一套韌性架構。6/22 這次事故,教我的是另一件事:架構畫完圖不算數,部署完成也不算完成,它必須被現實檢驗,才知道哪裡真的有用,哪裡只是自己以為有用。
這是我在創業與超級個體這個主題裡,想要反覆驗證的題目。混沌演練很重要,但演練終究是你自己安排的壓力測試,再逼真,都還帶著一點「我知道接下來會發生什麼」的底氣。真實事故不一樣。6/22 停權沒有預告,不在我的演練腳本裡,也不是我安排好的測試。它就是突然發生,然後,我要用手中的系統立刻回應。
這次我安然渡過了:網站、部署、電子報都活著。但它也幫我挑出一個風險。我以為兩個 AI session 是兩條備援路,結果它們共用同一個身份來源,暴露我在判斷架構時的疏忽,跟工具本身無關。
所以,一套韌性架構,要被真實世界檢驗,才知道真正的價值。更重要的是,每檢驗一次,就可以更新一次盲區清單。第一次事故後,我的清單上寫著:五層解耦。第二次事故後,我在清單上又加了一條:多路徑備援,不只要看路徑數量,更要檢查失效源是否真的獨立。未來一定還會有第三次、第四次,讓系統不斷堆疊演化。
上一篇文章裡,我說:不該把自己的命脈託付給一家公司,然後還聲稱自己是自由的。
兩個月後的心得是:建好系統不等於自由。真正撐住你的,是系統被現實測試時,你看得見問題、改得動結構,把主控權拿回自己手上。
GitHub 第三次 suspend 會不會來,我不知道。但這次我知道:它再來的時候,我的系統已經更扛得住。
正如艾倫.瓦茲所說:「要理解變化的意義,唯一的方法就是投身其中,隨它前行,與它共舞。」
那行紅字也許還會再跳一次。但下次它跳出來的時候,我的網站,大概還是會像什麼都沒發生過一樣,繼續運作。
💬 留言討論
載入中...