10.3 託管形態遷出:資產線盤點與並行期執行
0.21 交付形態選型 的升級自建 tripwire 回答「何時該重新評估」、評估成立後、本章接手回答「按下遷出鍵之後的工程」。讀者情境:產品跑在 Wix / Shopify / Firebase / WordPress 這類託管形態上、tripwire 已命中、目標是自建或半託管。遷出的核心原則是把「搬家」拆成多條資產線各自的受控 migration:資料、身分、流量、整合的可攜性差異極大、斷點位置不同、可以分開 cutover — 把它們綁成同一天的大爆炸切換(big bang cutover)、等於把可攜性最差的那條線的風險強加給其他所有線。
Vendor lock-in 在遷出日的具體形狀就是這幾條資產線的斷點。0.21 的可遷出保險清單(自有網域、資料定期匯出、客戶聯絡管道自有、金流可攜性、密碼不可攜的預案、業務邏輯文件化)是進場時買的保險、本章是理賠流程 — 保險有買、每條線的斷點都有現成出口;保險沒買、本章每一節都會多一段「先補保險再動手」的前置工。
資產線盤點
動手前先盤點:這個產品在平台上累積了哪些資產、每項資產走哪條線、可攜性如何。盤點的產出是一張「資產 → 線 → 出口 → 斷點」對照、它決定後面所有階段的順序與凍結窗口長度。
資料線
資料線問兩個問題:拿得出來嗎、拿出來之後能直接用嗎。多數平台對第一個問題的答案是肯定的 — Shopify 的商品與訂單歷史有官方 CSV / API 匯出、WordPress 的文章與媒體是最成熟的匯出路徑、Firebase 的 Firestore 有官方 export。真正的工程量在第二個問題:匯出格式是平台資料模型的快照、不是自建系統的 schema。
兩個典型情境。第一、BaaS 的反正規化結構:Firestore 的文件沿查詢需求生長、同一份事實散在多個 collection、而目標端的關聯式 database 要求單一事實單一位置 — 執行順序是先設計目標 schema、再寫轉換管線、而不是把 export 原樣灌進去。第二、半託管 CMS 的外掛私有表:WordPress 官方匯出涵蓋文章與媒體、外掛各自的私有表(會員等級、預約規則、客製欄位)在匯出範圍之外 — 每個外掛要單獨確認資料位置與匯出手段。盤點階段把這兩類「拿得出來但不能直接用」的資產標出來、它們是資料線時程的主要變數。
歷史資料搬完之後、增量是另一個問題:平台在並行期仍持續產生新訂單、新會員、新內容、需要一條增量同步管道(webhook、API 輪詢、排程匯出)把變更餵進新系統 — 角色等同自建世界的 change data capture、只是來源是平台 API 而不是資料庫 log。
資料線還有一類「可放棄、但要快照」的資產:平台內建報表與分析歷史。這類數據多數沒有匯出路徑、平台降級或關站後即消失 — 歷史明細可以放棄、但 cutover 後的健康判讀需要遷移前的基線(自然流量、轉換率、客單價)。盤點階段把基線指標匯出存檔、觀察期的「下滑超過預估」才有對照對象。
身分線
身分線的可攜性在所有資產線中分布最極端。會員的 email 與基本資料幾乎都可匯出;密碼雜湊多數平台拒絕交出 — Firebase Auth 是少數友善案例、官方工具可匯出密碼雜湊、演算法參數從主控台另行取得、自建認證系統照參數驗證即可無感銜接。多數平台(電商會員、網站會員系統)把雜湊留在自己手上、這條線的執行形態於是變成全體重設密碼。
重設密碼遷移要當成產品功能設計、而不是遷移日的告示:分批寄送重設邀請、首次登入時引導重設、保留舊 email 驗證鏈路、把重設高峰排開行銷活動。0.21 可遷出保險裡「密碼不可攜的預案」指的就是這套體驗、執行階段它從預案變成排程上的工作項。
Session 綁定在平台端、cutover 當天全體使用者重新登入是預設行為、要納入切換日的客服與監控預期。第三方登入(Google / Apple 登入)的識別碼可攜性介於兩者之間:識別碼存在 provider 端、但可能綁定在 OAuth client 或開發者帳號的範圍上 — Apple 的 user identifier 以開發者團隊為界、換團隊後同一使用者拿到不同識別碼。遷移前先用測試帳號驗證新舊系統拿到的識別碼一致、再決定第三方登入使用者要走無感銜接還是重新綁定。
身分線的盤點對象除了終端使用者、還有操作者與機器:員工帳號、角色權限、API key 與第三方服務的 OAuth 授權都要在新系統重新佈建、並納入 cutover 演練 — 切換日客服登不進新後台、是這條線最常見的自傷事故。
流量線
流量線的前提是自有網域 — 0.21 可遷出保險清單裡的保險項。網域在自己名下、DNS 自己控制、流量切換就是一次 DNS 變更加一套轉址規則;流量活在平台贈送的子網域上、遷出等於換址、SEO 與既有連結歸零、這條線要先補保險(買網域、在平台上綁定、讓搜尋引擎與外部連結先收斂到自有網域)再談切換。
執行面的關鍵是斷裂面管理。平台的 URL 結構(/products/handle、/blogs/news/slug)跟自建系統的路由幾乎必然不同、而離開平台後、舊 URL 的轉址規則沒有地方住 — 平台停用後它連 404 都不會回、是 DNS 直接指向新系統。所以轉址表(舊 URL 樣式 → 新 URL)要建在新系統自己身上:cutover 後由新系統對舊樣式回 301、搜尋引擎與外部連結沿轉址收斂。配套動作:cutover 前把 DNS TTL 調低、cutover 後重交 sitemap、用搜尋主控台觀察索引替換進度。SEO 累積是按月計的資產、轉址表缺漏的代價以自然流量下滑直接體現。
整合線
整合線收所有由平台出面跟外部世界握手的合約、其中金流是最硬的斷點 — 它在本章盤點順序排最後、執行確認要排最早、答案會改變整場遷移的形狀。一次性收款的遷移成本低 — 換金流串接、新訂單走新管道。訂閱制是另一回事:扣款授權 token 存在金流商的 vault 裡、且常綁定在平台名下的金流帳戶上。遷出時先問金流商「授權能否轉移到商家自有的金流帳戶」— 部分金流商支援處理商之間的卡號資料轉移、談得下來就是一次後台作業;談不下來、全體訂閱者重新授權、流失率直接換算成訂閱營收缺口。執行手段跟重設密碼同構:分批通知、寬限期、必要時用優惠補償授權摩擦。
金流之外、整合線還包括:平台外掛 / app 生態承擔的業務邏輯(Shopify app 做的折扣規則、WordPress 外掛做的預約流程)要逐個盤點、決定重寫進自建系統、換成獨立 SaaS、或趁機放棄;對外 webhook(ERP、出貨、會計系統)的端點切換要跟對方排時程;行銷 email 的寄送信譽綁在平台的寄件網域上、換到自有寄件網域要重建 SPF / DKIM 並逐步暖機、避免遷移週的通知信全進垃圾箱。
並行期設計
並行期是舊平台與新系統共存、用真實資料驗證新系統的階段 — 前提是目標系統已依 模組零的選型順序 建置完成、本章不重複選型推導。它跟 10.2 服務拆分執行 Runbook 的雙寫期同源但形狀不同:服務拆分時、寫入路徑在自己的程式碼裡、可以實作 dual write;託管平台的寫入發生在平台內部 — 顧客在 Shopify 結帳、會員在平台註冊 — 自建程式碼插不進那條寫入路徑。所以並行期的形態是「平台維持 source of truth、單向同步、新系統唯讀驗證」:
- 增量同步管道(webhook / API 輪詢 / 排程匯出)持續把平台變更餵進新系統
- 新系統以唯讀 replica 的角色運轉、對帳 job 定期比對兩邊的訂單數、會員數、金額總和
- 內部使用者先在新系統上工作(報表、後台查詢)、用真實業務流量驗證資料轉換的正確性
- 差異率收斂並穩定後、才排 cutover 日
Cutover 本身是一段 cutover window、不是一個按鈕:選低流量時段、短暫凍結平台側變更(電商常用「暫停結帳維護頁」幾十分鐘)、跑最後一輪增量同步、切 DNS、然後密集觀察訂單成功率、登入成功率、金流授權成功率 — 觀察清單來自資產線盤點、每條線各有自己的健康訊號。
回切窗口的設計決定這場遷移的失敗代價。cutover 後保留舊平台訂閱與設定、回切動作是 DNS 切回;代價是新系統在窗口內產生的交易要補回平台 — 平台側通常沒有批次匯入訂單的好路徑、補回多半是手動作業、所以回切窗口內要刻意壓低不可逆變更的累積速度(例如窗口前 48 小時內暫停大型行銷活動)。這跟 10.2 寫路徑切換的 point of no return 是同一個判讀:回退成本隨時間墊高、go/no-go 要當成有明確時點的決策執行、判定條件在進入窗口前排定。
關舊站走降級、而不是直接刪除。觀察期過後、平台帳號先降到最低方案、店面關閉但後台保留 — 退款處理、客服查歷史訂單、會計與稅務稽核都還會用到平台側資料。刪除帳號前的檢查條件:所有歷史資料已完整落地自有儲存並驗證可讀、法規要求的交易紀錄保存年限已由自有系統接手、最後一筆平台側退款 / 爭議單已結案。
部分遷出是常見的中繼形態
資產線可以獨立 cutover 的另一面、是遷出可以分期:先撤其中幾條線、其餘留在平台。部分遷出是把遷移風險拆期攤還的標準形態、結構上同 Strangler Fig:新系統從旁長出、逐線取代、平台最後才退役。
常見的中繼形態有四種。資料層先撤:增量同步管道建好之後、自有資料庫先成為報表與分析的 source、前台與結帳留在平台 — 0.21 BaaS 段描述的跨集合報表困境、在這個形態下已經解掉、而最高風險的金流與流量線還沒動。前台先撤(headless):自建前端體驗層、平台降級為後端引擎(結帳 API、內容 API)— 流量線與 SEO 控制權先回手、金流與資料留在平台的成熟路徑上。身分後撤:認證是使用者感知最強的線、Firebase Auth 這類可攜性好的元件常被留到最後 — 資料與流量都搬完、產品穩定後、再做密碼雜湊匯入或重設遷移。金流後撤(或長期留平台):訂閱授權轉移談不下來時、資料、前台與流量都遷出、訂閱扣款續走平台帳戶 — 它跟前三種不同、可能由中繼轉成長期形態、去留判讀回整合線的金流斷點確認。
中繼形態的判讀標準是「每個階段結束時、撤出的那條線已經完整脫離平台、由新系統持有唯一事實」。模糊狀態(一半訂單在平台、一半在自建、靠人腦記得哪邊查)是部分遷出最常見的事故源 — 每條線在任一時刻都要有唯一的 source of truth。
判讀訊號
| 訊號 | 判讀重點 | 對應動作 |
|---|---|---|
| 盤點時發現業務邏輯只存在平台 UI 設定裡 | 0.21 可遷出保險「業務邏輯文件化」缺項 | 先文件化再動手、規則重建期計入時程 |
| 並行期對帳差異率不收斂 | 資料轉換有 gap、或增量同步管道漏事件 | 暫停 cutover 排程、audit 轉換管線與 webhook |
| 金流商拒絕授權轉移 | 訂閱線變成全體重新授權、流失進入營收預估 | 重算遷移 ROI、評估訂閱線單獨延後 |
| Cutover 後自然流量持續下滑超過觀察期預估 | 轉址表缺漏、或索引替換異常 | 比對搜尋主控台的 404 清單、補轉址規則 |
| 回切窗口內手動補單量超出客服消化能力 | 不可逆變更累積速度超過回切設計 | 縮短決策週期、提前 go/no-go 判定 |
| 並行期超過原定窗口仍未排 cutover | 並行不是穩態、雙系統維運與平台月費在吃遷移 ROI | 重訂 cutover 條件、或承認部分遷出為長期形態 |
| 新舊系統各管一部分同類資料超過一個階段 | 部分遷出停在模糊狀態、source of truth 分裂 | 強制收斂該資產線、明確指定唯一 source of truth |
業務邏輯那一列值得展開:平台設定裡長出來的折扣邏輯、會員等級、運費規則、是盤點階段最容易漏的資產 — 它們沒有檔案形態、不會出現在任何匯出工具裡。0.21 可遷出保險清單把「業務邏輯文件化」列為進場保險、沒買這項保險的遷移、第一個階段是考古:對著平台後台逐頁截圖、把規則寫成文件、再評估哪些重寫、哪些放棄。
金流那一列是整場遷移裡少數「工程努力無法繞過」的斷點 — 授權轉移的決定權在金流商與平台的合約上、不在工程團隊手上。所以它在盤點階段就要最先確認:答案直接改變遷移的營收影響模型、甚至可能讓「訂閱線留在平台、其餘遷出」成為長期形態。
定位邊界
本章專注「託管形態 → 自建 / 半託管」的遷出執行。當問題回到「該不該遷、何時該重新評估」、回 0.21 交付形態選型 的升級自建 tripwire 表;遷移目標的自建選型(資料庫、部署、金流接法)走 模組零的選型順序;自建系統之間的資料庫搬遷技術細節(雙寫、shadow read、切換)進 1.6 資料庫轉換實作;服務層的漸進替換紀律進 10.2 服務拆分執行 Runbook。
下一步路由
要回頭確認遷移時機與保險、見 0.21 交付形態選型。要看並行期同源的雙寫與切流紀律、見 10.2 服務拆分執行 Runbook。遷入自建後的第一站、從 0.0 後端需求分類地圖 開始走選型順序。