<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Service-Selection on Tarragon</title><link>https://tarrragon.github.io/blog/tags/service-selection/</link><description>Recent content in Service-Selection on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Mon, 22 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/service-selection/index.xml" rel="self" type="application/rss+xml"/><item><title>FinTech：合規壓力下的後端選型</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/cases/fintech-compliance-and-selection-pressure/</link><pubDate>Thu, 07 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/cases/fintech-compliance-and-selection-pressure/</guid><description>&lt;p>這個案例的核心責任是把合規壓力轉成選型條件。FinTech 場景下，資料保留、審計追溯與交易一致性通常比純效能優先。&lt;/p>
&lt;h2 id="判讀訊號">判讀訊號&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>訊號&lt;/th>
 &lt;th>判讀重點&lt;/th>
 &lt;th>對應章節&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>audit evidence gap&lt;/td>
 &lt;td>稽核證據是否連續&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>duplicate transaction risk&lt;/td>
 &lt;td>重試是否可能造成雙重結果&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>release freeze frequency&lt;/td>
 &lt;td>發布是否常因風險臨時凍結&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="風險與邊界">風險與邊界&lt;/h2>
&lt;p>把合規當成部署後補強會抬高長期成本。較穩定的做法是在選型時就定義證據鏈、資料邊界與回復順序，避免後續跨模組反覆返工。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;p>先補 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/audit-log-governance/" data-link-title="4.12 Audit Log 邊界與 PII 治理" data-link-desc="把稽核訊號從 operational log 拆出、按法規與不變性治理">4.12&lt;/a> 的審計訊號，再用 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8&lt;/a> 定義合規變更門檻。&lt;/p></description><content:encoded><![CDATA[<p>這個案例的核心責任是把合規壓力轉成選型條件。FinTech 場景下，資料保留、審計追溯與交易一致性通常比純效能優先。</p>
<h2 id="判讀訊號">判讀訊號</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>判讀重點</th>
          <th>對應章節</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>audit evidence gap</td>
          <td>稽核證據是否連續</td>
          <td><a href="/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8</a></td>
      </tr>
      <tr>
          <td>duplicate transaction risk</td>
          <td>重試是否可能造成雙重結果</td>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a></td>
      </tr>
      <tr>
          <td>release freeze frequency</td>
          <td>發布是否常因風險臨時凍結</td>
          <td><a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
      </tr>
  </tbody>
</table>
<h2 id="風險與邊界">風險與邊界</h2>
<p>把合規當成部署後補強會抬高長期成本。較穩定的做法是在選型時就定義證據鏈、資料邊界與回復順序，避免後續跨模組反覆返工。</p>
<h2 id="下一步路由">下一步路由</h2>
<p>先補 <a href="/blog/backend/04-observability/audit-log-governance/" data-link-title="4.12 Audit Log 邊界與 PII 治理" data-link-desc="把稽核訊號從 operational log 拆出、按法規與不變性治理">4.12</a> 的審計訊號，再用 <a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8</a> 定義合規變更門檻。</p>
]]></content:encoded></item><item><title>0.1 後端服務能力地圖</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/service-capability-map/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/service-capability-map/</guid><description>&lt;p>後端服務能力地圖的核心原則是先辨識需求類型，再選擇服務分類。資料庫、快取、訊息佇列、觀測平台與部署平台都屬於後端能力，但它們分別回答「狀態放哪裡」、「讀取怎麼變快」、「工作怎麼跨 process」、「系統怎麼診斷」、「服務怎麼交付」。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>用需求類型辨識後端服務分類&lt;/li>
&lt;li>區分資料儲存、快取、訊息傳遞、觀測與部署平台&lt;/li>
&lt;li>判斷一個問題應先進入哪個 backend 模組&lt;/li>
&lt;li>避免把所有外部技術都混成同一種「基礎設施」&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="觀察需求會先表現成系統症狀">【觀察】需求會先表現成系統症狀&lt;/h2>
&lt;p>後端服務選型通常從症狀開始。產品需求或事故描述裡會出現一些可觀察訊號：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>需求訊號&lt;/th>
 &lt;th>代表的工程問題&lt;/th>
 &lt;th>優先評估方向&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>資料需要長期保存、查詢、交易一致性&lt;/td>
 &lt;td>狀態真相與持久化&lt;/td>
 &lt;td>資料庫&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>熱門資料讀取太頻繁、下游被打爆&lt;/td>
 &lt;td>讀取壓力與暫存&lt;/td>
 &lt;td>快取 / Redis&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>request 內完成工作太慢、需要重試或排隊&lt;/td>
 &lt;td>非同步處理與可靠傳遞&lt;/td>
 &lt;td>訊息佇列&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>出事時找不到原因、跨服務路徑不清楚&lt;/td>
 &lt;td>診斷與操作訊號&lt;/td>
 &lt;td>可觀測性平台&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>部署、擴容、流量入口與健康檢查不穩&lt;/td>
 &lt;td>服務交付與平台合約&lt;/td>
 &lt;td>部署平台&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表是索引。真正的選型要看每個訊號背後的資料生命週期、流量形狀與操作需求。&lt;/p>
&lt;h2 id="判讀資料長期存在通常先看資料庫">【判讀】資料長期存在通常先看資料庫&lt;/h2>
&lt;p>資料庫解決的是「系統承認哪份資料是正式狀態」。如果資料需要長期保存、支援查詢、維持交易一致性、被多個 request 共同讀寫，選型應先進入資料庫與持久化模組。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>電商訂單需要保存付款狀態、出貨狀態與退款紀錄&lt;/li>
&lt;li>會員系統需要保存帳號、權限、登入方式與審計資料&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">SaaS&lt;/a> 產品需要保存 workspace、plan、billing 與使用量&lt;/li>
&lt;/ul>
&lt;p>這類問題的核心是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth&lt;/a>。快取可以加速讀取，&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a> 可以延後處理，&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&lt;/a> 可以協助診斷，但正式狀態仍需要清楚的資料模型與一致性邊界。&lt;/p>
&lt;p>下一步可讀：&lt;a href="https://tarrragon.github.io/blog/backend/01-database/" data-link-title="模組一：資料庫與持久化" data-link-desc="整理 SQL、transaction、migration 與 repository adapter 的後端實務">資料庫與持久化&lt;/a>。&lt;/p>
&lt;h2 id="判讀讀取壓力集中通常先看快取">【判讀】讀取壓力集中通常先看快取&lt;/h2>
&lt;p>快取解決的是「同一類資料被重複讀取時，如何降低正式資料來源壓力」。如果資料本身已經有 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth&lt;/a>，但熱門資料導致資料庫或下游 API 壓力過高，選型應先進入快取與 Redis 模組。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>商品詳情頁被大量瀏覽，但商品資料變更頻率低&lt;/li>
&lt;li>使用者權限或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/feature-flag/" data-link-title="Feature Flag" data-link-desc="說明如何用可動態開關控制功能曝光與風險">Feature Flag&lt;/a> 每個 request 都要查&lt;/li>
&lt;li>即時服務需要快速查詢 client presence 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic&lt;/a> 訂閱狀態&lt;/li>
&lt;/ul>
&lt;p>這類問題的核心是讀取路徑與失效策略。快取要回答資料何時過期、何時更新、下游失敗時如何回應、cache &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-miss/" data-link-title="Cache Hit / Miss" data-link-desc="說明快取命中與未命中如何影響讀取成本與下游壓力">miss&lt;/a> 尖峰如何保護系統。&lt;/p>
&lt;p>下一步可讀：&lt;a href="https://tarrragon.github.io/blog/backend/02-cache-redis/" data-link-title="模組二：快取與 Redis" data-link-desc="整理快取策略、Redis 資料型別與分散式狀態輔助能力">快取與 Redis&lt;/a>。&lt;/p>
&lt;h2 id="判讀工作跨出-request-通常先看訊息傳遞">【判讀】工作跨出 request 通常先看訊息傳遞&lt;/h2>
&lt;p>訊息佇列解決的是「工作離開目前 process 或 request 後，如何可靠地被處理」。如果一個 request 需要觸發後續工作、等待外部系統、重試、批次處理或跨服務通知，選型應先進入訊息佇列與事件傳遞模組。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>付款成功後要寄信、更新 CRM、發送推播與建立出貨任務&lt;/li>
&lt;li>使用者上傳影片後要轉檔、產生縮圖與通知完成&lt;/li>
&lt;li>IoT 裝置上報資料後要清洗、聚合與觸發告警&lt;/li>
&lt;/ul>
&lt;p>這類問題的核心是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">delivery semantics&lt;/a>。系統要決定是否需要持久化、是否允許重複投遞、失敗是否重試、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer&lt;/a> 如何水平擴展。&lt;/p>
&lt;p>下一步可讀：&lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">訊息佇列與事件傳遞&lt;/a>。&lt;/p>
&lt;h2 id="判讀看不見系統行為通常先看觀測平台">【判讀】看不見系統行為通常先看觀測平台&lt;/h2>
&lt;p>可觀測性平台解決的是「服務發生什麼、為什麼發生、影響範圍多大」。如果事故發生後只能看單機 log，無法串起 request、事件、下游依賴與容量趨勢，選型應先進入可觀測性模組。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>API 偶爾變慢，但無法判斷是資料庫、外部 API 還是部署節點問題&lt;/li>
&lt;li>queue lag 上升，但不知道 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer&lt;/a> 變快還是 consumer 變慢&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/websocket/" data-link-title="WebSocket" data-link-desc="說明 WebSocket 如何提供長連線雙向即時通訊">WebSocket&lt;/a> client 斷線增加，但缺少連線生命週期與地區資訊&lt;/li>
&lt;/ul>
&lt;p>這類問題的核心是操作訊號。log、metric、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert&lt;/a> 需要共用欄位與關聯方式，才能讓工程師從症狀回到原因。&lt;/p>
&lt;p>下一步可讀：&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台&lt;/a>。&lt;/p>
&lt;h2 id="判讀服務交付不穩通常先看部署平台">【判讀】服務交付不穩通常先看部署平台&lt;/h2>
&lt;p>部署平台解決的是「服務如何被啟動、更新、擴容、接流量與停止」。如果問題集中在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rolling-update/" data-link-title="Rolling Update" data-link-desc="說明逐批替換服務版本的發版策略與風險控制">rolling update&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/health-check-liveness/" data-link-title="Liveness" data-link-desc="說明平台如何判斷 process 是否仍然存活，以及何時應重啟">liveness&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/load-balancer/" data-link-title="Load Balancer" data-link-desc="說明流量如何分散、排空與導向健康節點">load balancer&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/service-registry/" data-link-title="Service Registry" data-link-desc="說明服務實例如何被註冊、維護與摘除">service registry&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/service-discovery/" data-link-title="Service Discovery" data-link-desc="說明服務實例如何被查找與路由">service discovery&lt;/a>、container image 或資源限制，選型應先進入部署平台與網路入口模組。&lt;/p></description><content:encoded><![CDATA[<p>後端服務能力地圖的核心原則是先辨識需求類型，再選擇服務分類。資料庫、快取、訊息佇列、觀測平台與部署平台都屬於後端能力，但它們分別回答「狀態放哪裡」、「讀取怎麼變快」、「工作怎麼跨 process」、「系統怎麼診斷」、「服務怎麼交付」。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>用需求類型辨識後端服務分類</li>
<li>區分資料儲存、快取、訊息傳遞、觀測與部署平台</li>
<li>判斷一個問題應先進入哪個 backend 模組</li>
<li>避免把所有外部技術都混成同一種「基礎設施」</li>
</ol>
<hr>
<h2 id="觀察需求會先表現成系統症狀">【觀察】需求會先表現成系統症狀</h2>
<p>後端服務選型通常從症狀開始。產品需求或事故描述裡會出現一些可觀察訊號：</p>
<table>
  <thead>
      <tr>
          <th>需求訊號</th>
          <th>代表的工程問題</th>
          <th>優先評估方向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>資料需要長期保存、查詢、交易一致性</td>
          <td>狀態真相與持久化</td>
          <td>資料庫</td>
      </tr>
      <tr>
          <td>熱門資料讀取太頻繁、下游被打爆</td>
          <td>讀取壓力與暫存</td>
          <td>快取 / Redis</td>
      </tr>
      <tr>
          <td>request 內完成工作太慢、需要重試或排隊</td>
          <td>非同步處理與可靠傳遞</td>
          <td>訊息佇列</td>
      </tr>
      <tr>
          <td>出事時找不到原因、跨服務路徑不清楚</td>
          <td>診斷與操作訊號</td>
          <td>可觀測性平台</td>
      </tr>
      <tr>
          <td>部署、擴容、流量入口與健康檢查不穩</td>
          <td>服務交付與平台合約</td>
          <td>部署平台</td>
      </tr>
  </tbody>
</table>
<p>這張表是索引。真正的選型要看每個訊號背後的資料生命週期、流量形狀與操作需求。</p>
<h2 id="判讀資料長期存在通常先看資料庫">【判讀】資料長期存在通常先看資料庫</h2>
<p>資料庫解決的是「系統承認哪份資料是正式狀態」。如果資料需要長期保存、支援查詢、維持交易一致性、被多個 request 共同讀寫，選型應先進入資料庫與持久化模組。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>電商訂單需要保存付款狀態、出貨狀態與退款紀錄</li>
<li>會員系統需要保存帳號、權限、登入方式與審計資料</li>
<li><a href="/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">SaaS</a> 產品需要保存 workspace、plan、billing 與使用量</li>
</ul>
<p>這類問題的核心是 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a>。快取可以加速讀取，<a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a> 可以延後處理，<a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a> 可以協助診斷，但正式狀態仍需要清楚的資料模型與一致性邊界。</p>
<p>下一步可讀：<a href="/blog/backend/01-database/" data-link-title="模組一：資料庫與持久化" data-link-desc="整理 SQL、transaction、migration 與 repository adapter 的後端實務">資料庫與持久化</a>。</p>
<h2 id="判讀讀取壓力集中通常先看快取">【判讀】讀取壓力集中通常先看快取</h2>
<p>快取解決的是「同一類資料被重複讀取時，如何降低正式資料來源壓力」。如果資料本身已經有 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a>，但熱門資料導致資料庫或下游 API 壓力過高，選型應先進入快取與 Redis 模組。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>商品詳情頁被大量瀏覽，但商品資料變更頻率低</li>
<li>使用者權限或 <a href="/blog/backend/knowledge-cards/feature-flag/" data-link-title="Feature Flag" data-link-desc="說明如何用可動態開關控制功能曝光與風險">Feature Flag</a> 每個 request 都要查</li>
<li>即時服務需要快速查詢 client presence 或 <a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic</a> 訂閱狀態</li>
</ul>
<p>這類問題的核心是讀取路徑與失效策略。快取要回答資料何時過期、何時更新、下游失敗時如何回應、cache <a href="/blog/backend/knowledge-cards/cache-hit-miss/" data-link-title="Cache Hit / Miss" data-link-desc="說明快取命中與未命中如何影響讀取成本與下游壓力">miss</a> 尖峰如何保護系統。</p>
<p>下一步可讀：<a href="/blog/backend/02-cache-redis/" data-link-title="模組二：快取與 Redis" data-link-desc="整理快取策略、Redis 資料型別與分散式狀態輔助能力">快取與 Redis</a>。</p>
<h2 id="判讀工作跨出-request-通常先看訊息傳遞">【判讀】工作跨出 request 通常先看訊息傳遞</h2>
<p>訊息佇列解決的是「工作離開目前 process 或 request 後，如何可靠地被處理」。如果一個 request 需要觸發後續工作、等待外部系統、重試、批次處理或跨服務通知，選型應先進入訊息佇列與事件傳遞模組。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>付款成功後要寄信、更新 CRM、發送推播與建立出貨任務</li>
<li>使用者上傳影片後要轉檔、產生縮圖與通知完成</li>
<li>IoT 裝置上報資料後要清洗、聚合與觸發告警</li>
</ul>
<p>這類問題的核心是 <a href="/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">delivery semantics</a>。系統要決定是否需要持久化、是否允許重複投遞、失敗是否重試、<a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a> 如何水平擴展。</p>
<p>下一步可讀：<a href="/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">訊息佇列與事件傳遞</a>。</p>
<h2 id="判讀看不見系統行為通常先看觀測平台">【判讀】看不見系統行為通常先看觀測平台</h2>
<p>可觀測性平台解決的是「服務發生什麼、為什麼發生、影響範圍多大」。如果事故發生後只能看單機 log，無法串起 request、事件、下游依賴與容量趨勢，選型應先進入可觀測性模組。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>API 偶爾變慢，但無法判斷是資料庫、外部 API 還是部署節點問題</li>
<li>queue lag 上升，但不知道 <a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer</a> 變快還是 consumer 變慢</li>
<li><a href="/blog/backend/knowledge-cards/websocket/" data-link-title="WebSocket" data-link-desc="說明 WebSocket 如何提供長連線雙向即時通訊">WebSocket</a> client 斷線增加，但缺少連線生命週期與地區資訊</li>
</ul>
<p>這類問題的核心是操作訊號。log、metric、<a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a>、<a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> 與 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 需要共用欄位與關聯方式，才能讓工程師從症狀回到原因。</p>
<p>下一步可讀：<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台</a>。</p>
<h2 id="判讀服務交付不穩通常先看部署平台">【判讀】服務交付不穩通常先看部署平台</h2>
<p>部署平台解決的是「服務如何被啟動、更新、擴容、接流量與停止」。如果問題集中在 <a href="/blog/backend/knowledge-cards/rolling-update/" data-link-title="Rolling Update" data-link-desc="說明逐批替換服務版本的發版策略與風險控制">rolling update</a>、<a href="/blog/backend/knowledge-cards/health-check-liveness/" data-link-title="Liveness" data-link-desc="說明平台如何判斷 process 是否仍然存活，以及何時應重啟">liveness</a>、<a href="/blog/backend/knowledge-cards/load-balancer/" data-link-title="Load Balancer" data-link-desc="說明流量如何分散、排空與導向健康節點">load balancer</a>、<a href="/blog/backend/knowledge-cards/service-registry/" data-link-title="Service Registry" data-link-desc="說明服務實例如何被註冊、維護與摘除">service registry</a>、<a href="/blog/backend/knowledge-cards/service-discovery/" data-link-title="Service Discovery" data-link-desc="說明服務實例如何被查找與路由">service discovery</a>、container image 或資源限制，選型應先進入部署平台與網路入口模組。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>發版時部分 request 失敗，舊 pod 和新 pod 切換不穩</li>
<li>服務需要水平擴展，但 client 不知道該連到哪個 instance</li>
<li>shutdown 時仍有背景工作或長連線尚未清理</li>
</ul>
<p>這類問題的核心是平台合約。程式要提供 health、<a href="/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness</a>、shutdown 與資源使用訊號；平台要提供流量入口、排程、發版與回滾能力。</p>
<p>下一步可讀：<a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">部署平台與網路入口</a>。</p>
<p>進入規模成長路線時、能力地圖之外還要看四條額外章節：<a href="/blog/backend/10-system-evolution/service-decomposition-boundaries/" data-link-title="10.1 服務拆分與邊界判讀" data-link-desc="整理 monolith vs microservice 取捨、服務邊界判讀訊號、拆分時機與回退路徑">10.1 服務拆分與邊界判讀</a> 處理「該不該拆服務」、<a href="/blog/backend/00-service-selection/cloud-vendor-capability-mapping/" data-link-title="0.19 雲端服務對照地圖（AWS / GCP / Azure）" data-link-desc="把後端能力分類對照到 AWS / GCP / Azure 的具體服務名稱、保留跨雲遷移與選型差異的判讀重點">0.19 雲端服務對照地圖</a> 處理「該選哪家 vendor」、<a href="/blog/backend/09-performance-capacity/scaling-axes/" data-link-title="9.13 擴展軸與 Stateless 前提" data-link-desc="整理垂直 / 水平擴展取捨、stateless vs stateful 前提、auto scaling 操作模型與兩種擴展的 hidden cost">9.13 擴展軸與 Stateless 前提</a> 處理「該怎麼擴容」、<a href="/blog/backend/01-database/query-anti-patterns/" data-link-title="1.13 應用層查詢反模式與 Query 預算" data-link-desc="整理 N&#43;1、select *、缺索引、ORM lazy load、long transaction 等查詢反模式與每請求的 query 預算判讀">1.13 應用層查詢反模式</a> 處理「擴容前先優化什麼」。</p>
<h2 id="小結">小結</h2>
<p>後端服務選型先從需求類型開始。資料長期存在先看資料庫，讀取壓力集中先看快取，工作跨出 request 先看訊息傳遞，系統行為缺少可見性先看觀測平台，服務交付不穩先看部署平台。分類清楚後，後續產品選型與實作細節才會有正確位置。</p>
]]></content:encoded></item><item><title>Gaming：高峰流量與隔離邊界選型</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/cases/gaming-peak-traffic-and-isolation/</link><pubDate>Thu, 07 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/cases/gaming-peak-traffic-and-isolation/</guid><description>&lt;p>這個案例的核心責任是把活動高峰轉成預先可驗證的容量與隔離決策。Gaming 場景的失效通常來自瞬間峰值與連線風暴疊加。&lt;/p>
&lt;h2 id="判讀訊號">判讀訊號&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>訊號&lt;/th>
 &lt;th>判讀重點&lt;/th>
 &lt;th>對應章節&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>peak burst ratio&lt;/td>
 &lt;td>尖峰是否超過模型緩衝&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>matchmaking queue lag&lt;/td>
 &lt;td>非同步鏈路是否壅塞&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>reconnect storm indicator&lt;/td>
 &lt;td>回復是否放大負載&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="風險與邊界">風險與邊界&lt;/h2>
&lt;p>只追求低延遲而忽略隔離邊界，會在高峰時把單一熱點擴散成全域事故。選型時需要同時定義分流邏輯與分批恢復策略。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;p>把容量假設回寫 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/capacity-cost/" data-link-title="6.9 容量與成本邊界" data-link-desc="把容量規劃跟成本約束變成驗證輸入">6.9&lt;/a>，並在 &lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/multi-incident-coordination/" data-link-title="8.14 Multi-incident Coordination" data-link-desc="把同時多事故的優先序、資源分配與 incident command system pool 協調變成可執行流程">8.14&lt;/a> 補多事故協調規則。&lt;/p></description><content:encoded><![CDATA[<p>這個案例的核心責任是把活動高峰轉成預先可驗證的容量與隔離決策。Gaming 場景的失效通常來自瞬間峰值與連線風暴疊加。</p>
<h2 id="判讀訊號">判讀訊號</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>判讀重點</th>
          <th>對應章節</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>peak burst ratio</td>
          <td>尖峰是否超過模型緩衝</td>
          <td><a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a></td>
      </tr>
      <tr>
          <td>matchmaking queue lag</td>
          <td>非同步鏈路是否壅塞</td>
          <td><a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3</a></td>
      </tr>
      <tr>
          <td>reconnect storm indicator</td>
          <td>回復是否放大負載</td>
          <td><a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a></td>
      </tr>
  </tbody>
</table>
<h2 id="風險與邊界">風險與邊界</h2>
<p>只追求低延遲而忽略隔離邊界，會在高峰時把單一熱點擴散成全域事故。選型時需要同時定義分流邏輯與分批恢復策略。</p>
<h2 id="下一步路由">下一步路由</h2>
<p>把容量假設回寫 <a href="/blog/backend/06-reliability/capacity-cost/" data-link-title="6.9 容量與成本邊界" data-link-desc="把容量規劃跟成本約束變成驗證輸入">6.9</a>，並在 <a href="/blog/backend/08-incident-response/multi-incident-coordination/" data-link-title="8.14 Multi-incident Coordination" data-link-desc="把同時多事故的優先序、資源分配與 incident command system pool 協調變成可執行流程">8.14</a> 補多事故協調規則。</p>
]]></content:encoded></item><item><title>0.2 狀態與資料儲存選型</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/</guid><description>&lt;p>狀態與資料儲存選型的核心原則是先判斷資料責任。正式狀態、暫存資料、搜尋索引、事件歷史與大型檔案都屬於資料，但它們需要不同服務能力。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>區分 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth&lt;/a>、cache、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">search index&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">event log&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage&lt;/a>&lt;/li>
&lt;li>用資料生命週期判斷儲存服務類型&lt;/li>
&lt;li>看懂資料庫與 Redis、搜尋引擎、event store、object storage 的差異&lt;/li>
&lt;li>把資料選型轉成可檢查的工程判斷&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="觀察資料類型不同儲存責任也不同">【觀察】資料類型不同，儲存責任也不同&lt;/h2>
&lt;p>資料儲存服務的第一個問題是「這份資料扮演什麼責任」。同一份商品資料可以同時出現在 PostgreSQL、Redis、Elasticsearch、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">event log&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage&lt;/a> 裡，但每個位置的責任不同。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>資料責任&lt;/th>
 &lt;th>可觀察特徵&lt;/th>
 &lt;th>常見服務方向&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>正式狀態&lt;/td>
 &lt;td>需要交易、一致性、查詢與長期保存&lt;/td>
 &lt;td>SQL / document &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>暫存讀取&lt;/td>
 &lt;td>來源資料已存在，目標是降低讀取成本&lt;/td>
 &lt;td>Redis / cache&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>搜尋查詢&lt;/td>
 &lt;td>需要&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/full-text-search/" data-link-title="Full-Text Search" data-link-desc="說明全文檢索如何處理關鍵字匹配、語言分析與排序">全文搜尋&lt;/a>、排序、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/facet-query/" data-link-title="Facet Query" data-link-desc="說明分面查詢如何提供分類統計與篩選體驗">facet&lt;/a>、相關性&lt;/td>
 &lt;td>search engine&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>事件歷史&lt;/td>
 &lt;td>需要追蹤發生過的事、audit、replay&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">event log&lt;/a> / stream&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>大型檔案&lt;/td>
 &lt;td>需要保存圖片、影片、報表、備份&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表是索引。選型時要看資料是否能重建、是否需要一致性、是否要被使用者查詢、是否承擔稽核責任。&lt;/p>
&lt;h2 id="判讀source-of-truth-承擔正式狀態">【判讀】source of truth 承擔正式狀態&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">Source of truth&lt;/a> 的核心責任是保存系統承認的正式狀態。當資料需要被交易保護、被多個流程共同讀寫、支援一致查詢與長期保存時，應先評估資料庫。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>訂單狀態：created、paid、shipped、refunded&lt;/li>
&lt;li>會員帳號：email、password hash、角色、訂閱方案&lt;/li>
&lt;li>付款紀錄：交易 ID、金額、貨幣、狀態、時間&lt;/li>
&lt;/ul>
&lt;p>這類資料的主要風險是寫入一致性。服務要知道誰能改狀態、哪些欄位要一起成功、失敗後如何重試或補償。這些問題通常屬於資料庫與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">transaction&lt;/a> 邊界。&lt;/p>
&lt;h2 id="判讀cache-承擔可重建的讀取加速">【判讀】cache 承擔可重建的讀取加速&lt;/h2>
&lt;p>cache 的核心責任是降低讀取成本。快取資料應該能從 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth&lt;/a> 或下游服務重建；它的價值在於吸收熱門讀取、降低延遲、保護正式資料來源。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>商品詳情頁快取商品名稱、價格與庫存摘要&lt;/li>
&lt;li>使用者 session 或權限摘要&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/websocket/" data-link-title="WebSocket" data-link-desc="說明 WebSocket 如何提供長連線雙向即時通訊">WebSocket&lt;/a> presence 狀態與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic&lt;/a> 訂閱集合&lt;/li>
&lt;/ul>
&lt;p>這類資料的主要風險是過期與不一致。服務要知道 cache &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-miss/" data-link-title="Cache Hit / Miss" data-link-desc="說明快取命中與未命中如何影響讀取成本與下游壓力">miss&lt;/a> 怎麼處理、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ttl/" data-link-title="TTL" data-link-desc="說明資料過期時間如何影響快取新鮮度、成本與一致性">TTL&lt;/a> 如何設定、資料更新時如何失效、熱門 key 如何保護。&lt;/p>
&lt;h2 id="判讀search-index-承擔查詢體驗">【判讀】search index 承擔查詢體驗&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">Search index&lt;/a> 的核心責任是支援搜尋體驗。當使用者需要&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/full-text-search/" data-link-title="Full-Text Search" data-link-desc="說明全文檢索如何處理關鍵字匹配、語言分析與排序">全文搜尋&lt;/a>、排序、filter、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/facet-query/" data-link-title="Facet Query" data-link-desc="說明分面查詢如何提供分類統計與篩選體驗">facet&lt;/a>、autocomplete 或相關性排序，搜尋索引通常比一般資料庫查詢更合適。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>電商商品搜尋與分類篩選&lt;/li>
&lt;li>文件站全文搜尋&lt;/li>
&lt;li>企業知識庫搜尋與權限過濾&lt;/li>
&lt;/ul>
&lt;p>這類資料的主要風險是索引延遲與查詢語意。正式狀態通常仍在資料庫，&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">search index&lt;/a> 是為搜尋體驗建立的讀取模型。服務要知道資料更新後多久進索引、搜尋結果是否允許短暫延遲。&lt;/p>
&lt;h2 id="判讀event-log-承擔歷史與重播">【判讀】event log 承擔歷史與重播&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">Event log&lt;/a> 的核心責任是保存已發生的事。當系統需要 audit、replay、補送、狀態重建或跨服務事件傳遞，事件歷史就需要獨立設計。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>訂單狀態每次改變都要留下 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log&lt;/a>&lt;/li>
&lt;li>付款成功事件需要被通知、出貨、分析系統各自消費&lt;/li>
&lt;li>使用者行為事件需要進入分析 pipeline&lt;/li>
&lt;/ul>
&lt;p>這類資料的主要風險是順序、重複與 schema 演進。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">Event log&lt;/a> 要說明事件代表哪個 domain fact、如何去重、如何處理舊版本 payload。&lt;/p></description><content:encoded><![CDATA[<p>狀態與資料儲存選型的核心原則是先判斷資料責任。正式狀態、暫存資料、搜尋索引、事件歷史與大型檔案都屬於資料，但它們需要不同服務能力。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>區分 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a>、cache、<a href="/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">search index</a>、<a href="/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">event log</a> 與 <a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage</a></li>
<li>用資料生命週期判斷儲存服務類型</li>
<li>看懂資料庫與 Redis、搜尋引擎、event store、object storage 的差異</li>
<li>把資料選型轉成可檢查的工程判斷</li>
</ol>
<hr>
<h2 id="觀察資料類型不同儲存責任也不同">【觀察】資料類型不同，儲存責任也不同</h2>
<p>資料儲存服務的第一個問題是「這份資料扮演什麼責任」。同一份商品資料可以同時出現在 PostgreSQL、Redis、Elasticsearch、<a href="/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">event log</a> 與 <a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage</a> 裡，但每個位置的責任不同。</p>
<table>
  <thead>
      <tr>
          <th>資料責任</th>
          <th>可觀察特徵</th>
          <th>常見服務方向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>正式狀態</td>
          <td>需要交易、一致性、查詢與長期保存</td>
          <td>SQL / document <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a></td>
      </tr>
      <tr>
          <td>暫存讀取</td>
          <td>來源資料已存在，目標是降低讀取成本</td>
          <td>Redis / cache</td>
      </tr>
      <tr>
          <td>搜尋查詢</td>
          <td>需要<a href="/blog/backend/knowledge-cards/full-text-search/" data-link-title="Full-Text Search" data-link-desc="說明全文檢索如何處理關鍵字匹配、語言分析與排序">全文搜尋</a>、排序、<a href="/blog/backend/knowledge-cards/facet-query/" data-link-title="Facet Query" data-link-desc="說明分面查詢如何提供分類統計與篩選體驗">facet</a>、相關性</td>
          <td>search engine</td>
      </tr>
      <tr>
          <td>事件歷史</td>
          <td>需要追蹤發生過的事、audit、replay</td>
          <td><a href="/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">event log</a> / stream</td>
      </tr>
      <tr>
          <td>大型檔案</td>
          <td>需要保存圖片、影片、報表、備份</td>
          <td><a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage</a></td>
      </tr>
  </tbody>
</table>
<p>這張表是索引。選型時要看資料是否能重建、是否需要一致性、是否要被使用者查詢、是否承擔稽核責任。</p>
<h2 id="判讀source-of-truth-承擔正式狀態">【判讀】source of truth 承擔正式狀態</h2>
<p><a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">Source of truth</a> 的核心責任是保存系統承認的正式狀態。當資料需要被交易保護、被多個流程共同讀寫、支援一致查詢與長期保存時，應先評估資料庫。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>訂單狀態：created、paid、shipped、refunded</li>
<li>會員帳號：email、password hash、角色、訂閱方案</li>
<li>付款紀錄：交易 ID、金額、貨幣、狀態、時間</li>
</ul>
<p>這類資料的主要風險是寫入一致性。服務要知道誰能改狀態、哪些欄位要一起成功、失敗後如何重試或補償。這些問題通常屬於資料庫與 <a href="/blog/backend/knowledge-cards/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">transaction</a> 邊界。</p>
<h2 id="判讀cache-承擔可重建的讀取加速">【判讀】cache 承擔可重建的讀取加速</h2>
<p>cache 的核心責任是降低讀取成本。快取資料應該能從 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a> 或下游服務重建；它的價值在於吸收熱門讀取、降低延遲、保護正式資料來源。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>商品詳情頁快取商品名稱、價格與庫存摘要</li>
<li>使用者 session 或權限摘要</li>
<li><a href="/blog/backend/knowledge-cards/websocket/" data-link-title="WebSocket" data-link-desc="說明 WebSocket 如何提供長連線雙向即時通訊">WebSocket</a> presence 狀態與 <a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic</a> 訂閱集合</li>
</ul>
<p>這類資料的主要風險是過期與不一致。服務要知道 cache <a href="/blog/backend/knowledge-cards/cache-hit-miss/" data-link-title="Cache Hit / Miss" data-link-desc="說明快取命中與未命中如何影響讀取成本與下游壓力">miss</a> 怎麼處理、<a href="/blog/backend/knowledge-cards/ttl/" data-link-title="TTL" data-link-desc="說明資料過期時間如何影響快取新鮮度、成本與一致性">TTL</a> 如何設定、資料更新時如何失效、熱門 key 如何保護。</p>
<h2 id="判讀search-index-承擔查詢體驗">【判讀】search index 承擔查詢體驗</h2>
<p><a href="/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">Search index</a> 的核心責任是支援搜尋體驗。當使用者需要<a href="/blog/backend/knowledge-cards/full-text-search/" data-link-title="Full-Text Search" data-link-desc="說明全文檢索如何處理關鍵字匹配、語言分析與排序">全文搜尋</a>、排序、filter、<a href="/blog/backend/knowledge-cards/facet-query/" data-link-title="Facet Query" data-link-desc="說明分面查詢如何提供分類統計與篩選體驗">facet</a>、autocomplete 或相關性排序，搜尋索引通常比一般資料庫查詢更合適。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>電商商品搜尋與分類篩選</li>
<li>文件站全文搜尋</li>
<li>企業知識庫搜尋與權限過濾</li>
</ul>
<p>這類資料的主要風險是索引延遲與查詢語意。正式狀態通常仍在資料庫，<a href="/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">search index</a> 是為搜尋體驗建立的讀取模型。服務要知道資料更新後多久進索引、搜尋結果是否允許短暫延遲。</p>
<h2 id="判讀event-log-承擔歷史與重播">【判讀】event log 承擔歷史與重播</h2>
<p><a href="/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">Event log</a> 的核心責任是保存已發生的事。當系統需要 audit、replay、補送、狀態重建或跨服務事件傳遞，事件歷史就需要獨立設計。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>訂單狀態每次改變都要留下 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a></li>
<li>付款成功事件需要被通知、出貨、分析系統各自消費</li>
<li>使用者行為事件需要進入分析 pipeline</li>
</ul>
<p>這類資料的主要風險是順序、重複與 schema 演進。<a href="/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">Event log</a> 要說明事件代表哪個 domain fact、如何去重、如何處理舊版本 payload。</p>
<h2 id="判讀object-storage-承擔大型非結構化資料">【判讀】object storage 承擔大型非結構化資料</h2>
<p><a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">Object storage</a> 的核心責任是保存大型 blob。當資料是圖片、影片、PDF、匯出報表、備份檔或模型檔案，儲存服務通常需要 object storage，而正式 metadata 放在資料庫。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>使用者上傳的大頭貼、附件與影片</li>
<li>每日報表匯出的 CSV 或 PDF</li>
<li>系統備份、稽核封存與資料匯出檔</li>
</ul>
<p>這類資料的主要風險是存取權限、生命週期、版本與連結有效性。資料庫保存 object key、owner、狀態與 metadata；<a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage</a> 保存實際檔案內容。</p>
<h2 id="檢查進入實作前的概念邊界清單">【檢查】進入實作前的概念邊界清單</h2>
<p>當以下問題都能回答時，代表本章的概念層已完成，可以進入資料儲存實作章節：</p>
<ol>
<li>每一類資料的責任是否明確（正式狀態、快取、搜尋、事件、檔案）</li>
<li>每一類資料的真實來源是否明確（source of truth 在哪裡）</li>
<li>每一類資料是否定義一致性與延遲容忍度</li>
<li>每一類資料是否定義保留期限與回復方式</li>
</ol>
<p>下一步建議路由：</p>
<ul>
<li><a href="/blog/backend/01-database/" data-link-title="模組一：資料庫與持久化" data-link-desc="整理 SQL、transaction、migration 與 repository adapter 的後端實務">01-database</a></li>
<li><a href="/blog/backend/02-cache-redis/" data-link-title="模組二：快取與 Redis" data-link-desc="整理快取策略、Redis 資料型別與分散式狀態輔助能力">02-cache-redis</a></li>
</ul>
<h2 id="小結">小結</h2>
<p>資料儲存選型要先問資料責任。正式狀態進資料庫，可重建讀取資料進快取，搜尋體驗用 <a href="/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">search index</a>，歷史與重播用 <a href="/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">event log</a>，大型檔案用 <a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage</a>。責任分清楚後，同一份業務資料可以出現在多個服務中，但每個服務的位置都能被解釋。</p>
]]></content:encoded></item><item><title>Healthcare：資料主權與回復順序選型</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/cases/healthcare-data-sovereignty-and-recovery/</link><pubDate>Thu, 07 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/cases/healthcare-data-sovereignty-and-recovery/</guid><description>&lt;p>這個案例的核心責任是讓資料主權與可用性同時被治理。Healthcare 場景常同時面臨資料區域限制、最小存取原則與緊急回復需求。&lt;/p>
&lt;h2 id="判讀訊號">判讀訊號&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>訊號&lt;/th>
 &lt;th>判讀重點&lt;/th>
 &lt;th>對應章節&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>cross-region data movement&lt;/td>
 &lt;td>是否違反主權邊界&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>access audit completeness&lt;/td>
 &lt;td>存取證據是否可追溯&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>recovery ordering conflict&lt;/td>
 &lt;td>回復步驟是否與合規衝突&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="風險與邊界">風險與邊界&lt;/h2>
&lt;p>將合規需求與 DR 流程分開設計，容易在事故時出現互斥決策。較穩定做法是先定義可恢復資料集合與不可跨境資料集合，再安排回復順序。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;p>先補 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/observability-operating-model/" data-link-title="4.18 Observability Operating Model" data-link-desc="定義 platform / service team / on-call 對訊號、dashboard、alert 與成本的 ownership">4.18&lt;/a> 的責任邊界，再在 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/dr-rollback-rehearsal/" data-link-title="6.7 DR 演練與 Rollback Rehearsal" data-link-desc="把回復路徑從紙面計畫變成定期可重播、可量測的驗證流程">6.7&lt;/a> 驗證回復流程。&lt;/p></description><content:encoded><![CDATA[<p>這個案例的核心責任是讓資料主權與可用性同時被治理。Healthcare 場景常同時面臨資料區域限制、最小存取原則與緊急回復需求。</p>
<h2 id="判讀訊號">判讀訊號</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>判讀重點</th>
          <th>對應章節</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>cross-region data movement</td>
          <td>是否違反主權邊界</td>
          <td><a href="/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8</a></td>
      </tr>
      <tr>
          <td>access audit completeness</td>
          <td>存取證據是否可追溯</td>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a></td>
      </tr>
      <tr>
          <td>recovery ordering conflict</td>
          <td>回復步驟是否與合規衝突</td>
          <td><a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a></td>
      </tr>
  </tbody>
</table>
<h2 id="風險與邊界">風險與邊界</h2>
<p>將合規需求與 DR 流程分開設計，容易在事故時出現互斥決策。較穩定做法是先定義可恢復資料集合與不可跨境資料集合，再安排回復順序。</p>
<h2 id="下一步路由">下一步路由</h2>
<p>先補 <a href="/blog/backend/04-observability/observability-operating-model/" data-link-title="4.18 Observability Operating Model" data-link-desc="定義 platform / service team / on-call 對訊號、dashboard、alert 與成本的 ownership">4.18</a> 的責任邊界，再在 <a href="/blog/backend/06-reliability/dr-rollback-rehearsal/" data-link-title="6.7 DR 演練與 Rollback Rehearsal" data-link-desc="把回復路徑從紙面計畫變成定期可重播、可量測的驗證流程">6.7</a> 驗證回復流程。</p>
]]></content:encoded></item><item><title>0.3 非同步與事件傳遞選型</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/async-delivery-selection/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/async-delivery-selection/</guid><description>&lt;p>非同步與事件傳遞選型的核心原則是先判斷工作離開 request 後需要什麼保證。背景工作、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue&lt;/a>、stream、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">pub/sub&lt;/a> 與 outbox 都能讓流程非同步化，但它們對持久化、重試、順序、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out&lt;/a> 與一致性的承諾不同。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>區分本地背景工作、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a> &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a>、stream、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">pub/sub&lt;/a> 與 outbox&lt;/li>
&lt;li>用投遞保證、重試需求與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out&lt;/a> 需求判斷服務類型&lt;/li>
&lt;li>看懂 RabbitMQ、Kafka、NATS、Redis Streams 這類工具的選型入口&lt;/li>
&lt;li>把非同步設計轉成可檢查的工程判斷&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="觀察非同步需求來自-request-邊界外的工作">【觀察】非同步需求來自 request 邊界外的工作&lt;/h2>
&lt;p>非同步處理通常從一個現象開始：某件事適合在 request 結束後繼續做。這可能是因為工作太慢、需要重試、需要多個 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer&lt;/a>、需要跨服務傳遞，或需要在資料庫交易後補送事件。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>需求訊號&lt;/th>
 &lt;th>代表的工程問題&lt;/th>
 &lt;th>常見服務方向&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>工作只需要離開 request，但留在同一 process&lt;/td>
 &lt;td>背景處理與生命週期&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/local-worker/" data-link-title="Local Worker" data-link-desc="說明同一個 process 內的背景工作模型與其生命週期邊界">local worker&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>工作需要 process 重啟後仍存在&lt;/td>
 &lt;td>持久化與重試&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>多個 consumer 要各自追進度&lt;/td>
 &lt;td>replay、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">offset&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group&lt;/a>&lt;/td>
 &lt;td>stream / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>多個訂閱者即時收到訊息&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out&lt;/a> 與即時通知&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">pub/sub&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>資料寫入和事件發布要一起可靠&lt;/td>
 &lt;td>交易一致性與補送&lt;/td>
 &lt;td>outbox&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表是索引。選型時要看事件是否能遺失、是否會重複、是否要重播、是否要多個服務各自消費。&lt;/p>
&lt;h2 id="判讀local-worker-承擔-process-內背景工作">【判讀】local worker 承擔 process 內背景工作&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/local-worker/" data-link-title="Local Worker" data-link-desc="說明同一個 process 內的背景工作模型與其生命週期邊界">Local worker&lt;/a> 的核心責任是把工作從 request 等待時間中拆出來，但仍留在同一個 process 裡。當工作可以接受 process 重啟後消失，或上游可以重新觸發，&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/local-worker/" data-link-title="Local Worker" data-link-desc="說明同一個 process 內的背景工作模型與其生命週期邊界">local worker&lt;/a> 通常足夠。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>request 完成後寫一筆非關鍵 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log&lt;/a>&lt;/li>
&lt;li>在同一服務內批次刷新短生命週期快取&lt;/li>
&lt;li>定期清理 memory repository 裡的過期資料&lt;/li>
&lt;/ul>
&lt;p>這類設計的主要風險是生命週期。worker 要能停止、記錄錯誤、控制 queue full，並在 shutdown 時有明確策略。語言教材通常會處理這一層，例如 Go 的 &lt;code>Run(ctx)&lt;/code>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/in-process-channel/" data-link-title="In-Process Channel" data-link-desc="說明單一 process 內用來傳遞工作的 channel 或 queue abstraction">in-process channel&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/worker-pool/" data-link-title="Worker Pool" data-link-desc="說明一組 worker 如何限制同時處理量並保護下游資源">worker pool&lt;/a>。&lt;/p>
&lt;h2 id="判讀durable-queue-承擔可重試工作">【判讀】durable queue 承擔可重試工作&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">Durable queue&lt;/a> 的核心責任是讓工作在 process 重啟、暫時失敗或 consumer 下線後仍能被處理。當事件可以延後，但需要可靠送達與重試，應評估 broker queue。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p></description><content:encoded><![CDATA[<p>非同步與事件傳遞選型的核心原則是先判斷工作離開 request 後需要什麼保證。背景工作、<a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue</a>、stream、<a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">pub/sub</a> 與 outbox 都能讓流程非同步化，但它們對持久化、重試、順序、<a href="/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out</a> 與一致性的承諾不同。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>區分本地背景工作、<a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a>、stream、<a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">pub/sub</a> 與 outbox</li>
<li>用投遞保證、重試需求與 <a href="/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out</a> 需求判斷服務類型</li>
<li>看懂 RabbitMQ、Kafka、NATS、Redis Streams 這類工具的選型入口</li>
<li>把非同步設計轉成可檢查的工程判斷</li>
</ol>
<hr>
<h2 id="觀察非同步需求來自-request-邊界外的工作">【觀察】非同步需求來自 request 邊界外的工作</h2>
<p>非同步處理通常從一個現象開始：某件事適合在 request 結束後繼續做。這可能是因為工作太慢、需要重試、需要多個 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a>、需要跨服務傳遞，或需要在資料庫交易後補送事件。</p>
<table>
  <thead>
      <tr>
          <th>需求訊號</th>
          <th>代表的工程問題</th>
          <th>常見服務方向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>工作只需要離開 request，但留在同一 process</td>
          <td>背景處理與生命週期</td>
          <td><a href="/blog/backend/knowledge-cards/local-worker/" data-link-title="Local Worker" data-link-desc="說明同一個 process 內的背景工作模型與其生命週期邊界">local worker</a></td>
      </tr>
      <tr>
          <td>工作需要 process 重啟後仍存在</td>
          <td>持久化與重試</td>
          <td><a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue</a></td>
      </tr>
      <tr>
          <td>多個 consumer 要各自追進度</td>
          <td>replay、<a href="/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">offset</a>、<a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group</a></td>
          <td>stream / <a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a></td>
      </tr>
      <tr>
          <td>多個訂閱者即時收到訊息</td>
          <td><a href="/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out</a> 與即時通知</td>
          <td><a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">pub/sub</a></td>
      </tr>
      <tr>
          <td>資料寫入和事件發布要一起可靠</td>
          <td>交易一致性與補送</td>
          <td>outbox</td>
      </tr>
  </tbody>
</table>
<p>這張表是索引。選型時要看事件是否能遺失、是否會重複、是否要重播、是否要多個服務各自消費。</p>
<h2 id="判讀local-worker-承擔-process-內背景工作">【判讀】local worker 承擔 process 內背景工作</h2>
<p><a href="/blog/backend/knowledge-cards/local-worker/" data-link-title="Local Worker" data-link-desc="說明同一個 process 內的背景工作模型與其生命週期邊界">Local worker</a> 的核心責任是把工作從 request 等待時間中拆出來，但仍留在同一個 process 裡。當工作可以接受 process 重啟後消失，或上游可以重新觸發，<a href="/blog/backend/knowledge-cards/local-worker/" data-link-title="Local Worker" data-link-desc="說明同一個 process 內的背景工作模型與其生命週期邊界">local worker</a> 通常足夠。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>request 完成後寫一筆非關鍵 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a></li>
<li>在同一服務內批次刷新短生命週期快取</li>
<li>定期清理 memory repository 裡的過期資料</li>
</ul>
<p>這類設計的主要風險是生命週期。worker 要能停止、記錄錯誤、控制 queue full，並在 shutdown 時有明確策略。語言教材通常會處理這一層，例如 Go 的 <code>Run(ctx)</code>、<a href="/blog/backend/knowledge-cards/in-process-channel/" data-link-title="In-Process Channel" data-link-desc="說明單一 process 內用來傳遞工作的 channel 或 queue abstraction">in-process channel</a> 與 <a href="/blog/backend/knowledge-cards/worker-pool/" data-link-title="Worker Pool" data-link-desc="說明一組 worker 如何限制同時處理量並保護下游資源">worker pool</a>。</p>
<h2 id="判讀durable-queue-承擔可重試工作">【判讀】durable queue 承擔可重試工作</h2>
<p><a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">Durable queue</a> 的核心責任是讓工作在 process 重啟、暫時失敗或 consumer 下線後仍能被處理。當事件可以延後，但需要可靠送達與重試，應評估 broker queue。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>付款成功後寄送 email、簡訊與推播</li>
<li>上傳影片後排隊轉檔</li>
<li>訂單成立後建立出貨任務</li>
</ul>
<p>這類設計的主要風險是 <a href="/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">delivery semantics</a>。服務要決定 <a href="/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">ack/nack</a>、retry、<a href="/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">dead-letter queue</a>、<a href="/blog/backend/knowledge-cards/poison-message/" data-link-title="Poison Message" data-link-desc="說明特定訊息內容如何穩定造成 consumer 失敗">poison message</a> 與 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a>。RabbitMQ、NATS JetStream、Redis Streams 都可以承擔部分 durable delivery，但模型不同。</p>
<h2 id="判讀stream-承擔可重播事件序列">【判讀】stream 承擔可重播事件序列</h2>
<p>stream 的核心責任是保存事件序列，讓 consumer 可以依自己的進度讀取。當資料需要 replay、多個 consumer group、offset 或 <a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition</a> ordering，stream 模型會比單純 queue 更合適。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>使用者行為事件進入分析 pipeline</li>
<li>訂單事件同時給推薦、風控、報表系統消費</li>
<li>IoT sensor readings 需要持續聚合與回放</li>
</ul>
<p>這類設計的主要風險是順序、保留期限與 schema 演進。Kafka、Redis Streams、NATS JetStream 都提供不同程度的 stream 能力；選型時要看 <a href="/blog/backend/knowledge-cards/throughput/" data-link-title="Throughput" data-link-desc="整理系統單位時間內可處理的工作量">throughput</a>、consumer group、保留策略與操作成本。</p>
<h2 id="判讀pubsub-承擔即時-fan-out">【判讀】pub/sub 承擔即時 fan-out</h2>
<p><a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">Pub/Sub</a> 的核心責任是把訊息即時傳給目前訂閱者。當訊息偏向即時通知，且訂閱者離線後可以透過 <a href="/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">offline catch-up</a> 補狀態，<a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">pub/sub</a> 通常是好候選。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li><a href="/blog/backend/knowledge-cards/websocket/" data-link-title="WebSocket" data-link-desc="說明 WebSocket 如何提供長連線雙向即時通訊">WebSocket</a> server 跨節點廣播 <a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic</a> update</li>
<li>presence 狀態變更通知在線 client</li>
<li><a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> 即時刷新目前任務進度</li>
</ul>
<p>這類設計的主要風險是 <a href="/blog/backend/knowledge-cards/reliability-boundary/" data-link-title="Reliability Boundary" data-link-desc="說明系統在哪個邊界內承諾可靠傳遞，邊界外需要哪些補償機制">reliability boundary</a>。pub/sub 適合即時 <a href="/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out</a>；若訊息需要 <a href="/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">offline catch-up</a>、audit 或 <a href="/blog/backend/knowledge-cards/strong-reliability/" data-link-title="Strong Reliability" data-link-desc="說明高可靠事件路徑需要的保存、重試、去重與回復責任">strong reliability</a>，通常還需要 <a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue</a>、<a href="/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">event log</a> 或資料庫狀態搭配。</p>
<h2 id="判讀outbox-承擔資料寫入與事件補送">【判讀】outbox 承擔資料寫入與事件補送</h2>
<p>outbox 的核心責任是把業務資料寫入和待發事件放進同一個資料庫交易，再由 publisher 補送。當狀態更新成功後必須可靠發布事件，outbox 是常見選型。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>訂單寫入成功後必須發布 <code>order.created</code></li>
<li>付款狀態更新後必須通知出貨與報表系統</li>
<li>帳號停用後必須可靠通知所有安全相關服務</li>
</ul>
<p>這類設計的主要風險是半成功。outbox 讓事件至少會被發現並補送；consumer 仍需要 idempotency，因為補送與重試可能造成重複投遞。</p>
<h2 id="判讀用業務形狀反推-broker-候選">【判讀】用業務形狀反推 broker 候選</h2>
<p>反推的核心責任是把「目前場景需要的吞吐、延遲、保留窗口與操作承擔」轉成 broker 候選、不是從 vendor 規格表挑工具。先決定需求形狀、再對齊量級訊號、最後才挑工具。</p>
<p>接近真實網路服務的反推路徑：</p>
<ul>
<li>感測器一秒上報幾百筆、可接受偶發遺失、後端只需即時聚合 → broker 候選是 MQTT broker / NATS、量級訊號 sub-ms 延遲 + 萬到十萬 msg/sec</li>
<li>訂單事件需要多個下游服務各自 replay、保留 7 天以上 → broker 候選是 Kafka / Pulsar、量級訊號 partition 化吞吐 + retention 天 / 週 / 月可設</li>
<li>寄信、轉檔等可重試任務、不要遺失但允許短暫延遲 → broker 候選是 RabbitMQ / SQS、量級訊號萬級 msg/sec + ack/nack + dead-letter</li>
<li>跨節點即時通知在線 client、訂閱者離線可放棄 → broker 候選是 Redis Pub/Sub / NATS、量級訊號 sub-ms + 即時廣播、不保留</li>
</ul>
<p>反推的目的是把「broker 比較」轉成「需求對齊」、避免從 vendor 規格表開始挑工具。下面四個維度是反推時要對齊的量級訊號。</p>
<h3 id="吞吐量訊號">吞吐量訊號</h3>
<p>吞吐評估的核心問題是「broker 在我的 topology 下能撐多少」、不是「broker 規格上限」。同一個 broker 在不同 partition / queue / consumer / 訊息大小下、實際吞吐可以差一個量級。</p>
<p>實務量級（典型值、視配置與部署）：</p>
<table>
  <thead>
      <tr>
          <th>broker 類型</th>
          <th>單節點典型吞吐</th>
          <th>量級擴張條件</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>MQTT broker</td>
          <td>萬到十萬 msg/sec</td>
          <td>連線數 / topic 樹深度</td>
      </tr>
      <tr>
          <td>RabbitMQ classic queue</td>
          <td>萬級 msg/sec</td>
          <td>quorum queue / stream / cluster scaling</td>
      </tr>
      <tr>
          <td>Redis Streams</td>
          <td>十萬 msg/sec</td>
          <td>shard / consumer group</td>
      </tr>
      <tr>
          <td>NATS JetStream</td>
          <td>十萬到百萬 msg/sec</td>
          <td>subject hierarchy / cluster</td>
      </tr>
      <tr>
          <td>Kafka</td>
          <td>百萬 msg/sec（partition + batch）</td>
          <td>partition 數 + batch.size + linger.ms</td>
      </tr>
      <tr>
          <td>Managed queue（SQS 等）</td>
          <td>視 account quota</td>
          <td>region / 訊息大小</td>
      </tr>
  </tbody>
</table>
<p>對齊的問題是尖峰打進來後 broker 是否仍有 headroom（見 <a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5 流量與資料量評估</a>）。穩定流量 × 尖峰倍率 × <a href="/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out</a> 倍率才是真正要對齊的數字。</p>
<h3 id="延遲訊號">延遲訊號</h3>
<p>延遲評估的核心問題是「業務能容忍 P99 多少」、跟 broker 級延遲特性對齊。請求-應答、fire-and-forget、事件流的可容忍延遲是不同量級。</p>
<p>實務量級：</p>
<ul>
<li>sub-ms 到個位數 ms：MQTT broker、NATS、Redis Pub/Sub — 即時通知 / 控制信號 / IoT 上報</li>
<li>個位數 ms：RabbitMQ classic queue、Redis Streams — 任務隊列 / 中等延遲事件</li>
<li>十 ms 到百 ms：Kafka（低 batch）、managed pub/sub — 事件流 / 分析 pipeline</li>
<li>百 ms 以上：Kafka 高 batch、SQS standard — 批次處理 / 容忍延遲的補送</li>
</ul>
<p>陷阱是把「broker 內部延遲」當成「端到端延遲」。實際端到端通常被 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a> 處理時間 + 下游 I/O 主導、不是 broker 傳遞時間。</p>
<h3 id="保留窗口訊號">保留窗口訊號</h3>
<p>保留窗口的核心問題是「事件需要被未來多久內的 consumer 讀到」。任務隊列吃掉就丟、事件流要可 replay、分析 pipeline 要留週級到月級。</p>
<p>實務量級：</p>
<ul>
<li>不保留 / 短期：Redis Pub/Sub、MQTT QoS 0 — 只給「現在」訂閱者</li>
<li>queue 級（持久但 ack 後刪）：RabbitMQ classic queue、SQS（最長 14 天）</li>
<li>中期（小時到天、受 RAM）：Redis Streams</li>
<li>天到月級（log-based、<a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention</a> policy）：Kafka、Pulsar、NATS JetStream</li>
<li>永久 / tiered：Kafka tiered storage、Pulsar tiered storage</li>
</ul>
<p>保留窗口直接影響成本：log-based broker 的儲存成本隨保留期線性增加、queue-based broker 的成本主要由「待處理深度」決定。</p>
<h3 id="操作複雜度訊號">操作複雜度訊號</h3>
<p>複雜度評估的核心問題是「團隊願意承擔哪些日常運維」、不是「broker 安裝多難」。安裝跟運維是不同量級工作。</p>
<p>實務量級：</p>
<ul>
<li>低（managed）：SQS、Google Pub/Sub — quota / IAM / DLQ drain 是主要工作</li>
<li>低到中（self-host 但運維輕）：Redis Streams、NATS — 跟 Redis / NATS 本體運維捆綁</li>
<li>中（broker 級運維）：RabbitMQ — Erlang / clustering / mirrored vs quorum / network partition 處理</li>
<li>高（平台級運維）：Kafka self-host — partition rebalance / <a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag</a> / KRaft / topic governance / 跨 cluster 路由</li>
</ul>
<p>複雜度的真正成本不在初期 setup、在「事故時誰能讀懂訊號」。挑 broker 時要問「下次 lag 暴增、團隊能在多久內找到原因」、這比 broker 規格表更接近真實業務考慮。</p>
<h3 id="反推的常見陷阱">反推的常見陷阱</h3>
<p>把「broker 規格上限」當需求對齊基準、會導致過度選型。Kafka 規格上百萬 msg/sec 不代表你需要 — 多數任務隊列場景在 RabbitMQ 萬級吞吐就足夠、Kafka 的 partition / consumer group / retention 治理成本反而是負擔。</p>
<p>把「現在吞吐」當未來基準、會導致欠選型。新 broker 通常要支撐 2-3 年成長、評估時要乘上預期成長倍率再對齊量級訊號。</p>
<p>把「規格表」當「實測值」、會在實際 topology 出問題。Broker 規格數字通常在最佳化測試環境得到、實際 production 受訊息大小 / consumer 速度 / 網路延遲 / replication factor 影響、實測常見差距 30%-60%。</p>
<h2 id="檢查進入實作前的概念邊界清單">【檢查】進入實作前的概念邊界清單</h2>
<p>當以下問題都能回答時，代表本章的概念層已完成，可以進入訊息傳遞實作章節：</p>
<ol>
<li>每種事件的投遞語意是否明確（可遺失、可重試、可重播）</li>
<li>事件失敗後的路徑是否明確（retry、DLQ、replay）</li>
<li>consumer 的去重責任是否明確（idempotency 範圍與語意鍵）</li>
<li>壓力保護條件是否明確（lag、<a href="/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">queue depth</a>、降級觸發）</li>
</ol>
<p>下一步建議路由：</p>
<ul>
<li><a href="/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">03-message-queue</a></li>
<li><a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">08-incident-response</a></li>
</ul>
<h2 id="小結">小結</h2>
<p>非同步選型要先看工作需要什麼保證。本地工作用 <a href="/blog/backend/knowledge-cards/local-worker/" data-link-title="Local Worker" data-link-desc="說明同一個 process 內的背景工作模型與其生命週期邊界">local worker</a>，可重試工作用 <a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue</a>，可重播事件序列用 stream，即時 <a href="/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out</a> 用 <a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">pub/sub</a>，資料寫入與事件發布一致性用 outbox。分類清楚後，RabbitMQ、Kafka、NATS、Redis Streams 等工具比較才有意義。</p>
]]></content:encoded></item><item><title>營運後技術轉換：語言、工具與架構何時該換</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/cases/post-scale-migration-language-tool-architecture/</link><pubDate>Thu, 07 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/cases/post-scale-migration-language-tool-architecture/</guid><description>&lt;p>這個案例的核心責任是把「營運後轉換」變成可判讀決策，而不是技術潮流追逐。服務在成長期常會遇到早期選型與現況負載不再匹配，此時轉換的重點是風險收斂與效率改善，而不是語言偏好。&lt;/p>
&lt;h2 id="大量真實案例與轉換原因">大量真實案例與轉換原因&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>案例&lt;/th>
 &lt;th>轉換類型&lt;/th>
 &lt;th>為什麼轉換&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Slack：PHP 逐步遷移到 Hack&lt;/td>
 &lt;td>語言/型別系統&lt;/td>
 &lt;td>以漸進式靜態型別提升重構安全與開發效率，降低 runtime 才暴露型別錯誤的成本。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Discord：Read States 服務 Go 重寫為 Rust&lt;/td>
 &lt;td>語言/執行模型&lt;/td>
 &lt;td>Go 服務在特定負載下出現 GC 造成的週期性延遲尖峰，Rust 以無 GC 記憶體模型降低延遲抖動。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Dropbox：Python 2 轉 Python 3&lt;/td>
 &lt;td>語言/runtime 生命週期&lt;/td>
 &lt;td>Python 2 EOL 與型別工具鏈演進壓力，驅動全面升級並降低長期維護風險。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Dropbox：內部 RPC 轉向 gRPC（Courier）&lt;/td>
 &lt;td>工具/協定標準化&lt;/td>
 &lt;td>多語言服務擴張後，需要統一傳輸契約、提高跨團隊可維護性與可觀測性。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GitLab：單一資料庫拆成 Main/CI 資料庫&lt;/td>
 &lt;td>資料層架構&lt;/td>
 &lt;td>單庫承載產品與 CI 工作負載，容量與干擾風險上升，需以職責拆分換取穩定性。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Notion：Postgres 單庫轉分片&lt;/td>
 &lt;td>資料層架構&lt;/td>
 &lt;td>寫入與資料量成長造成熱點與容量壓力，以分片提升可擴展性與故障隔離。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Shopify：Rails 後端引入 Vitess 水平擴充&lt;/td>
 &lt;td>資料層工具&lt;/td>
 &lt;td>MySQL 垂直擴充成本上升，需在不中斷服務前提下取得分片與路由能力。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Shopify：Ruby 導入 Sorbet 靜態型別&lt;/td>
 &lt;td>工具/語言治理&lt;/td>
 &lt;td>大型程式碼庫重構與跨團隊協作風險高，需要型別訊號降低變更不確定性。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Figma：服務遷移至 Kubernetes&lt;/td>
 &lt;td>平台/部署工具&lt;/td>
 &lt;td>手工或半自動部署流程難以支撐規模成長，需要統一調度、回滾與資源治理能力。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cloudflare：邊緣系統由 C/NGINX 模組逐步改寫 Rust&lt;/td>
 &lt;td>語言/安全性&lt;/td>
 &lt;td>記憶體安全與可維護性需求提升，在高效能路徑引入 Rust 降低記憶體錯誤風險。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Slack：關鍵服務從單體拓撲遷移到 Cell-based 架構&lt;/td>
 &lt;td>架構/隔離策略&lt;/td>
 &lt;td>以降低爆炸半徑與提高冗餘為目標，將重大故障影響限制在局部 cell。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Uber：大規模微服務治理轉向 Domain-oriented 邊界重整&lt;/td>
 &lt;td>架構/組織對齊&lt;/td>
 &lt;td>服務數量擴張後依賴複雜度暴增，需要把技術邊界與業務邊界對齊以降低協作與故障傳染成本。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Meta：MySQL 大規模場景導入 MyRocks&lt;/td>
 &lt;td>儲存引擎/成本優化&lt;/td>
 &lt;td>寫入放大與儲存成本壓力上升，透過新儲存引擎換取空間效率與寫入效能。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="案例分組判讀">案例分組判讀&lt;/h2>
&lt;h3 id="語言與型別系統轉換">語言與型別系統轉換&lt;/h3>
&lt;p>語言轉換常見於「延遲抖動不可接受」或「重構風險不可接受」兩類壓力。前者多是 runtime/記憶體模型問題，後者多是大型程式碼庫可維護性問題。&lt;/p>
&lt;ul>
&lt;li>代表案例：Slack PHP -&amp;gt; Hack、Discord Go -&amp;gt; Rust、Dropbox Python 2 -&amp;gt; Python 3、Cloudflare C/NGINX -&amp;gt; Rust&lt;/li>
&lt;li>主要動機：降低 tail latency、提升記憶體安全、對抗 runtime EOL、引入更強型別訊號&lt;/li>
&lt;/ul>
&lt;h3 id="資料層與儲存架構轉換">資料層與儲存架構轉換&lt;/h3>
&lt;p>資料層轉換通常源自單體資料庫在容量、隔離與可恢復性上出現結構性瓶頸，追新技術本身很少是真正驅動力。&lt;/p>
&lt;ul>
&lt;li>代表案例：GitLab Main/CI split、Notion Postgres sharding、Shopify Vitess、Meta MyRocks&lt;/li>
&lt;li>主要動機：解耦不同負載、降低熱點、取得水平擴充、降低儲存成本&lt;/li>
&lt;/ul>
&lt;h3 id="平台與部署工具轉換">平台與部署工具轉換&lt;/h3>
&lt;p>平台轉換通常發生在部署頻率提升後，原本的人工作業或弱自動化無法承擔發布風險。&lt;/p>
&lt;ul>
&lt;li>代表案例：Figma 遷移 Kubernetes、Dropbox RPC 標準化到 gRPC&lt;/li>
&lt;li>主要動機：統一部署控制面、縮短發布/回滾時間、提升跨語言協作效率&lt;/li>
&lt;/ul>
&lt;h3 id="架構邊界重整">架構邊界重整&lt;/h3>
&lt;p>架構重整通常是「故障會跨邊界放大」或「團隊邊界與系統邊界失配」時的修正動作。&lt;/p>
&lt;ul>
&lt;li>代表案例：Slack cellular architecture、Uber domain-oriented microservice governance&lt;/li>
&lt;li>主要動機：縮小 blast radius、讓服務責任與組織責任對齊、降低跨團隊耦合&lt;/li>
&lt;/ul>
&lt;h2 id="三倍擴充案例池42">三倍擴充案例池（42）&lt;/h2>
&lt;p>這份案例池的核心責任是提供「可直接回寫實作」的案例母體，而不是只做公司清單。下面分成兩層：外部官方遷移案例（偏選型與轉換動機）與站內已整理案例（偏實作、驗證、事故教訓）。&lt;/p>
&lt;h3 id="a-外部官方遷移案例20">A. 外部官方遷移案例（20）&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>案例&lt;/th>
 &lt;th>轉換主題&lt;/th>
 &lt;th>實作討論入口&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Slack PHP -&amp;gt; Hack&lt;/td>
 &lt;td>漸進型別化與大型重構安全&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Discord Go -&amp;gt; Rust&lt;/td>
 &lt;td>延遲長尾與 GC 抖動治理&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Dropbox Python 2 -&amp;gt; 3&lt;/td>
 &lt;td>runtime EOL 與生態升級&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Dropbox RPC -&amp;gt; gRPC&lt;/td>
 &lt;td>協定標準化與跨語言維運&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GitLab Main/CI DB split&lt;/td>
 &lt;td>單庫拆分與負載隔離&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Notion Postgres sharding&lt;/td>
 &lt;td>熱點與容量壓力分片&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Shopify MySQL -&amp;gt; Vitess&lt;/td>
 &lt;td>水平擴充與線上遷移&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Shopify Ruby + Sorbet&lt;/td>
 &lt;td>動態語言型別治理&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/contract-testing/" data-link-title="6.10 Contract Testing 與 Schema 演進" data-link-desc="把跨服務 / API / event schema 的隱性期待變成可驗證契約，控制演進相容性">6.10&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Figma -&amp;gt; Kubernetes&lt;/td>
 &lt;td>部署控制面平台化&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cloudflare C/NGINX -&amp;gt; Rust&lt;/td>
 &lt;td>記憶體安全與效能路徑重寫&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Slack monolith topology -&amp;gt; cellular&lt;/td>
 &lt;td>blast radius 局部化&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Uber domain-oriented microservices&lt;/td>
 &lt;td>服務邊界與組織對齊&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Meta MySQL -&amp;gt; MyRocks&lt;/td>
 &lt;td>儲存成本與寫入效率&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Pinterest HBase -&amp;gt; TiDB&lt;/td>
 &lt;td>零停機儲存遷移&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Pinterest 新 wide-column DB（RocksDB）&lt;/td>
 &lt;td>資料層能力換血&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Meta MySQL Raft deploy&lt;/td>
 &lt;td>failover 工具化&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/dr-rollback-rehearsal/" data-link-title="6.7 DR 演練與 Rollback Rehearsal" data-link-desc="把回復路徑從紙面計畫變成定期可重播、可量測的驗證流程">6.7&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Shopify MySQL upgrade program&lt;/td>
 &lt;td>大規模升級治理&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>GitLab major PostgreSQL upgrade&lt;/td>
 &lt;td>主版本升級與回退窗&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>AWS shuffle sharding adoption&lt;/td>
 &lt;td>多租戶隔離重整&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/dependency-reliability-budget/" data-link-title="6.14 Dependency Reliability Budget" data-link-desc="把內外依賴的可靠性納入 SLO 計算與設計約束">6.14&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cloudflare observability stack內建化&lt;/td>
 &lt;td>觀測平台內生化&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/observability-operating-model/" data-link-title="4.18 Observability Operating Model" data-link-desc="定義 platform / service team / on-call 對訊號、dashboard、alert 與成本的 ownership">4.18&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="b-站內可回寫實作案例池22">B. 站內可回寫實作案例池（22）&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>案例&lt;/th>
 &lt;th>轉換主題&lt;/th>
 &lt;th>實作討論入口&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/cases/stripe/idempotency-and-zero-downtime-migration/" data-link-title="Stripe：Idempotency 與零停機遷移的交易安全設計" data-link-desc="把 API 重試與資料遷移放在同一套安全模型，維持支付交易的一致結果。">Stripe：Idempotency 與零停機遷移&lt;/a>&lt;/td>
 &lt;td>交易安全 + migration 並行&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/cases/pinterest/cache-reliability-and-capacity-surprises/" data-link-title="Pinterest：快取可靠性與容量驚奇治理" data-link-desc="針對快取層失效與流量突增，建立容量緩衝、退化路徑與重建節奏。">Pinterest：快取可靠性與容量驚奇治理&lt;/a>&lt;/td>
 &lt;td>快取策略與容量重整&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/capacity-cost/" data-link-title="6.9 容量與成本邊界" data-link-desc="把容量規劃跟成本約束變成驗證輸入">6.9&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/cases/amazon/shuffle-sharding-and-cell-boundary/" data-link-title="Amazon：Shuffle Sharding 與 Cell 邊界的失效局部化" data-link-desc="用 cell 與 shuffle sharding 將多租戶故障限制在局部，讓恢復策略可分批執行。">Amazon：Shuffle Sharding 與 Cell 邊界&lt;/a>&lt;/td>
 &lt;td>cell/shard 重整&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/cases/meta/region-failover-and-reliability-boundaries/" data-link-title="Meta：Region Failover 與可靠性邊界" data-link-desc="把跨區故障視為邊界治理問題，透過分區隔離與回復順序控制失效擴散。">Meta：Region Failover 與可靠性邊界&lt;/a>&lt;/td>
 &lt;td>區域切換能力演進&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/dr-rollback-rehearsal/" data-link-title="6.7 DR 演練與 Rollback Rehearsal" data-link-desc="把回復路徑從紙面計畫變成定期可重播、可量測的驗證流程">6.7&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/cases/shopify/bfcm-capacity-and-game-day/" data-link-title="Shopify：BFCM 容量治理與 Game Day 驗證節奏" data-link-desc="把季節性流量峰值轉成年度可靠性流程，透過容量模型、演練與隔離策略提前吸收風險。">Shopify：BFCM 容量治理與 Game Day&lt;/a>&lt;/td>
 &lt;td>高峰前治理轉換&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/load-testing/" data-link-title="6.2 load test" data-link-desc="把 production 流量結構轉成可重播壓力情境，定位 saturation 轉折與容量邊界">6.6&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/cases/google/error-budget-policy-and-release-gating/" data-link-title="Google：Error Budget 政策如何決定發布節奏" data-link-desc="把 SLO 消耗量轉成 release gate，讓可靠性與交付速度共用同一套決策語言。">Google：Error Budget 發布門檻&lt;/a>&lt;/td>
 &lt;td>從速度導向轉為預算導向&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/slo-error-budget/" data-link-title="6.6 SLO 與 Error Budget 政策" data-link-desc="把可靠性目標轉成可驗證量測與凍結條件">6.2&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/cases/microsoft/change-management-and-reliability-governance/" data-link-title="Microsoft：變更治理與可靠性門檻" data-link-desc="透過分層變更管理與發布閘門，降低大型 SaaS 平台的系統性回歸風險。">Microsoft：變更治理與可靠性門檻&lt;/a>&lt;/td>
 &lt;td>變更流程平台化&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/cases/spotify/platform-engineering-and-reliability-contracts/" data-link-title="Spotify：平台工程與可靠性契約" data-link-desc="用平台契約統一服務團隊的可靠性最低標準，降低跨團隊變更造成的隱性風險。">Spotify：平台工程與可靠性契約&lt;/a>&lt;/td>
 &lt;td>團隊自助平台化&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/cases/linkedin/capacity-headroom-and-oncall-tiering/" data-link-title="LinkedIn：Capacity Headroom 與 On-call 分層" data-link-desc="把容量預測與值班分層綁在一起，降低高峰時段的升級混亂與恢復延遲。">LinkedIn：Capacity Headroom 與 On-call 分層&lt;/a>&lt;/td>
 &lt;td>容量與值班模型重整&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/capacity-cost/" data-link-title="6.9 容量與成本邊界" data-link-desc="把容量規劃跟成本約束變成驗證輸入">6.9&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/cases/netflix/steady-state-chaos-and-fit/" data-link-title="Netflix：Steady State、Chaos 與 FIT 的驗證路徑" data-link-desc="把故障注入從工具操作升級成可驗證流程：先定義穩態，再設計注入與回復條件。">Netflix：Steady State、Chaos 與 FIT&lt;/a>&lt;/td>
 &lt;td>驗證方法轉換&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/chaos-testing/" data-link-title="6.4 chaos testing" data-link-desc="把故障注入從工具操作升級成可驗證流程：先定義穩態，再按依賴類型設計注入、控制 blast radius 與收集證據">6.5&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/cases/honeycomb/burn-rate-driven-reliability-operations/" data-link-title="Honeycomb：以 Burn Rate 驅動的可靠性操作" data-link-desc="把 SLO burn rate 直接連到值班決策與改善優先序，降低高噪音告警造成的判讀失真。">Honeycomb：Burn Rate 驅動操作&lt;/a>&lt;/td>
 &lt;td>告警治理轉換&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/sli-slo-signal/" data-link-title="4.6 SLI 量測與 SLO 訊號設計" data-link-desc="把可靠性目標的訊號從 metric 端設計好、餵給 6.6 SLO 政策">4.13&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/github/2018-oct21-mysql-topology-incident/" data-link-title="GitHub 2018 Oct21 MySQL Topology Incident" data-link-desc="2018-10-21 GitHub 因 network partition 觸發跨區資料庫拓撲異常的事故解析：資料一致性優先、fail-forward 決策與長時間恢復。">GitHub 2018 MySQL Topology Incident&lt;/a>&lt;/td>
 &lt;td>跨區 DB 拓撲決策轉換&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/reddit/2023-kubernetes-upgrade-incident/" data-link-title="Reddit：2023 Kubernetes 升級事故" data-link-desc="平台升級變更如何觸發服務退化，以及如何設計可回退的升級策略。">Reddit 2023 Kubernetes 升級事故&lt;/a>&lt;/td>
 &lt;td>平台升級失敗模式&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/discord/2022-gateway-capacity-event/" data-link-title="Discord：Gateway 容量事件與恢復節奏" data-link-desc="長連線平台在容量邊界被擊穿時，如何控制擴散並分批恢復。">Discord 2022 Gateway 容量事件&lt;/a>&lt;/td>
 &lt;td>容量與連線模型調整&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/cloudflare/2019-regex-cpu-outage/" data-link-title="Cloudflare 2019 Regex CPU Outage" data-link-desc="2019-07-02 Cloudflare WAF 規則更新導致全球 CPU 飆升的事故解析：觸發條件、擴散機制、止血決策與可回寫控制面。">Cloudflare 2019 Regex CPU Outage&lt;/a>&lt;/td>
 &lt;td>規則系統推送模型調整&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/incident-workflow-automation-boundary/" data-link-title="8.21 Incident Workflow Automation Boundary" data-link-desc="定義哪些事故流程適合自動化，哪些決策需要保留人工確認">8.13&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/cloudflare/2023-control-plane-token-incident/" data-link-title="Cloudflare 2023 Control Plane Token Incident" data-link-desc="2023-01-24 Cloudflare service token 錯誤變更導致多產品連鎖影響的事故解析：信任邊界、擴散機制、止血策略與流程回寫。">Cloudflare 2023 Control Plane Token Incident&lt;/a>&lt;/td>
 &lt;td>控制面信任邊界重整&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/security-control-handoff-to-delivery-and-incident/" data-link-title="7.18 資安控制面如何交接到部署與事故流程" data-link-desc="建立資安控制面交接到部署、可靠性與事故流程的大綱">7.12&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/fastly/2021-june-global-edge-config-triggered-outage/" data-link-title="Fastly 2021 June Global Edge Config-triggered Outage" data-link-desc="2021-06-08 Fastly 全球 edge 事故解析：有效客戶配置觸發潛藏 bug、分鐘級擴散與快速隔離恢復。">Fastly 2021 全域 Edge 配置事故&lt;/a>&lt;/td>
 &lt;td>配置發布流程轉換&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/aws-s3/2017-us-east-1-service-disruption/" data-link-title="AWS S3 2017 US-EAST-1 Service Disruption" data-link-desc="2017-02-28 AWS S3 us-east-1 事故解析：內部操作命令、index / placement 子系統重啟、區域依賴擴散與狀態頁依賴回寫。">AWS S3 2017 US-EAST-1 事件&lt;/a>&lt;/td>
 &lt;td>控制面操作模型重整&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/containment-recovery-strategy/" data-link-title="8.3 止血、降級與回復策略" data-link-desc="把短期止血與正式回復拆成可執行步驟">8.3&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/atlassian/2022-april-multi-tenant-deletion-outage/" data-link-title="Atlassian 2022 April Multi-tenant Deletion Outage" data-link-desc="2022-04 Atlassian 因維運腳本誤刪多租戶站點造成長時間事故的解析：恢復分批、跨團隊指揮與對外通訊節奏。">Atlassian 2022 多租戶刪除事故&lt;/a>&lt;/td>
 &lt;td>tenant 安全邊界重整&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/azure-ad/2021-identity-control-plane-disruption/" data-link-title="Azure AD：2021 身分控制面中斷事件" data-link-desc="身分服務失效時，如何評估跨產品影響與收斂優先序。">Azure AD 2021 身分控制面事件&lt;/a>&lt;/td>
 &lt;td>身分服務依賴治理&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/customer-impact-assessment/" data-link-title="8.20 Customer Impact Assessment" data-link-desc="把受影響用戶、功能、區域、金額、SLO 與補償判斷串成影響評估模型">8.20&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/gcp/2019-us-network-congestion-multi-service-incident/" data-link-title="GCP 2019 US Network Congestion Multi-service Incident" data-link-desc="2019-06-02 Google Cloud 因美國區域網路壅塞造成多服務退化的事故解析：跨產品依賴、流量控制與區域隔離判讀。">GCP 2019 多服務網路擁塞事件&lt;/a>&lt;/td>
 &lt;td>區域網路依賴重整&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/dependency-reliability-budget/" data-link-title="6.14 Dependency Reliability Budget" data-link-desc="把內外依賴的可靠性納入 SLO 計算與設計約束">6.14&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/cases/heroku/2021-routing-control-event/" data-link-title="Heroku：Routing 控制事件與多租戶影響" data-link-desc="PaaS 路由層異常時，如何限制租戶擴散並維持可用通訊。">Heroku 2021 Routing 控制事件&lt;/a>&lt;/td>
 &lt;td>路由控制面恢復策略&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/containment-recovery-strategy/" data-link-title="8.3 止血、降級與回復策略" data-link-desc="把短期止血與正式回復拆成可執行步驟">8.3&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這兩層合計 42 個案例。使用方式是先在 A 層找轉換動機，再到 B 層找可操作證據與失敗模式，最後回寫到 &lt;code>01/04/06/08&lt;/code> 的正文。&lt;/p></description><content:encoded><![CDATA[<p>這個案例的核心責任是把「營運後轉換」變成可判讀決策，而不是技術潮流追逐。服務在成長期常會遇到早期選型與現況負載不再匹配，此時轉換的重點是風險收斂與效率改善，而不是語言偏好。</p>
<h2 id="大量真實案例與轉換原因">大量真實案例與轉換原因</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>轉換類型</th>
          <th>為什麼轉換</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Slack：PHP 逐步遷移到 Hack</td>
          <td>語言/型別系統</td>
          <td>以漸進式靜態型別提升重構安全與開發效率，降低 runtime 才暴露型別錯誤的成本。</td>
      </tr>
      <tr>
          <td>Discord：Read States 服務 Go 重寫為 Rust</td>
          <td>語言/執行模型</td>
          <td>Go 服務在特定負載下出現 GC 造成的週期性延遲尖峰，Rust 以無 GC 記憶體模型降低延遲抖動。</td>
      </tr>
      <tr>
          <td>Dropbox：Python 2 轉 Python 3</td>
          <td>語言/runtime 生命週期</td>
          <td>Python 2 EOL 與型別工具鏈演進壓力，驅動全面升級並降低長期維護風險。</td>
      </tr>
      <tr>
          <td>Dropbox：內部 RPC 轉向 gRPC（Courier）</td>
          <td>工具/協定標準化</td>
          <td>多語言服務擴張後，需要統一傳輸契約、提高跨團隊可維護性與可觀測性。</td>
      </tr>
      <tr>
          <td>GitLab：單一資料庫拆成 Main/CI 資料庫</td>
          <td>資料層架構</td>
          <td>單庫承載產品與 CI 工作負載，容量與干擾風險上升，需以職責拆分換取穩定性。</td>
      </tr>
      <tr>
          <td>Notion：Postgres 單庫轉分片</td>
          <td>資料層架構</td>
          <td>寫入與資料量成長造成熱點與容量壓力，以分片提升可擴展性與故障隔離。</td>
      </tr>
      <tr>
          <td>Shopify：Rails 後端引入 Vitess 水平擴充</td>
          <td>資料層工具</td>
          <td>MySQL 垂直擴充成本上升，需在不中斷服務前提下取得分片與路由能力。</td>
      </tr>
      <tr>
          <td>Shopify：Ruby 導入 Sorbet 靜態型別</td>
          <td>工具/語言治理</td>
          <td>大型程式碼庫重構與跨團隊協作風險高，需要型別訊號降低變更不確定性。</td>
      </tr>
      <tr>
          <td>Figma：服務遷移至 Kubernetes</td>
          <td>平台/部署工具</td>
          <td>手工或半自動部署流程難以支撐規模成長，需要統一調度、回滾與資源治理能力。</td>
      </tr>
      <tr>
          <td>Cloudflare：邊緣系統由 C/NGINX 模組逐步改寫 Rust</td>
          <td>語言/安全性</td>
          <td>記憶體安全與可維護性需求提升，在高效能路徑引入 Rust 降低記憶體錯誤風險。</td>
      </tr>
      <tr>
          <td>Slack：關鍵服務從單體拓撲遷移到 Cell-based 架構</td>
          <td>架構/隔離策略</td>
          <td>以降低爆炸半徑與提高冗餘為目標，將重大故障影響限制在局部 cell。</td>
      </tr>
      <tr>
          <td>Uber：大規模微服務治理轉向 Domain-oriented 邊界重整</td>
          <td>架構/組織對齊</td>
          <td>服務數量擴張後依賴複雜度暴增，需要把技術邊界與業務邊界對齊以降低協作與故障傳染成本。</td>
      </tr>
      <tr>
          <td>Meta：MySQL 大規模場景導入 MyRocks</td>
          <td>儲存引擎/成本優化</td>
          <td>寫入放大與儲存成本壓力上升，透過新儲存引擎換取空間效率與寫入效能。</td>
      </tr>
  </tbody>
</table>
<h2 id="案例分組判讀">案例分組判讀</h2>
<h3 id="語言與型別系統轉換">語言與型別系統轉換</h3>
<p>語言轉換常見於「延遲抖動不可接受」或「重構風險不可接受」兩類壓力。前者多是 runtime/記憶體模型問題，後者多是大型程式碼庫可維護性問題。</p>
<ul>
<li>代表案例：Slack PHP -&gt; Hack、Discord Go -&gt; Rust、Dropbox Python 2 -&gt; Python 3、Cloudflare C/NGINX -&gt; Rust</li>
<li>主要動機：降低 tail latency、提升記憶體安全、對抗 runtime EOL、引入更強型別訊號</li>
</ul>
<h3 id="資料層與儲存架構轉換">資料層與儲存架構轉換</h3>
<p>資料層轉換通常源自單體資料庫在容量、隔離與可恢復性上出現結構性瓶頸，追新技術本身很少是真正驅動力。</p>
<ul>
<li>代表案例：GitLab Main/CI split、Notion Postgres sharding、Shopify Vitess、Meta MyRocks</li>
<li>主要動機：解耦不同負載、降低熱點、取得水平擴充、降低儲存成本</li>
</ul>
<h3 id="平台與部署工具轉換">平台與部署工具轉換</h3>
<p>平台轉換通常發生在部署頻率提升後，原本的人工作業或弱自動化無法承擔發布風險。</p>
<ul>
<li>代表案例：Figma 遷移 Kubernetes、Dropbox RPC 標準化到 gRPC</li>
<li>主要動機：統一部署控制面、縮短發布/回滾時間、提升跨語言協作效率</li>
</ul>
<h3 id="架構邊界重整">架構邊界重整</h3>
<p>架構重整通常是「故障會跨邊界放大」或「團隊邊界與系統邊界失配」時的修正動作。</p>
<ul>
<li>代表案例：Slack cellular architecture、Uber domain-oriented microservice governance</li>
<li>主要動機：縮小 blast radius、讓服務責任與組織責任對齊、降低跨團隊耦合</li>
</ul>
<h2 id="三倍擴充案例池42">三倍擴充案例池（42）</h2>
<p>這份案例池的核心責任是提供「可直接回寫實作」的案例母體，而不是只做公司清單。下面分成兩層：外部官方遷移案例（偏選型與轉換動機）與站內已整理案例（偏實作、驗證、事故教訓）。</p>
<h3 id="a-外部官方遷移案例20">A. 外部官方遷移案例（20）</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>轉換主題</th>
          <th>實作討論入口</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Slack PHP -&gt; Hack</td>
          <td>漸進型別化與大型重構安全</td>
          <td><a href="/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6</a></td>
      </tr>
      <tr>
          <td>Discord Go -&gt; Rust</td>
          <td>延遲長尾與 GC 抖動治理</td>
          <td><a href="/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11</a></td>
      </tr>
      <tr>
          <td>Dropbox Python 2 -&gt; 3</td>
          <td>runtime EOL 與生態升級</td>
          <td><a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8</a></td>
      </tr>
      <tr>
          <td>Dropbox RPC -&gt; gRPC</td>
          <td>協定標準化與跨語言維運</td>
          <td><a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4</a></td>
      </tr>
      <tr>
          <td>GitLab Main/CI DB split</td>
          <td>單庫拆分與負載隔離</td>
          <td><a href="/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6</a></td>
      </tr>
      <tr>
          <td>Notion Postgres sharding</td>
          <td>熱點與容量壓力分片</td>
          <td><a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a></td>
      </tr>
      <tr>
          <td>Shopify MySQL -&gt; Vitess</td>
          <td>水平擴充與線上遷移</td>
          <td><a href="/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6</a></td>
      </tr>
      <tr>
          <td>Shopify Ruby + Sorbet</td>
          <td>動態語言型別治理</td>
          <td><a href="/blog/backend/06-reliability/contract-testing/" data-link-title="6.10 Contract Testing 與 Schema 演進" data-link-desc="把跨服務 / API / event schema 的隱性期待變成可驗證契約，控制演進相容性">6.10</a></td>
      </tr>
      <tr>
          <td>Figma -&gt; Kubernetes</td>
          <td>部署控制面平台化</td>
          <td><a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4</a></td>
      </tr>
      <tr>
          <td>Cloudflare C/NGINX -&gt; Rust</td>
          <td>記憶體安全與效能路徑重寫</td>
          <td><a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
      </tr>
      <tr>
          <td>Slack monolith topology -&gt; cellular</td>
          <td>blast radius 局部化</td>
          <td><a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a></td>
      </tr>
      <tr>
          <td>Uber domain-oriented microservices</td>
          <td>服務邊界與組織對齊</td>
          <td><a href="/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1</a></td>
      </tr>
      <tr>
          <td>Meta MySQL -&gt; MyRocks</td>
          <td>儲存成本與寫入效率</td>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a></td>
      </tr>
      <tr>
          <td>Pinterest HBase -&gt; TiDB</td>
          <td>零停機儲存遷移</td>
          <td><a href="/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11</a></td>
      </tr>
      <tr>
          <td>Pinterest 新 wide-column DB（RocksDB）</td>
          <td>資料層能力換血</td>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a></td>
      </tr>
      <tr>
          <td>Meta MySQL Raft deploy</td>
          <td>failover 工具化</td>
          <td><a href="/blog/backend/06-reliability/dr-rollback-rehearsal/" data-link-title="6.7 DR 演練與 Rollback Rehearsal" data-link-desc="把回復路徑從紙面計畫變成定期可重播、可量測的驗證流程">6.7</a></td>
      </tr>
      <tr>
          <td>Shopify MySQL upgrade program</td>
          <td>大規模升級治理</td>
          <td><a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8</a></td>
      </tr>
      <tr>
          <td>GitLab major PostgreSQL upgrade</td>
          <td>主版本升級與回退窗</td>
          <td><a href="/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11</a></td>
      </tr>
      <tr>
          <td>AWS shuffle sharding adoption</td>
          <td>多租戶隔離重整</td>
          <td><a href="/blog/backend/06-reliability/dependency-reliability-budget/" data-link-title="6.14 Dependency Reliability Budget" data-link-desc="把內外依賴的可靠性納入 SLO 計算與設計約束">6.14</a></td>
      </tr>
      <tr>
          <td>Cloudflare observability stack內建化</td>
          <td>觀測平台內生化</td>
          <td><a href="/blog/backend/04-observability/observability-operating-model/" data-link-title="4.18 Observability Operating Model" data-link-desc="定義 platform / service team / on-call 對訊號、dashboard、alert 與成本的 ownership">4.18</a></td>
      </tr>
  </tbody>
</table>
<h3 id="b-站內可回寫實作案例池22">B. 站內可回寫實作案例池（22）</h3>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>轉換主題</th>
          <th>實作討論入口</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/stripe/idempotency-and-zero-downtime-migration/" data-link-title="Stripe：Idempotency 與零停機遷移的交易安全設計" data-link-desc="把 API 重試與資料遷移放在同一套安全模型，維持支付交易的一致結果。">Stripe：Idempotency 與零停機遷移</a></td>
          <td>交易安全 + migration 並行</td>
          <td><a href="/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/pinterest/cache-reliability-and-capacity-surprises/" data-link-title="Pinterest：快取可靠性與容量驚奇治理" data-link-desc="針對快取層失效與流量突增，建立容量緩衝、退化路徑與重建節奏。">Pinterest：快取可靠性與容量驚奇治理</a></td>
          <td>快取策略與容量重整</td>
          <td><a href="/blog/backend/06-reliability/capacity-cost/" data-link-title="6.9 容量與成本邊界" data-link-desc="把容量規劃跟成本約束變成驗證輸入">6.9</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/amazon/shuffle-sharding-and-cell-boundary/" data-link-title="Amazon：Shuffle Sharding 與 Cell 邊界的失效局部化" data-link-desc="用 cell 與 shuffle sharding 將多租戶故障限制在局部，讓恢復策略可分批執行。">Amazon：Shuffle Sharding 與 Cell 邊界</a></td>
          <td>cell/shard 重整</td>
          <td><a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/meta/region-failover-and-reliability-boundaries/" data-link-title="Meta：Region Failover 與可靠性邊界" data-link-desc="把跨區故障視為邊界治理問題，透過分區隔離與回復順序控制失效擴散。">Meta：Region Failover 與可靠性邊界</a></td>
          <td>區域切換能力演進</td>
          <td><a href="/blog/backend/06-reliability/dr-rollback-rehearsal/" data-link-title="6.7 DR 演練與 Rollback Rehearsal" data-link-desc="把回復路徑從紙面計畫變成定期可重播、可量測的驗證流程">6.7</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/shopify/bfcm-capacity-and-game-day/" data-link-title="Shopify：BFCM 容量治理與 Game Day 驗證節奏" data-link-desc="把季節性流量峰值轉成年度可靠性流程，透過容量模型、演練與隔離策略提前吸收風險。">Shopify：BFCM 容量治理與 Game Day</a></td>
          <td>高峰前治理轉換</td>
          <td><a href="/blog/backend/06-reliability/load-testing/" data-link-title="6.2 load test" data-link-desc="把 production 流量結構轉成可重播壓力情境，定位 saturation 轉折與容量邊界">6.6</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/google/error-budget-policy-and-release-gating/" data-link-title="Google：Error Budget 政策如何決定發布節奏" data-link-desc="把 SLO 消耗量轉成 release gate，讓可靠性與交付速度共用同一套決策語言。">Google：Error Budget 發布門檻</a></td>
          <td>從速度導向轉為預算導向</td>
          <td><a href="/blog/backend/06-reliability/slo-error-budget/" data-link-title="6.6 SLO 與 Error Budget 政策" data-link-desc="把可靠性目標轉成可驗證量測與凍結條件">6.2</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/microsoft/change-management-and-reliability-governance/" data-link-title="Microsoft：變更治理與可靠性門檻" data-link-desc="透過分層變更管理與發布閘門，降低大型 SaaS 平台的系統性回歸風險。">Microsoft：變更治理與可靠性門檻</a></td>
          <td>變更流程平台化</td>
          <td><a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/spotify/platform-engineering-and-reliability-contracts/" data-link-title="Spotify：平台工程與可靠性契約" data-link-desc="用平台契約統一服務團隊的可靠性最低標準，降低跨團隊變更造成的隱性風險。">Spotify：平台工程與可靠性契約</a></td>
          <td>團隊自助平台化</td>
          <td><a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/linkedin/capacity-headroom-and-oncall-tiering/" data-link-title="LinkedIn：Capacity Headroom 與 On-call 分層" data-link-desc="把容量預測與值班分層綁在一起，降低高峰時段的升級混亂與恢復延遲。">LinkedIn：Capacity Headroom 與 On-call 分層</a></td>
          <td>容量與值班模型重整</td>
          <td><a href="/blog/backend/06-reliability/capacity-cost/" data-link-title="6.9 容量與成本邊界" data-link-desc="把容量規劃跟成本約束變成驗證輸入">6.9</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/netflix/steady-state-chaos-and-fit/" data-link-title="Netflix：Steady State、Chaos 與 FIT 的驗證路徑" data-link-desc="把故障注入從工具操作升級成可驗證流程：先定義穩態，再設計注入與回復條件。">Netflix：Steady State、Chaos 與 FIT</a></td>
          <td>驗證方法轉換</td>
          <td><a href="/blog/backend/06-reliability/chaos-testing/" data-link-title="6.4 chaos testing" data-link-desc="把故障注入從工具操作升級成可驗證流程：先定義穩態，再按依賴類型設計注入、控制 blast radius 與收集證據">6.5</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/06-reliability/cases/honeycomb/burn-rate-driven-reliability-operations/" data-link-title="Honeycomb：以 Burn Rate 驅動的可靠性操作" data-link-desc="把 SLO burn rate 直接連到值班決策與改善優先序，降低高噪音告警造成的判讀失真。">Honeycomb：Burn Rate 驅動操作</a></td>
          <td>告警治理轉換</td>
          <td><a href="/blog/backend/04-observability/sli-slo-signal/" data-link-title="4.6 SLI 量測與 SLO 訊號設計" data-link-desc="把可靠性目標的訊號從 metric 端設計好、餵給 6.6 SLO 政策">4.13</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/github/2018-oct21-mysql-topology-incident/" data-link-title="GitHub 2018 Oct21 MySQL Topology Incident" data-link-desc="2018-10-21 GitHub 因 network partition 觸發跨區資料庫拓撲異常的事故解析：資料一致性優先、fail-forward 決策與長時間恢復。">GitHub 2018 MySQL Topology Incident</a></td>
          <td>跨區 DB 拓撲決策轉換</td>
          <td><a href="/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/reddit/2023-kubernetes-upgrade-incident/" data-link-title="Reddit：2023 Kubernetes 升級事故" data-link-desc="平台升級變更如何觸發服務退化，以及如何設計可回退的升級策略。">Reddit 2023 Kubernetes 升級事故</a></td>
          <td>平台升級失敗模式</td>
          <td><a href="/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/discord/2022-gateway-capacity-event/" data-link-title="Discord：Gateway 容量事件與恢復節奏" data-link-desc="長連線平台在容量邊界被擊穿時，如何控制擴散並分批恢復。">Discord 2022 Gateway 容量事件</a></td>
          <td>容量與連線模型調整</td>
          <td><a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/cloudflare/2019-regex-cpu-outage/" data-link-title="Cloudflare 2019 Regex CPU Outage" data-link-desc="2019-07-02 Cloudflare WAF 規則更新導致全球 CPU 飆升的事故解析：觸發條件、擴散機制、止血決策與可回寫控制面。">Cloudflare 2019 Regex CPU Outage</a></td>
          <td>規則系統推送模型調整</td>
          <td><a href="/blog/backend/08-incident-response/incident-workflow-automation-boundary/" data-link-title="8.21 Incident Workflow Automation Boundary" data-link-desc="定義哪些事故流程適合自動化，哪些決策需要保留人工確認">8.13</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/cloudflare/2023-control-plane-token-incident/" data-link-title="Cloudflare 2023 Control Plane Token Incident" data-link-desc="2023-01-24 Cloudflare service token 錯誤變更導致多產品連鎖影響的事故解析：信任邊界、擴散機制、止血策略與流程回寫。">Cloudflare 2023 Control Plane Token Incident</a></td>
          <td>控制面信任邊界重整</td>
          <td><a href="/blog/backend/07-security-data-protection/security-control-handoff-to-delivery-and-incident/" data-link-title="7.18 資安控制面如何交接到部署與事故流程" data-link-desc="建立資安控制面交接到部署、可靠性與事故流程的大綱">7.12</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/fastly/2021-june-global-edge-config-triggered-outage/" data-link-title="Fastly 2021 June Global Edge Config-triggered Outage" data-link-desc="2021-06-08 Fastly 全球 edge 事故解析：有效客戶配置觸發潛藏 bug、分鐘級擴散與快速隔離恢復。">Fastly 2021 全域 Edge 配置事故</a></td>
          <td>配置發布流程轉換</td>
          <td><a href="/blog/backend/06-reliability/release-gate/" data-link-title="6.8 Release Gate 與變更節奏" data-link-desc="把驗證、migration、相容性納入放行判準">6.8</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/aws-s3/2017-us-east-1-service-disruption/" data-link-title="AWS S3 2017 US-EAST-1 Service Disruption" data-link-desc="2017-02-28 AWS S3 us-east-1 事故解析：內部操作命令、index / placement 子系統重啟、區域依賴擴散與狀態頁依賴回寫。">AWS S3 2017 US-EAST-1 事件</a></td>
          <td>控制面操作模型重整</td>
          <td><a href="/blog/backend/08-incident-response/containment-recovery-strategy/" data-link-title="8.3 止血、降級與回復策略" data-link-desc="把短期止血與正式回復拆成可執行步驟">8.3</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/atlassian/2022-april-multi-tenant-deletion-outage/" data-link-title="Atlassian 2022 April Multi-tenant Deletion Outage" data-link-desc="2022-04 Atlassian 因維運腳本誤刪多租戶站點造成長時間事故的解析：恢復分批、跨團隊指揮與對外通訊節奏。">Atlassian 2022 多租戶刪除事故</a></td>
          <td>tenant 安全邊界重整</td>
          <td><a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/azure-ad/2021-identity-control-plane-disruption/" data-link-title="Azure AD：2021 身分控制面中斷事件" data-link-desc="身分服務失效時，如何評估跨產品影響與收斂優先序。">Azure AD 2021 身分控制面事件</a></td>
          <td>身分服務依賴治理</td>
          <td><a href="/blog/backend/08-incident-response/customer-impact-assessment/" data-link-title="8.20 Customer Impact Assessment" data-link-desc="把受影響用戶、功能、區域、金額、SLO 與補償判斷串成影響評估模型">8.20</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/gcp/2019-us-network-congestion-multi-service-incident/" data-link-title="GCP 2019 US Network Congestion Multi-service Incident" data-link-desc="2019-06-02 Google Cloud 因美國區域網路壅塞造成多服務退化的事故解析：跨產品依賴、流量控制與區域隔離判讀。">GCP 2019 多服務網路擁塞事件</a></td>
          <td>區域網路依賴重整</td>
          <td><a href="/blog/backend/06-reliability/dependency-reliability-budget/" data-link-title="6.14 Dependency Reliability Budget" data-link-desc="把內外依賴的可靠性納入 SLO 計算與設計約束">6.14</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/08-incident-response/cases/heroku/2021-routing-control-event/" data-link-title="Heroku：Routing 控制事件與多租戶影響" data-link-desc="PaaS 路由層異常時，如何限制租戶擴散並維持可用通訊。">Heroku 2021 Routing 控制事件</a></td>
          <td>路由控制面恢復策略</td>
          <td><a href="/blog/backend/08-incident-response/containment-recovery-strategy/" data-link-title="8.3 止血、降級與回復策略" data-link-desc="把短期止血與正式回復拆成可執行步驟">8.3</a></td>
      </tr>
  </tbody>
</table>
<p>這兩層合計 42 個案例。使用方式是先在 A 層找轉換動機，再到 B 層找可操作證據與失敗模式，最後回寫到 <code>01/04/06/08</code> 的正文。</p>
<h2 id="跨分類覆蓋與缺口">跨分類覆蓋與缺口</h2>
<p>這一段的核心責任是避免案例池被資料庫議題主導。選型與轉換在實務上會同時涉及快取、訊息傳遞、觀測、部署、安全與事故治理，因此案例覆蓋要跨分類配置。</p>
<table>
  <thead>
      <tr>
          <th>分類</th>
          <th>目前案例密度</th>
          <th>代表案例入口</th>
          <th>目前缺口與補查方向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>01 Database / Storage</td>
          <td>高</td>
          <td><a href="/blog/backend/01-database/schema-migration-rollout-evidence/" data-link-title="1.7 Schema Migration Rollout 證據（Schema Migration Rollout Evidence）實作示範" data-link-desc="以訂單付款狀態欄位演進示範 schema migration 如何產出 evidence、release gate 與 incident decision log。">1.7 Schema Migration Rollout 證據</a></td>
          <td>已有遷移流程與 rollout evidence；下一步補更多 vendor 轉換對照</td>
      </tr>
      <tr>
          <td>02 Cache / Redis</td>
          <td>中低</td>
          <td><a href="/blog/backend/06-reliability/cases/pinterest/cache-reliability-and-capacity-surprises/" data-link-title="Pinterest：快取可靠性與容量驚奇治理" data-link-desc="針對快取層失效與流量突增，建立容量緩衝、退化路徑與重建節奏。">Pinterest：快取可靠性與容量驚奇治理</a></td>
          <td>補「快取策略轉換」案例（cache-aside -&gt; write-through、multi-layer cache）</td>
      </tr>
      <tr>
          <td>03 Message Queue</td>
          <td>中低</td>
          <td><a href="/blog/backend/06-reliability/cases/amazon/shuffle-sharding-and-cell-boundary/" data-link-title="Amazon：Shuffle Sharding 與 Cell 邊界的失效局部化" data-link-desc="用 cell 與 shuffle sharding 將多租戶故障限制在局部，讓恢復策略可分批執行。">Amazon：Shuffle Sharding 與 Cell 邊界</a></td>
          <td>補「自管 broker -&gt; managed queue」與「語義轉換（at-least-once / exactly-once）」</td>
      </tr>
      <tr>
          <td>04 Observability</td>
          <td>中</td>
          <td><a href="/blog/backend/06-reliability/cases/honeycomb/burn-rate-driven-reliability-operations/" data-link-title="Honeycomb：以 Burn Rate 驅動的可靠性操作" data-link-desc="把 SLO burn rate 直接連到值班決策與改善優先序，降低高噪音告警造成的判讀失真。">Honeycomb：Burn Rate 驅動操作</a></td>
          <td>補「監控平台遷移」與「OpenTelemetry 導入遷移」案例</td>
      </tr>
      <tr>
          <td>05 Deployment Platform</td>
          <td>中</td>
          <td><a href="/blog/backend/08-incident-response/cases/reddit/2023-kubernetes-upgrade-incident/" data-link-title="Reddit：2023 Kubernetes 升級事故" data-link-desc="平台升級變更如何觸發服務退化，以及如何設計可回退的升級策略。">Reddit：2023 Kubernetes 升級事故</a></td>
          <td>補「自建部署 -&gt; Kubernetes/GitOps」轉換案例</td>
      </tr>
      <tr>
          <td>06 Reliability</td>
          <td>高</td>
          <td><a href="/blog/backend/06-reliability/cases/stripe/idempotency-and-zero-downtime-migration/" data-link-title="Stripe：Idempotency 與零停機遷移的交易安全設計" data-link-desc="把 API 重試與資料遷移放在同一套安全模型，維持支付交易的一致結果。">Stripe：Idempotency 與零停機遷移</a></td>
          <td>持續補不同產業的 rollout/rollback 對照</td>
      </tr>
      <tr>
          <td>07 Security / Data Protection</td>
          <td>中低</td>
          <td><a href="/blog/backend/08-incident-response/cases/cloudflare/2023-control-plane-token-incident/" data-link-title="Cloudflare 2023 Control Plane Token Incident" data-link-desc="2023-01-24 Cloudflare service token 錯誤變更導致多產品連鎖影響的事故解析：信任邊界、擴散機制、止血策略與流程回寫。">Cloudflare 2023 Control Plane Token Incident</a></td>
          <td>補「憑證、金鑰、身分邊界治理轉換」案例</td>
      </tr>
      <tr>
          <td>08 Incident Response</td>
          <td>高</td>
          <td><a href="/blog/backend/08-incident-response/cases/github/2018-oct21-mysql-topology-incident/" data-link-title="GitHub 2018 Oct21 MySQL Topology Incident" data-link-desc="2018-10-21 GitHub 因 network partition 觸發跨區資料庫拓撲異常的事故解析：資料一致性優先、fail-forward 決策與長時間恢復。">GitHub 2018 MySQL Topology Incident</a></td>
          <td>補「轉換期間事故」專題，建立遷移失敗模式索引</td>
      </tr>
  </tbody>
</table>
<h2 id="覆蓋門檻與缺口追蹤">覆蓋門檻與缺口追蹤</h2>
<p>這份追蹤表的核心責任是把「案例夠不夠」變成可量化判斷，而不是主觀感覺。</p>
<table>
  <thead>
      <tr>
          <th>分類</th>
          <th>最低門檻（篇）</th>
          <th>目前已收錄（篇）</th>
          <th>缺口（篇）</th>
          <th>狀態</th>
          <th>下一步</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>01 Database / Storage</td>
          <td>12</td>
          <td>12</td>
          <td>0</td>
          <td>達標</td>
          <td>補 vendor 轉換對照深度</td>
      </tr>
      <tr>
          <td>02 Cache / Redis</td>
          <td>10</td>
          <td>10</td>
          <td>0</td>
          <td>達標</td>
          <td>進入案例深度擴寫與反例補充</td>
      </tr>
      <tr>
          <td>03 Message Queue</td>
          <td>10</td>
          <td>10</td>
          <td>0</td>
          <td>達標</td>
          <td>進入案例深度擴寫與反例補充</td>
      </tr>
      <tr>
          <td>04 Observability</td>
          <td>10</td>
          <td>10</td>
          <td>0</td>
          <td>達標</td>
          <td>進入案例深度擴寫與反例補充</td>
      </tr>
      <tr>
          <td>05 Deployment Platform</td>
          <td>10</td>
          <td>10</td>
          <td>0</td>
          <td>達標</td>
          <td>進入案例深度擴寫與反例補充</td>
      </tr>
      <tr>
          <td>06 Reliability</td>
          <td>10</td>
          <td>12</td>
          <td>0</td>
          <td>達標</td>
          <td>補產業多樣性與 rollback 成本對照</td>
      </tr>
      <tr>
          <td>07 Security / Data Protection</td>
          <td>10</td>
          <td>10</td>
          <td>0</td>
          <td>達標</td>
          <td>進入案例深度擴寫與反例補充</td>
      </tr>
      <tr>
          <td>08 Incident Response</td>
          <td>10</td>
          <td>12</td>
          <td>0</td>
          <td>達標</td>
          <td>補「轉換期間事故」專題索引</td>
      </tr>
  </tbody>
</table>
<h2 id="下一輪優先順序">下一輪優先順序</h2>
<p>門檻已達標，下一輪優先順序改為：</p>
<ol>
<li>每分類補「失敗反例」與「轉換失敗回退案例」</li>
<li>每分類補「同議題不同規模企業」對照</li>
<li>把案例回寫到章節正文中的判讀訊號與 tripwire 欄位</li>
</ol>
<h2 id="回退失敗專題索引">回退失敗專題索引</h2>
<p>這個索引的核心責任是讓讀者在「已經出錯」時，能快速找到對應回退失敗模式，而不是從頭重讀選型章節。</p>
<table>
  <thead>
      <tr>
          <th>分類</th>
          <th>回退失敗專題</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>02 Cache / Redis</td>
          <td><a href="/blog/backend/02-cache-redis/cases/failure-cache-stampede-rollout-regression/" data-link-title="2.C9 反例：快取切換引發 Stampede 回歸" data-link-desc="快取策略切換若缺乏保護，會導致回源壓力與錯誤率連鎖上升。">2.C9 反例：快取切換失敗</a></td>
      </tr>
      <tr>
          <td>03 Message Queue</td>
          <td><a href="/blog/backend/03-message-queue/cases/failure-queue-semantics-mismatch-cutover/" data-link-title="3.C9 反例：Queue 語義切換誤配" data-link-desc="at-least-once / exactly-once 語義誤配導致資料重複與遺漏。">3.C9 反例：語義切換失敗</a></td>
      </tr>
      <tr>
          <td>04 Observability</td>
          <td><a href="/blog/backend/04-observability/cases/failure-otel-migration-signal-drift/" data-link-title="4.C9 反例：OTel 遷移後訊號漂移" data-link-desc="雙軌採集未對齊導致告警與 SLO 判讀失真。">4.C9 反例：OTel 訊號漂移</a></td>
      </tr>
      <tr>
          <td>05 Deployment Platform</td>
          <td><a href="/blog/backend/05-deployment-platform/cases/failure-platform-cutover-without-drain/" data-link-title="5.C9 反例：平台切流未先 Draining" data-link-desc="切流時忽略連線清退造成請求錯誤與重試風暴。">5.C9 反例：切流未先 drain</a></td>
      </tr>
      <tr>
          <td>07 Security / Data Protection</td>
          <td><a href="/blog/backend/07-security-data-protection/cases/failure-credential-rotation-without-scope/" data-link-title="7.C9 反例：憑證輪替未分 Scope" data-link-desc="憑證輪替若未分域分批，容易造成跨系統連鎖中斷。">7.C9 反例：憑證輪替失敗</a></td>
      </tr>
  </tbody>
</table>
<h2 id="回退判讀寫法">回退判讀寫法</h2>
<p>回退判讀的核心責任是把失敗條件寫回該分類自己的業務語境。快取看的是回源壓力與資料新鮮度；queue 看的是語義、lag 與重播；observability 看的是訊號語意漂移；deployment 看的是切流、draining 與連線生命週期；security 看的是身份、憑證作用域與控制面擴散。</p>
<p>這些判讀不能抽成同一份模板。每次寫案例時，先回答該分類自己的問題：哪個業務路徑受影響、哪個訊號最早失真、哪個回退動作會降低傷害、哪份證據能證明回退有效。</p>
<h2 id="下一輪補查清單非-db-優先">下一輪補查清單（非 DB 優先）</h2>
<p>下一輪補查會優先補目前中低密度分類，目標是讓每一類至少有 8 到 12 個可回寫案例。</p>
<ol>
<li>Cache：快取策略遷移與失效治理（multi-layer、eviction、warmup）</li>
<li>Queue：broker/語義轉換與 replay 風險控制</li>
<li>Observability：監控平台遷移與資料品質治理</li>
<li>Deployment：部署平台轉換與灰度/回滾策略</li>
<li>Security：控制面信任邊界與憑證機制轉換</li>
</ol>
<h2 id="第二批外部案例補充非-db-類">第二批外部案例補充（非 DB 類）</h2>
<p>這一批的核心責任是把中低密度分類補到可用水位，讓 <code>02/03/04/05/07</code> 都有可引用的真實轉換案例，而不是只有資料庫案例可用。</p>
<table>
  <thead>
      <tr>
          <th>分類</th>
          <th>案例</th>
          <th>轉換焦點</th>
          <th>回寫入口</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Cache</td>
          <td>Meta：Cache made consistent</td>
          <td>cache invalidation 一致性治理升級</td>
          <td><a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.1</a></td>
      </tr>
      <tr>
          <td>Cache</td>
          <td>Meta：mcrouter at scale</td>
          <td>單機快取轉成跨區路由層</td>
          <td><a href="/blog/backend/02-cache-redis/high-concurrency-access/" data-link-title="2.1 高併發下的 Redis 讀寫邊界" data-link-desc="說明高併發服務如何共用 Redis client、控制 pipeline 與避免 cache stampede">2.4</a></td>
      </tr>
      <tr>
          <td>Cache</td>
          <td>Meta：CacheLib + Kangaroo</td>
          <td>DRAM-only 快取轉向 flash-friendly 架構</td>
          <td><a href="/blog/backend/02-cache-redis/ttl-eviction/" data-link-title="2.3 TTL 與 eviction" data-link-desc="整理過期策略、容量控制與熱點資料">2.5</a></td>
      </tr>
      <tr>
          <td>Cache</td>
          <td>Shopify：Marshal -&gt; MessagePack cache migration</td>
          <td>快取序列化格式遷移與雙軌相容</td>
          <td><a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.1</a></td>
      </tr>
      <tr>
          <td>Cache</td>
          <td>Shopify：Shop App write-through cache</td>
          <td>read-heavy 路徑轉 write-through</td>
          <td><a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.1</a></td>
      </tr>
      <tr>
          <td>Queue</td>
          <td>Meta：FOQS disaster-ready migration</td>
          <td>區域佇列轉全域架構且零停機</td>
          <td><a href="/blog/backend/03-message-queue/durable-queue/" data-link-title="3.2 durable queue 與重試策略" data-link-desc="整理持久化佇列、DLQ 與重試流程">3.3</a></td>
      </tr>
      <tr>
          <td>Queue</td>
          <td>LinkedIn：Running Kafka at Scale</td>
          <td>單叢集使用模式轉 tiered cluster</td>
          <td><a href="/blog/backend/03-message-queue/broker-basics/" data-link-title="3.1 broker 基礎與投遞模型" data-link-desc="先理解 broker、queue、consumer 與 delivery semantics">3.1</a></td>
      </tr>
      <tr>
          <td>Queue</td>
          <td>LinkedIn：TopicGC</td>
          <td>Kafka topic 治理從手動轉自動回收</td>
          <td><a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.2</a></td>
      </tr>
      <tr>
          <td>Queue</td>
          <td>VMware Tanzu CloudHealth：Kafka -&gt; Amazon MSK</td>
          <td>自管 broker 轉 managed streaming</td>
          <td><a href="/blog/backend/03-message-queue/broker-basics/" data-link-title="3.1 broker 基礎與投遞模型" data-link-desc="先理解 broker、queue、consumer 與 delivery semantics">3.1</a></td>
      </tr>
      <tr>
          <td>Queue</td>
          <td>Slack：Scaling job queue</td>
          <td>背景工作通道轉 Kafka + Redis 組合</td>
          <td><a href="/blog/backend/03-message-queue/outbox-pattern/" data-link-title="3.3 outbox pattern 與發佈一致性" data-link-desc="把 transaction 與 event publish 分離">3.4</a></td>
      </tr>
      <tr>
          <td>Observability</td>
          <td>AWS：X-Ray SDK/Daemon -&gt; OpenTelemetry migration</td>
          <td>vendor SDK 轉 OTel 標準化</td>
          <td><a href="/blog/backend/04-observability/telemetry-pipeline/" data-link-title="4.11 Telemetry Pipeline 架構" data-link-desc="把 log / metric / trace 的 agent → collector → ingest → storage → query 分層治理">4.21</a></td>
      </tr>
      <tr>
          <td>Observability</td>
          <td>Google Cloud：OTLP support in Cloud Trace (2025)</td>
          <td>專有 ingest 轉 OTLP 標準入口</td>
          <td><a href="/blog/backend/04-observability/telemetry-pipeline/" data-link-title="4.11 Telemetry Pipeline 架構" data-link-desc="把 log / metric / trace 的 agent → collector → ingest → storage → query 分層治理">4.21</a></td>
      </tr>
      <tr>
          <td>Observability</td>
          <td>AWS：ADOT 建立集中觀測平台</td>
          <td>多代理轉單一 OTel pipeline</td>
          <td><a href="/blog/backend/04-observability/observability-operating-model/" data-link-title="4.18 Observability Operating Model" data-link-desc="定義 platform / service team / on-call 對訊號、dashboard、alert 與成本的 ownership">4.18</a></td>
      </tr>
      <tr>
          <td>Observability</td>
          <td>AWS：EKS + ADOT + X-Ray/CloudWatch</td>
          <td>既有監控拆散轉標準化管線</td>
          <td><a href="/blog/backend/04-observability/tracing-context/" data-link-title="4.3 tracing 與 context link" data-link-desc="整理 trace id、span 與跨服務 context propagation">4.7</a></td>
      </tr>
      <tr>
          <td>Observability</td>
          <td>Honeycomb：Burn rate operations</td>
          <td>告警規則轉 error budget 驅動治理</td>
          <td><a href="/blog/backend/04-observability/sli-slo-signal/" data-link-title="4.6 SLI 量測與 SLO 訊號設計" data-link-desc="把可靠性目標的訊號從 metric 端設計好、餵給 6.6 SLO 政策">4.13</a></td>
      </tr>
      <tr>
          <td>Deployment</td>
          <td>Tradeshift：self-hosted K8s -&gt; EKS (zero downtime)</td>
          <td>自管控制面轉 managed control plane</td>
          <td><a href="/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2</a></td>
      </tr>
      <tr>
          <td>Deployment</td>
          <td>Condé Nast：K8s platform modernization on EKS</td>
          <td>多團隊異質集群轉統一平台</td>
          <td><a href="/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2</a></td>
      </tr>
      <tr>
          <td>Deployment</td>
          <td>Orbitera：AWS -&gt; GKE migration</td>
          <td>基礎平台重置與容器編排轉換</td>
          <td><a href="/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2</a></td>
      </tr>
      <tr>
          <td>Deployment</td>
          <td>Mobileye：workloads -&gt; EKS</td>
          <td>資源調度模式轉 managed K8s</td>
          <td><a href="/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2</a></td>
      </tr>
      <tr>
          <td>Deployment</td>
          <td>Miro：microservices/K8s -&gt; EKS managed</td>
          <td>自維運平台轉 managed service 組合</td>
          <td><a href="/blog/backend/05-deployment-platform/kubernetes-deployment/" data-link-title="5.2 Kubernetes 部署策略" data-link-desc="整理 deployment、probe 與 rolling update">5.2</a></td>
      </tr>
      <tr>
          <td>Security/Control Plane</td>
          <td>Cloudflare：2026 route leak incident</td>
          <td>路由政策自動化治理重整</td>
          <td><a href="/blog/backend/07-security-data-protection/security-governance-exception-and-tripwire/" data-link-title="7.14 資安治理例外與 Tripwire" data-link-desc="定義例外管理、風險接受與重新評估觸發器">7.16</a></td>
      </tr>
      <tr>
          <td>Security/Control Plane</td>
          <td>Cloudflare：2026 BYOIP BGP withdrawal</td>
          <td>控制面變更保護與回退策略</td>
          <td><a href="/blog/backend/08-incident-response/containment-recovery-strategy/" data-link-title="8.3 止血、降級與回復策略" data-link-desc="把短期止血與正式回復拆成可執行步驟">8.3</a></td>
      </tr>
      <tr>
          <td>Security/Control Plane</td>
          <td>Cloudflare：2023 control-plane token incident</td>
          <td>token 管理邊界與供應鏈信任調整</td>
          <td><a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.11</a></td>
      </tr>
      <tr>
          <td>Security/Control Plane</td>
          <td>Azure AD：2021 identity control-plane disruption</td>
          <td>身分控制面故障隔離與恢復路由</td>
          <td><a href="/blog/backend/08-incident-response/security-vs-operational-incident/" data-link-title="8.17 Security Incident vs Operational Incident 分流" data-link-desc="把資安事故跟可用性事故的 IR 流程分支點明確化">8.8</a></td>
      </tr>
      <tr>
          <td>Security/Control Plane</td>
          <td>Microsoft 365：2023 suite-wide authentication incident</td>
          <td>身分服務相依邊界重整</td>
          <td><a href="/blog/backend/08-incident-response/customer-impact-assessment/" data-link-title="8.20 Customer Impact Assessment" data-link-desc="把受影響用戶、功能、區域、金額、SLO 與補償判斷串成影響評估模型">8.20</a></td>
      </tr>
  </tbody>
</table>
<h2 id="第二批補查來源">第二批補查來源</h2>
<ul>
<li>Meta：Cache consistency / mcrouter / CacheLib / Kangaroo / FOQS / MyRocks migration</li>
<li>LinkedIn Engineering：Kafka at scale / TopicGC</li>
<li>AWS：CloudHealth Kafka -&gt; MSK、X-Ray -&gt; OTel migration、ADOT/EKS 實務、EKS 遷移案例</li>
<li>Google Cloud：OTLP in Cloud Trace、Orbitera -&gt; GKE</li>
<li>Shopify Engineering：cache serialization migration、write-through cache</li>
<li>Cloudflare Post-mortem：2023/2026 control-plane 與路由事件</li>
</ul>
<h2 id="判讀訊號">判讀訊號</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>判讀重點</th>
          <th>對應章節</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>延遲分布長尾惡化</td>
          <td>是平均值問題還是尖峰問題</td>
          <td><a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a></td>
      </tr>
      <tr>
          <td>重構風險持續升高</td>
          <td>型別/契約是否不足以支撐變更</td>
          <td><a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
      </tr>
      <tr>
          <td>故障常跨服務放大</td>
          <td>架構邊界是否缺乏隔離能力</td>
          <td><a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a></td>
      </tr>
      <tr>
          <td>發布節奏被品質問題拖慢</td>
          <td>問題在語言、工具鏈或架構層</td>
          <td><a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4</a></td>
      </tr>
  </tbody>
</table>
<h2 id="轉換決策資料要求">轉換決策資料要求</h2>
<table>
  <thead>
      <tr>
          <th>資料面向</th>
          <th>最低需要的證據</th>
          <th>若缺失會發生什麼事</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>成本面</td>
          <td>現況維運成本與轉換成本（人力、基礎設施、機會成本）</td>
          <td>轉換中途停擺或 ROI 判斷失真</td>
      </tr>
      <tr>
          <td>風險面</td>
          <td>故障型態、爆炸半徑、回退時間</td>
          <td>上線後故障放大但無法快速止血</td>
      </tr>
      <tr>
          <td>性能面</td>
          <td>P50/P95/P99、吞吐、尖峰流量下的行為</td>
          <td>只優化平均值，長尾問題仍存在</td>
      </tr>
      <tr>
          <td>組織面</td>
          <td>團隊技能分布、訓練成本、維運責任邊界</td>
          <td>工具換了但組織無法承接</td>
      </tr>
      <tr>
          <td>生命週期面</td>
          <td>依賴版本 EOL、供應商策略、平台相容性</td>
          <td>被動升級，且在最差時機被迫遷移</td>
      </tr>
      <tr>
          <td>遷移可行性面</td>
          <td>雙寫/雙跑策略、灰度範圍、指標切換門檻、回滾條件</td>
          <td>遷移無法分段驗證，風險一次性爆發</td>
      </tr>
  </tbody>
</table>
<h2 id="轉換前要先回答的三個問題">轉換前要先回答的三個問題</h2>
<ol>
<li>現有問題是「局部優化可解」還是「結構性不匹配」？</li>
<li>轉換後的收益是性能、可靠性、開發效率哪一項，如何量化？</li>
<li>遷移期間如何維持雙軌可運行與回退能力？</li>
</ol>
<p>如果三個問題答不清楚，通常代表先做局部治理比全面轉換更穩定。</p>
<h2 id="常見誤區">常見誤區</h2>
<p>把「技術新舊」當成轉換理由，容易忽略遷移期成本。可靠做法是先界定症狀與邊界，再決定要換語言、換工具，或只換架構切分方式。</p>
<h2 id="下一步路由">下一步路由</h2>
<p>若問題在執行時特性（延遲抖動、記憶體模型），先回 <a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a> 與 <a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a>。若是資料庫轉換已進入執行階段，直接進 <a href="/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6 資料庫轉換實作</a>；需要把 production migration 寫成 evidence、gate 與 decision log，接 <a href="/blog/backend/01-database/schema-migration-rollout-evidence/" data-link-title="1.7 Schema Migration Rollout 證據（Schema Migration Rollout Evidence）實作示範" data-link-desc="以訂單付款狀態欄位演進示範 schema migration 如何產出 evidence、release gate 與 incident decision log。">1.7 Schema Migration Rollout 證據</a>；需要放行與回滾治理時，接 <a href="/blog/backend/06-reliability/migration-safety/" data-link-title="6.11 Migration Safety 與 DB Rollout" data-link-desc="把 schema migration 從一次性事件變成可逆、可漸進的 rollout 流程">6.11 Migration Safety</a>；若要看事故層教訓，接 <a href="/blog/backend/08-incident-response/cases/github/2018-oct21-mysql-topology-incident/" data-link-title="GitHub 2018 Oct21 MySQL Topology Incident" data-link-desc="2018-10-21 GitHub 因 network partition 觸發跨區資料庫拓撲異常的事故解析：資料一致性優先、fail-forward 決策與長時間恢復。">GitHub 2018 Oct21 MySQL Topology Incident</a>。</p>
<h2 id="引用源">引用源</h2>
<ul>
<li><a href="https://slack.engineering/hacklang-at-slack-a-better-php/">Hacklang at Slack: A Better PHP</a>：Slack 說明 PHP 到 Hack 的遷移動機與型別收益。</li>
<li><a href="https://slack.engineering/how-big-technical-changes-happen-at-slack/">How Big Technical Changes Happen at Slack</a>：Slack 逐步遷移與組織推進方式。</li>
<li><a href="https://discord.com/blog/why-discord-is-switching-from-go-to-rust">Why Discord is switching from Go to Rust</a>：Discord 說明 Go→Rust 的延遲與 GC 觀察。</li>
<li><a href="https://slack.engineering/slacks-migration-to-a-cellular-architecture/">Slack’s Migration to a Cellular Architecture</a>：Slack 從單體拓撲轉到 cell 架構的原因。</li>
<li><a href="https://dropbox.tech/application/the-long-awaited-python-3-upgrade-at-dropbox">The Long-Awaited Python 3 Upgrade at Dropbox</a>：Dropbox 的 Python 2 -&gt; 3 遷移動機與推進方式。</li>
<li><a href="https://dropbox.tech/infrastructure/rewriting-the-heart-of-our-sync-engine">Rewriting the heart of our sync engine</a>：Dropbox 在核心效能路徑重寫的轉換決策脈絡。</li>
<li><a href="https://dropbox.tech/infrastructure/courier-driving-the-first-years-of-grpc">Courier: Driving the first years of gRPC</a>：Dropbox 內部 RPC 到 gRPC 的演進背景。</li>
<li><a href="https://about.gitlab.com/blog/2022/06/02/splitting-database-into-main-and-ci/">Splitting database into Main and CI</a>：GitLab 的資料庫職責拆分案例。</li>
<li><a href="https://www.notion.com/blog/sharding-postgres-at-notion">Sharding Postgres at Notion</a>：Notion 分片遷移與容量壓力背景。</li>
<li><a href="https://shopify.engineering/blogs/engineering/horizontally-scaling-the-rails-backend-of-shop-app-with-vitess">Horizontally scaling the Rails backend of Shop App with Vitess</a>：Shopify 導入 Vitess 的原因與方式。</li>
<li><a href="https://shopify.engineering/adopting-sorbet">How Shopify Is Adopting Sorbet</a>：Shopify 在大型 Ruby 程式碼庫導入型別系統。</li>
<li><a href="https://www.figma.com/blog/migrating-figma-to-kubernetes/">Migrating Figma to Kubernetes</a>：Figma 的平台遷移原因與收益。</li>
<li><a href="https://blog.cloudflare.com/rust-nginx-module/">A Rust regex engine in NGINX</a>：Cloudflare 在高效能路徑導入 Rust 的案例。</li>
<li><a href="https://www.uber.com/en-GB/blog/microservice-architecture/">Domain-Oriented Microservice Architecture</a>：Uber 在規模化後重整服務邊界。</li>
<li><a href="https://engineering.fb.com/2016/08/31/core-infra/myrocks-a-space-and-write-optimized-mysql-database/">MyRocks: A space- and write-optimized MySQL database</a>：Meta 導入 MyRocks 的成本與效能動機。</li>
</ul>
]]></content:encoded></item><item><title>0.4 操作平台選型</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/operations-platform-selection/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/operations-platform-selection/</guid><description>&lt;p>操作平台選型的核心原則是先判斷系統需要哪一種操作能力。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&lt;/a>、metric、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert&lt;/a>、deployment platform 與 reliability pipeline 都服務於系統運行，但它們回答的問題不同。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>區分 log、metric、trace、dashboard 與 alert 的用途&lt;/li>
&lt;li>判斷部署平台與可靠性驗證流程解決的問題&lt;/li>
&lt;li>用事故症狀和操作需求判斷應先補哪種平台能力&lt;/li>
&lt;li>把操作平台選型轉成可檢查的工程判斷&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="觀察操作問題會表現成診斷或交付困難">【觀察】操作問題會表現成診斷或交付困難&lt;/h2>
&lt;p>操作平台需求通常來自事故、擴容、發版或維護壓力。當服務在本機可用，但到生產環境後很難診斷、告警、部署或驗證，問題就已經超出語言本身。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>需求訊號&lt;/th>
 &lt;th>代表的工程問題&lt;/th>
 &lt;th>優先評估方向&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>只知道錯了，看不到上下文&lt;/td>
 &lt;td>操作事件與錯誤脈絡&lt;/td>
 &lt;td>log aggregation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>想看趨勢、容量、錯誤率&lt;/td>
 &lt;td>數值訊號與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI/SLO&lt;/a>&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>跨服務 request path 不清楚&lt;/td>
 &lt;td>呼叫鏈與延遲拆解&lt;/td>
 &lt;td>tracing&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>團隊需要共同看服務健康&lt;/td>
 &lt;td>視覺化與操作入口&lt;/td>
 &lt;td>dashboard&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>問題發生時需要主動通知&lt;/td>
 &lt;td>告警與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a>&lt;/td>
 &lt;td>alerting&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>發版與擴容不穩&lt;/td>
 &lt;td>平台合約與流量入口&lt;/td>
 &lt;td>deployment platform&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>想驗證系統能承受壓力與失敗&lt;/td>
 &lt;td>可靠性驗證&lt;/td>
 &lt;td>reliability pipeline&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表是索引。每種能力都可以採用不同產品與平台，但第一步是判斷你缺的是哪一種操作能力。&lt;/p>
&lt;h2 id="判讀log-aggregation-承擔事件脈絡">【判讀】log aggregation 承擔事件脈絡&lt;/h2>
&lt;p>log aggregation 的核心責任是收集可搜尋的操作事件。當工程師需要知道某個 request、event、worker 或 client 發生了什麼，log 是最直接的診斷入口。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>查某筆訂單 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook&lt;/a> 為什麼被拒絕&lt;/li>
&lt;li>查某個 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a> message 重試了幾次&lt;/li>
&lt;li>查某個 client 連線何時建立、何時斷線&lt;/li>
&lt;/ul>
&lt;p>這類平台的主要風險是欄位不穩定與敏感資料外洩。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">log schema&lt;/a> 要像 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/api-contract/" data-link-title="API Contract" data-link-desc="說明 request / response 邊界如何維持相容與可驗證">API Contract&lt;/a> 一樣維持欄位名稱，並在服務輸出前控制 token、payload 與個資。&lt;/p>
&lt;h2 id="判讀metrics-承擔趨勢與容量判斷">【判讀】metrics 承擔趨勢與容量判斷&lt;/h2>
&lt;p>metrics 的核心責任是把服務狀態轉成可聚合的數值。當團隊需要看錯誤率、延遲、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/throughput/" data-link-title="Throughput" data-link-desc="整理系統單位時間內可處理的工作量">throughput&lt;/a>、queue lag、goroutine count 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-rate/" data-link-title="Cache Hit Rate" data-link-desc="說明快取命中比例如何衡量加速效果與下游保護">cache hit rate&lt;/a>，metrics 是主要工具。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>API p95 latency 是否持續上升&lt;/li>
&lt;li>queue lag 是否超過 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer&lt;/a> 處理能力&lt;/li>
&lt;li>Redis &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-key/" data-link-title="Hot Key" data-link-desc="說明單一 key 承受大量讀寫時如何形成容量瓶頸">hot key&lt;/a> 是否造成 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout&lt;/a> 增加&lt;/li>
&lt;/ul>
&lt;p>這類平台的主要風險是 cardinality。label 設計要能聚合趨勢，同時避免把 user id、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/request-id/" data-link-title="Request ID" data-link-desc="說明單次 request 的識別碼如何支援 log 搜尋與問題定位">request id&lt;/a> 這類高基數欄位放進 metric。&lt;/p>
&lt;h2 id="判讀tracing-承擔跨服務路徑">【判讀】tracing 承擔跨服務路徑&lt;/h2>
&lt;p>tracing 的核心責任是把一次 request 或事件處理串成跨服務路徑。當一個操作會經過 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/request-routing/" data-link-title="Request Routing" data-link-desc="說明入口流量如何依規則被導向不同服務或處理路徑">Request Routing&lt;/a>、service、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a>、queue、worker 和外部 API，trace 可以拆解每一段延遲與錯誤位置。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>checkout request 經過 cart、payment、inventory、shipping 多個服務&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook&lt;/a> 進入後觸發 queue，再由 worker 呼叫外部 API&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/bff/" data-link-title="BFF" data-link-desc="說明 Backend for Frontend 如何聚合下游服務並服務特定客戶端">BFF&lt;/a> API 聚合多個下游服務造成延遲不穩&lt;/li>
&lt;/ul>
&lt;p>這類平台的主要風險是 context propagation。服務之間要傳遞 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace-id/" data-link-title="Trace ID" data-link-desc="說明分散式追蹤中同一條呼叫路徑的識別碼">trace id&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/span/" data-link-title="Span" data-link-desc="說明 trace 中一段工作如何記錄耗時、狀態與關聯">span&lt;/a> context 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/correlation-id/" data-link-title="Correlation ID" data-link-desc="說明跨事件或跨服務的關聯識別碼如何支援排障">correlation id&lt;/a>，否則 trace 會在邊界斷掉。&lt;/p></description><content:encoded><![CDATA[<p>操作平台選型的核心原則是先判斷系統需要哪一種操作能力。<a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a>、metric、<a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a>、<a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a>、<a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>、deployment platform 與 reliability pipeline 都服務於系統運行，但它們回答的問題不同。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>區分 log、metric、trace、dashboard 與 alert 的用途</li>
<li>判斷部署平台與可靠性驗證流程解決的問題</li>
<li>用事故症狀和操作需求判斷應先補哪種平台能力</li>
<li>把操作平台選型轉成可檢查的工程判斷</li>
</ol>
<hr>
<h2 id="觀察操作問題會表現成診斷或交付困難">【觀察】操作問題會表現成診斷或交付困難</h2>
<p>操作平台需求通常來自事故、擴容、發版或維護壓力。當服務在本機可用，但到生產環境後很難診斷、告警、部署或驗證，問題就已經超出語言本身。</p>
<table>
  <thead>
      <tr>
          <th>需求訊號</th>
          <th>代表的工程問題</th>
          <th>優先評估方向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>只知道錯了，看不到上下文</td>
          <td>操作事件與錯誤脈絡</td>
          <td>log aggregation</td>
      </tr>
      <tr>
          <td>想看趨勢、容量、錯誤率</td>
          <td>數值訊號與 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI/SLO</a></td>
          <td><a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics</a></td>
      </tr>
      <tr>
          <td>跨服務 request path 不清楚</td>
          <td>呼叫鏈與延遲拆解</td>
          <td>tracing</td>
      </tr>
      <tr>
          <td>團隊需要共同看服務健康</td>
          <td>視覺化與操作入口</td>
          <td>dashboard</td>
      </tr>
      <tr>
          <td>問題發生時需要主動通知</td>
          <td>告警與 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a></td>
          <td>alerting</td>
      </tr>
      <tr>
          <td>發版與擴容不穩</td>
          <td>平台合約與流量入口</td>
          <td>deployment platform</td>
      </tr>
      <tr>
          <td>想驗證系統能承受壓力與失敗</td>
          <td>可靠性驗證</td>
          <td>reliability pipeline</td>
      </tr>
  </tbody>
</table>
<p>這張表是索引。每種能力都可以採用不同產品與平台，但第一步是判斷你缺的是哪一種操作能力。</p>
<h2 id="判讀log-aggregation-承擔事件脈絡">【判讀】log aggregation 承擔事件脈絡</h2>
<p>log aggregation 的核心責任是收集可搜尋的操作事件。當工程師需要知道某個 request、event、worker 或 client 發生了什麼，log 是最直接的診斷入口。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>查某筆訂單 <a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook</a> 為什麼被拒絕</li>
<li>查某個 <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a> message 重試了幾次</li>
<li>查某個 client 連線何時建立、何時斷線</li>
</ul>
<p>這類平台的主要風險是欄位不穩定與敏感資料外洩。<a href="/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">log schema</a> 要像 <a href="/blog/backend/knowledge-cards/api-contract/" data-link-title="API Contract" data-link-desc="說明 request / response 邊界如何維持相容與可驗證">API Contract</a> 一樣維持欄位名稱，並在服務輸出前控制 token、payload 與個資。</p>
<h2 id="判讀metrics-承擔趨勢與容量判斷">【判讀】metrics 承擔趨勢與容量判斷</h2>
<p>metrics 的核心責任是把服務狀態轉成可聚合的數值。當團隊需要看錯誤率、延遲、<a href="/blog/backend/knowledge-cards/throughput/" data-link-title="Throughput" data-link-desc="整理系統單位時間內可處理的工作量">throughput</a>、queue lag、goroutine count 或 <a href="/blog/backend/knowledge-cards/cache-hit-rate/" data-link-title="Cache Hit Rate" data-link-desc="說明快取命中比例如何衡量加速效果與下游保護">cache hit rate</a>，metrics 是主要工具。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>API p95 latency 是否持續上升</li>
<li>queue lag 是否超過 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a> 處理能力</li>
<li>Redis <a href="/blog/backend/knowledge-cards/hot-key/" data-link-title="Hot Key" data-link-desc="說明單一 key 承受大量讀寫時如何形成容量瓶頸">hot key</a> 是否造成 <a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout</a> 增加</li>
</ul>
<p>這類平台的主要風險是 cardinality。label 設計要能聚合趨勢，同時避免把 user id、<a href="/blog/backend/knowledge-cards/request-id/" data-link-title="Request ID" data-link-desc="說明單次 request 的識別碼如何支援 log 搜尋與問題定位">request id</a> 這類高基數欄位放進 metric。</p>
<h2 id="判讀tracing-承擔跨服務路徑">【判讀】tracing 承擔跨服務路徑</h2>
<p>tracing 的核心責任是把一次 request 或事件處理串成跨服務路徑。當一個操作會經過 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>、<a href="/blog/backend/knowledge-cards/request-routing/" data-link-title="Request Routing" data-link-desc="說明入口流量如何依規則被導向不同服務或處理路徑">Request Routing</a>、service、<a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a>、queue、worker 和外部 API，trace 可以拆解每一段延遲與錯誤位置。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>checkout request 經過 cart、payment、inventory、shipping 多個服務</li>
<li><a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook</a> 進入後觸發 queue，再由 worker 呼叫外部 API</li>
<li><a href="/blog/backend/knowledge-cards/bff/" data-link-title="BFF" data-link-desc="說明 Backend for Frontend 如何聚合下游服務並服務特定客戶端">BFF</a> API 聚合多個下游服務造成延遲不穩</li>
</ul>
<p>這類平台的主要風險是 context propagation。服務之間要傳遞 <a href="/blog/backend/knowledge-cards/trace-id/" data-link-title="Trace ID" data-link-desc="說明分散式追蹤中同一條呼叫路徑的識別碼">trace id</a>、<a href="/blog/backend/knowledge-cards/span/" data-link-title="Span" data-link-desc="說明 trace 中一段工作如何記錄耗時、狀態與關聯">span</a> context 與 <a href="/blog/backend/knowledge-cards/correlation-id/" data-link-title="Correlation ID" data-link-desc="說明跨事件或跨服務的關聯識別碼如何支援排障">correlation id</a>，否則 trace 會在邊界斷掉。</p>
<h2 id="判讀dashboard-與-alert-承擔操作決策">【判讀】dashboard 與 alert 承擔操作決策</h2>
<p>dashboard 的核心責任是讓團隊看見服務健康；alert 的核心責任是把需要動作的異常主動送到負責者面前。兩者應該連到同一套 SLI、SLO 與 runbook。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>API error rate 超過 SLO 時通知 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a></li>
<li>queue lag 超過可接受時間時提示擴容 consumer</li>
<li><a href="/blog/backend/knowledge-cards/websocket/" data-link-title="WebSocket" data-link-desc="說明 WebSocket 如何提供長連線雙向即時通訊">WebSocket</a> disconnect rate 在特定地區突然升高</li>
</ul>
<p>這類平台的主要風險是噪音。alert 應對應可執行動作；dashboard 應服務排障與容量判斷，圖表呈現則要服務這些操作目標。</p>
<h2 id="判讀deployment-platform-承擔服務交付">【判讀】deployment platform 承擔服務交付</h2>
<p>deployment platform 的核心責任是讓服務穩定啟動、更新、接流量、擴容與停止。當問題集中在發版、健康檢查、資源限制、流量入口或服務發現，應先評估部署平台能力。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li><a href="/blog/backend/knowledge-cards/rolling-update/" data-link-title="Rolling Update" data-link-desc="說明逐批替換服務版本的發版策略與風險控制">rolling update</a> 時新版本還沒 ready 就接到流量</li>
<li>pod 被停止時還有 worker 和長連線尚未清理</li>
<li>多個 service instance 需要透過 <a href="/blog/backend/knowledge-cards/load-balancer/" data-link-title="Load Balancer" data-link-desc="說明流量如何分散、排空與導向健康節點">load balancer</a> 與 <a href="/blog/backend/knowledge-cards/service-registry/" data-link-title="Service Registry" data-link-desc="說明服務實例如何被註冊、維護與摘除">service registry</a>、<a href="/blog/backend/knowledge-cards/service-discovery/" data-link-title="Service Discovery" data-link-desc="說明服務實例如何被查找與路由">service discovery</a> 協作</li>
</ul>
<p>這類平台的主要風險是程式與平台合約不一致。服務要提供 <a href="/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness</a>、<a href="/blog/backend/knowledge-cards/health-check-liveness/" data-link-title="Liveness" data-link-desc="說明平台如何判斷 process 是否仍然存活，以及何時應重啟">liveness</a>、<a href="/blog/backend/knowledge-cards/graceful-shutdown/" data-link-title="Graceful Shutdown" data-link-desc="說明服務停止前如何排空流量、完成工作與保存狀態">graceful shutdown</a> 與 resource usage 訊號；平台要根據這些訊號調度流量。</p>
<h2 id="判讀reliability-pipeline-承擔失敗前驗證">【判讀】reliability pipeline 承擔失敗前驗證</h2>
<p>reliability pipeline 的核心責任是在事故前驗證系統承受能力。<a href="/blog/backend/knowledge-cards/ci-pipeline/" data-link-title="CI Pipeline" data-link-desc="說明持續整合流程如何在合併前驗證品質與相容性">CI pipeline</a>、<a href="/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">load test</a>、<a href="/blog/backend/knowledge-cards/fuzz-test/" data-link-title="Fuzz Test" data-link-desc="說明用隨機與變異輸入驗證解析器與邊界處理健壯性">fuzz test</a>、<a href="/blog/backend/knowledge-cards/chaos-test/" data-link-title="Chaos Test" data-link-desc="說明透過受控故障注入驗證系統在異常條件下的恢復能力">chaos test</a> 都屬於可靠性驗證，但它們觀察的風險不同。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>發版前確認 <a href="/blog/backend/knowledge-cards/api-contract/" data-link-title="API Contract" data-link-desc="說明 request / response 邊界如何維持相容與可驗證">API Contract</a> 和 <a href="/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration</a> 能一起通過</li>
<li>高流量活動前用 <a href="/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">load test</a> 驗證容量</li>
<li>對 parser、<a href="/blog/backend/knowledge-cards/protocol/" data-link-title="Communication Protocol" data-link-desc="說明不同系統如何對齊資料交換與錯誤語意">protocol</a> 或 <a href="/blog/backend/knowledge-cards/input-validation/" data-link-title="Input Validation" data-link-desc="說明進入系統的資料如何先被檢查格式、範圍與語意">input validation</a> 做 fuzz campaign</li>
<li>在預備環境演練 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a>、database、network failure</li>
</ul>
<p>這類流程的主要風險是測試和真實系統脫節。可靠性驗證要對準實際 failure mode，並產出可行的修正或容量決策。</p>
<h2 id="檢查進入實作前的概念邊界清單">【檢查】進入實作前的概念邊界清單</h2>
<p>當以下問題都能回答時，代表本章的概念層已完成，可以進入操作平台實作章節：</p>
<ol>
<li>每種觀測訊號的責任是否明確（log、metric、trace、alert）</li>
<li>告警是否對應可執行動作與 runbook</li>
<li>部署平台與服務合約是否明確（readiness、shutdown、資源限制）</li>
<li>可靠性驗證是否有固定入口（CI、load、chaos）</li>
</ol>
<p>下一步建議路由：</p>
<ul>
<li><a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">04-observability</a></li>
<li><a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">05-deployment-platform</a></li>
<li><a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">06-reliability</a></li>
</ul>
<h2 id="小結">小結</h2>
<p>操作平台選型要先看團隊缺的是哪種運行能力。需要事件脈絡看 log，需要趨勢看 metrics，需要跨服務路徑看 tracing，需要共同操作入口看 dashboard，需要主動通知看 alert，需要穩定交付看 deployment platform，需要事故前驗證看 reliability pipeline。分類清楚後，產品與工具比較才會有明確目標。</p>
]]></content:encoded></item><item><title>0.5 流量與資料量評估</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/traffic-data-scale/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/traffic-data-scale/</guid><description>&lt;p>流量與資料量評估的核心原則是先描述規模形狀，再討論服務能力。平均 QPS、尖峰倍率、資料成長速度、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-key/" data-link-title="Hot Key" data-link-desc="說明單一 key 承受大量讀寫時如何形成容量瓶頸">hot key&lt;/a>、保留期限與讀寫比例，會直接影響資料庫、快取、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a>、觀測與部署平台的選型方向。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>區分平均流量、尖峰流量、burst 與批次流量&lt;/li>
&lt;li>用讀寫比例、hot key 與資料成長辨識瓶頸形狀&lt;/li>
&lt;li>評估資料保留期限與查詢範圍對服務能力的影響&lt;/li>
&lt;li>避免用單一數字描述所有容量問題&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="觀察容量問題通常來自形狀差異">【觀察】容量問題通常來自形狀差異&lt;/h2>
&lt;p>容量評估的第一個問題是「壓力如何出現」。同樣是一千個 request，每秒穩定進來、五秒內全部湧入、集中打同一個商品、或每次都查不同使用者，對系統的壓力完全不同。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>評估面向&lt;/th>
 &lt;th>需要回答的問題&lt;/th>
 &lt;th>常見影響&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>平均流量&lt;/td>
 &lt;td>平常每秒有多少 request 或 message&lt;/td>
 &lt;td>基礎容量與成本&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>尖峰倍率&lt;/td>
 &lt;td>尖峰是平均的幾倍，持續多久&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">buffer&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/autoscaling/" data-link-title="Autoscaling" data-link-desc="說明系統如何依負載自動調整服務實例數量">autoscaling&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>讀寫比例&lt;/td>
 &lt;td>讀多、寫多，還是混合交易&lt;/td>
 &lt;td>cache、index、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">transaction&lt;/a> 設計&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>hot key&lt;/td>
 &lt;td>壓力是否集中在少數 key&lt;/td>
 &lt;td>cache、sharding、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">rate limit&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>資料成長&lt;/td>
 &lt;td>每天新增多少 row、event 或 object&lt;/td>
 &lt;td>storage、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>查詢範圍&lt;/td>
 &lt;td>查最近資料、全量資料，還是任意條件&lt;/td>
 &lt;td>index、search、archive&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>保留期限&lt;/td>
 &lt;td>資料要留多久，是否需要 audit&lt;/td>
 &lt;td>cost、lifecycle、compliance&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表是評估索引。真正的容量討論要把數字放回產品情境，才能知道需要擴充哪種能力。&lt;/p>
&lt;h2 id="判讀平均流量決定基礎容量">【判讀】平均流量決定基礎容量&lt;/h2>
&lt;p>平均流量的核心用途是估算日常成本與基本容量。穩定 API、背景 worker、資料同步與觀測資料，都需要知道平常每秒會產生多少 request、message、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&lt;/a>、metric 或資料寫入。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>一個 B2B &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">SaaS&lt;/a> 白天每秒 50 個 API request，晚上降到每秒 5 個。&lt;/li>
&lt;li>一個 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook&lt;/a> 平均每秒 20 筆事件，但每筆事件會觸發三個下游工作。&lt;/li>
&lt;li>一個即時 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a> 平均每秒收到 200 筆狀態更新。&lt;/li>
&lt;/ul>
&lt;p>這類評估的陷阱是只看平均值。平均值能估算基礎成本，但它無法說明尖峰、集中 key、批次匯入或下游失敗時的堆積風險。&lt;/p>
&lt;h2 id="判讀尖峰流量決定緩衝與降級策略">【判讀】尖峰流量決定緩衝與降級策略&lt;/h2>
&lt;p>尖峰流量的核心用途是估算系統如何吸收短時間壓力。活動開賣、推播通知、直播開始、月底結帳、第三方批次同步，都可能讓流量在短時間內暴增。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>活動開始後前三分鐘的商品頁瀏覽量是平常的 30 倍。&lt;/li>
&lt;li>推播送出後，大量 client 同時回到 App 查通知列表。&lt;/li>
&lt;li>每天凌晨外部系統一次送入大量資料檔。&lt;/li>
&lt;/ul>
&lt;p>這類評估的陷阱是把尖峰當成一般擴容問題。尖峰可能需要 queue、backpressure、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-warmup/" data-link-title="Cache Warmup" data-link-desc="說明服務啟動或活動前如何預先建立快取資料">cache warmup&lt;/a>、rate limit、預先產生 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model&lt;/a> 或降級策略；單純加機器未必能保護資料庫、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a> 或外部 API。&lt;/p>
&lt;h2 id="判讀讀寫比例決定資料路徑設計">【判讀】讀寫比例決定資料路徑設計&lt;/h2>
&lt;p>讀寫比例的核心用途是判斷主要壓力在讀取、寫入還是交易一致性。讀多系統常需要 cache、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model&lt;/a> 或搜尋索引；寫多系統則更關心 transaction、batching、queue、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency&lt;/a> 與資料成長。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>商品頁是讀多寫少，資料可短暫快取。&lt;/li>
&lt;li>訂單建立是寫入與交易一致性重點，狀態轉移要受保護。&lt;/li>
&lt;li>行為分析事件是寫多讀少，讀取通常集中在離線報表或聚合結果。&lt;/li>
&lt;/ul>
&lt;p>這類評估的陷阱是只問資料量。十億筆冷資料和一萬筆每秒被反覆讀寫的熱資料，壓力來源完全不同。讀寫比例要和查詢模式、更新頻率與一致性需求一起看。&lt;/p>
&lt;h2 id="判讀hot-key-會讓平均流量失真">【判讀】hot key 會讓平均流量失真&lt;/h2>
&lt;p>hot key 的核心訊號是壓力集中在少數資料上。即使整體 QPS 看起來正常，單一商品、單一直播間、單一聊天室、單一熱門文章或單一 tenant 也可能打爆特定資料路徑。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>一個熱門商品承接大部分查詢與庫存扣減。&lt;/li>
&lt;li>一個大型直播間同時有大量觀眾接收訊息。&lt;/li>
&lt;li>一個企業 tenant 的使用量遠高於其他 tenant。&lt;/li>
&lt;/ul>
&lt;p>這類評估的陷阱是只做整體水平擴展。hot key 可能需要資料拆分、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic&lt;/a> 分層、快取策略、讀寫分離、限流或產品層降級；具體做法要等需求形狀確認後再進入服務細節。&lt;/p>
&lt;h2 id="判讀資料成長與保留期限決定長期成本">【判讀】資料成長與保留期限決定長期成本&lt;/h2>
&lt;p>資料成長評估的核心問題是「今天可用的設計，三個月後是否仍可用」。row、event、log、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace&lt;/a>、object、index 都會成長；不同資料還有不同查詢頻率與保留需求。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>每天新增一百萬筆行為事件，但只查最近七天即時聚合。&lt;/li>
&lt;li>每天新增十萬筆付款紀錄，法規要求保存多年。&lt;/li>
&lt;li>每天產生大量 debug log，但事故排查主要看最近兩週。&lt;/li>
&lt;/ul>
&lt;p>這類評估的陷阱是把所有資料都放進同一個保存策略。正式狀態、audit、分析事件、debug log、trace、使用者上傳檔案需要不同保留期限、查詢方式與封存策略。&lt;/p></description><content:encoded><![CDATA[<p>流量與資料量評估的核心原則是先描述規模形狀，再討論服務能力。平均 QPS、尖峰倍率、資料成長速度、<a href="/blog/backend/knowledge-cards/hot-key/" data-link-title="Hot Key" data-link-desc="說明單一 key 承受大量讀寫時如何形成容量瓶頸">hot key</a>、保留期限與讀寫比例，會直接影響資料庫、快取、<a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a>、觀測與部署平台的選型方向。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>區分平均流量、尖峰流量、burst 與批次流量</li>
<li>用讀寫比例、hot key 與資料成長辨識瓶頸形狀</li>
<li>評估資料保留期限與查詢範圍對服務能力的影響</li>
<li>避免用單一數字描述所有容量問題</li>
</ol>
<hr>
<h2 id="觀察容量問題通常來自形狀差異">【觀察】容量問題通常來自形狀差異</h2>
<p>容量評估的第一個問題是「壓力如何出現」。同樣是一千個 request，每秒穩定進來、五秒內全部湧入、集中打同一個商品、或每次都查不同使用者，對系統的壓力完全不同。</p>
<table>
  <thead>
      <tr>
          <th>評估面向</th>
          <th>需要回答的問題</th>
          <th>常見影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>平均流量</td>
          <td>平常每秒有多少 request 或 message</td>
          <td>基礎容量與成本</td>
      </tr>
      <tr>
          <td>尖峰倍率</td>
          <td>尖峰是平均的幾倍，持續多久</td>
          <td><a href="/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">buffer</a>、<a href="/blog/backend/knowledge-cards/autoscaling/" data-link-title="Autoscaling" data-link-desc="說明系統如何依負載自動調整服務實例數量">autoscaling</a>、<a href="/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure</a></td>
      </tr>
      <tr>
          <td>讀寫比例</td>
          <td>讀多、寫多，還是混合交易</td>
          <td>cache、index、<a href="/blog/backend/knowledge-cards/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">transaction</a> 設計</td>
      </tr>
      <tr>
          <td>hot key</td>
          <td>壓力是否集中在少數 key</td>
          <td>cache、sharding、<a href="/blog/backend/knowledge-cards/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">rate limit</a></td>
      </tr>
      <tr>
          <td>資料成長</td>
          <td>每天新增多少 row、event 或 object</td>
          <td>storage、<a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition</a>、<a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention</a></td>
      </tr>
      <tr>
          <td>查詢範圍</td>
          <td>查最近資料、全量資料，還是任意條件</td>
          <td>index、search、archive</td>
      </tr>
      <tr>
          <td>保留期限</td>
          <td>資料要留多久，是否需要 audit</td>
          <td>cost、lifecycle、compliance</td>
      </tr>
  </tbody>
</table>
<p>這張表是評估索引。真正的容量討論要把數字放回產品情境，才能知道需要擴充哪種能力。</p>
<h2 id="判讀平均流量決定基礎容量">【判讀】平均流量決定基礎容量</h2>
<p>平均流量的核心用途是估算日常成本與基本容量。穩定 API、背景 worker、資料同步與觀測資料，都需要知道平常每秒會產生多少 request、message、<a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a>、metric 或資料寫入。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>一個 B2B <a href="/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">SaaS</a> 白天每秒 50 個 API request，晚上降到每秒 5 個。</li>
<li>一個 <a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook</a> 平均每秒 20 筆事件，但每筆事件會觸發三個下游工作。</li>
<li>一個即時 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> 平均每秒收到 200 筆狀態更新。</li>
</ul>
<p>這類評估的陷阱是只看平均值。平均值能估算基礎成本，但它無法說明尖峰、集中 key、批次匯入或下游失敗時的堆積風險。</p>
<h2 id="判讀尖峰流量決定緩衝與降級策略">【判讀】尖峰流量決定緩衝與降級策略</h2>
<p>尖峰流量的核心用途是估算系統如何吸收短時間壓力。活動開賣、推播通知、直播開始、月底結帳、第三方批次同步，都可能讓流量在短時間內暴增。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>活動開始後前三分鐘的商品頁瀏覽量是平常的 30 倍。</li>
<li>推播送出後，大量 client 同時回到 App 查通知列表。</li>
<li>每天凌晨外部系統一次送入大量資料檔。</li>
</ul>
<p>這類評估的陷阱是把尖峰當成一般擴容問題。尖峰可能需要 queue、backpressure、<a href="/blog/backend/knowledge-cards/cache-warmup/" data-link-title="Cache Warmup" data-link-desc="說明服務啟動或活動前如何預先建立快取資料">cache warmup</a>、rate limit、預先產生 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a> 或降級策略；單純加機器未必能保護資料庫、<a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> 或外部 API。</p>
<h2 id="判讀讀寫比例決定資料路徑設計">【判讀】讀寫比例決定資料路徑設計</h2>
<p>讀寫比例的核心用途是判斷主要壓力在讀取、寫入還是交易一致性。讀多系統常需要 cache、<a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a> 或搜尋索引；寫多系統則更關心 transaction、batching、queue、<a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 與資料成長。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>商品頁是讀多寫少，資料可短暫快取。</li>
<li>訂單建立是寫入與交易一致性重點，狀態轉移要受保護。</li>
<li>行為分析事件是寫多讀少，讀取通常集中在離線報表或聚合結果。</li>
</ul>
<p>這類評估的陷阱是只問資料量。十億筆冷資料和一萬筆每秒被反覆讀寫的熱資料，壓力來源完全不同。讀寫比例要和查詢模式、更新頻率與一致性需求一起看。</p>
<h2 id="判讀hot-key-會讓平均流量失真">【判讀】hot key 會讓平均流量失真</h2>
<p>hot key 的核心訊號是壓力集中在少數資料上。即使整體 QPS 看起來正常，單一商品、單一直播間、單一聊天室、單一熱門文章或單一 tenant 也可能打爆特定資料路徑。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>一個熱門商品承接大部分查詢與庫存扣減。</li>
<li>一個大型直播間同時有大量觀眾接收訊息。</li>
<li>一個企業 tenant 的使用量遠高於其他 tenant。</li>
</ul>
<p>這類評估的陷阱是只做整體水平擴展。hot key 可能需要資料拆分、<a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic</a> 分層、快取策略、讀寫分離、限流或產品層降級；具體做法要等需求形狀確認後再進入服務細節。</p>
<h2 id="判讀資料成長與保留期限決定長期成本">【判讀】資料成長與保留期限決定長期成本</h2>
<p>資料成長評估的核心問題是「今天可用的設計，三個月後是否仍可用」。row、event、log、<a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a>、object、index 都會成長；不同資料還有不同查詢頻率與保留需求。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>每天新增一百萬筆行為事件，但只查最近七天即時聚合。</li>
<li>每天新增十萬筆付款紀錄，法規要求保存多年。</li>
<li>每天產生大量 debug log，但事故排查主要看最近兩週。</li>
</ul>
<p>這類評估的陷阱是把所有資料都放進同一個保存策略。正式狀態、audit、分析事件、debug log、trace、使用者上傳檔案需要不同保留期限、查詢方式與封存策略。</p>
<h2 id="判讀查詢範圍決定索引與讀取模型">【判讀】查詢範圍決定索引與讀取模型</h2>
<p>查詢範圍的核心問題是「使用者或系統實際會怎麼找資料」。查最近十筆、查單一 ID、查某個 tenant、查全文、查任意時間範圍與查聚合報表，需要不同資料模型。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>後台訂單頁主要查單一訂單與最近訂單。</li>
<li>客服系統需要依 email、電話、交易 ID 找到使用者。</li>
<li>分析頁需要依時間、地區、產品線聚合趨勢。</li>
</ul>
<p>這類評估的陷阱是把所有查詢都塞進正式資料庫的單一模型。當查詢體驗、聚合方式或資料保留策略不同時，可能需要 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a>、<a href="/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">search index</a>、analytics pipeline 或 archive，但這些都應來自明確查詢需求。</p>
<h2 id="檢查進入實作前的概念邊界清單">【檢查】進入實作前的概念邊界清單</h2>
<p>當以下問題都能回答時，代表本章的概念層已完成，可以進入容量與成本實作章節：</p>
<ol>
<li>流量形狀是否明確（平均、尖峰、burst、批次）</li>
<li>主要壓力來源是否明確（讀寫比例、hot key、查詢範圍）</li>
<li>成長假設是否明確（資料新增速度、保留期限、查詢頻率）</li>
<li>容量保護策略是否明確（backpressure、rate limit、<a href="/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">降級</a>）</li>
</ol>
<p>下一步建議路由：</p>
<ul>
<li><a href="/blog/backend/09-performance-capacity/scaling-axes/" data-link-title="9.13 擴展軸與 Stateless 前提" data-link-desc="整理垂直 / 水平擴展取捨、stateless vs stateful 前提、auto scaling 操作模型與兩種擴展的 hidden cost">9.13 擴展軸與 Stateless 前提</a>（流量壓力出來後、選擴展軸）</li>
<li><a href="/blog/backend/05-deployment-platform/edge-cdn-static-distribution/" data-link-title="5.9 邊緣分發與靜態資源（CDN / Origin Protection）" data-link-desc="整理 CDN 與 edge cache 在部署平台中的責任邊界、origin protection、purge 與 invalidation 策略">5.9 邊緣分發與靜態資源</a>（讀峰值的第一層緩衝）</li>
<li><a href="/blog/backend/02-cache-redis/" data-link-title="模組二：快取與 Redis" data-link-desc="整理快取策略、Redis 資料型別與分散式狀態輔助能力">02-cache-redis</a></li>
<li><a href="/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">03-message-queue</a></li>
<li><a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">06-reliability</a></li>
</ul>
<h2 id="小結">小結</h2>
<p>流量與資料量評估要描述壓力形狀。平均流量估算基礎容量，尖峰流量決定緩衝與降級，讀寫比例影響資料路徑，hot key 會讓平均值失真，資料成長與保留期限決定長期成本，查詢範圍決定索引與讀取模型。這些資訊補齊後，服務選型才會有可靠依據。</p>
]]></content:encoded></item><item><title>0.6 成本、風險與選型取捨</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/</guid><description>&lt;p>成本與風險取捨的核心原則是把選型看成長期承諾。每加入一種後端服務能力，都會帶來雲端費用、人力維護、操作流程、事故風險與學習成本；它也可能降低延遲、失敗代價、開發摩擦與未來重構成本。&lt;/p>
&lt;p>這一章的內容是所有 Backend 服務實體章節的共同段落要求。後續討論 PostgreSQL、Redis、RabbitMQ、Kafka、Prometheus、Kubernetes、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/waf/" data-link-title="WAF" data-link-desc="說明 Web Application Firewall 如何在入口層過濾常見攻擊與濫用">WAF&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/iam/" data-link-title="IAM" data-link-desc="說明 identity and access management 如何集中管理身分、角色與權限">IAM&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management&lt;/a> 或任何具體服務時，都要回到同一組問題：資安限制會增加什麼成本，流量與穩定性會造成什麼壓力，伺服器與雲端費用如何成長，團隊要承擔多少操作成本，選擇這個方案會放棄哪些替代路線。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>區分建置成本、使用成本、操作成本與失敗代價&lt;/li>
&lt;li>用產品後果評估資料遺失、重複、延遲與停機風險&lt;/li>
&lt;li>判斷何時先用簡單設計，何時需要提前補能力&lt;/li>
&lt;li>把成本討論轉成可比較的選型問題&lt;/li>
&lt;li>在每個服務實體章節保留固定的成本與機會成本討論&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="觀察後端選型同時改變成本與風險">【觀察】後端選型同時改變成本與風險&lt;/h2>
&lt;p>選型取捨的第一個問題是「這個能力降低哪種風險，又增加哪種成本」。資料庫、快取、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a>、觀測平台、部署平台與可靠性流程都能提升能力，但它們也會增加操作面積。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>取捨面向&lt;/th>
 &lt;th>要回答的問題&lt;/th>
 &lt;th>常見例子&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>建置成本&lt;/td>
 &lt;td>開發與導入要花多少時間&lt;/td>
 &lt;td>schema、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/repository-adapter/" data-link-title="Repository Adapter" data-link-desc="說明持久化層如何把資料模型轉成外部儲存介面">Repository Adapter&lt;/a>、pipeline、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>使用成本&lt;/td>
 &lt;td>流量與資料量帶來多少費用&lt;/td>
 &lt;td>storage、egress、request、compute&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>操作成本&lt;/td>
 &lt;td>誰負責維護、升級、排障&lt;/td>
 &lt;td>backup、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert&lt;/a>、權限、容量規劃&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>失敗代價&lt;/td>
 &lt;td>延遲、遺失、重複、停機造成什麼後果&lt;/td>
 &lt;td>付款錯誤、通知延遲、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-inconsistency/" data-link-title="Data Inconsistency" data-link-desc="說明多份資料暫時不同步時如何判斷產品後果與修復責任">資料不一致&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>機會成本&lt;/td>
 &lt;td>導入這項能力會延後哪些產品工作&lt;/td>
 &lt;td>平台建設、功能交付、技術債&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>資安成本&lt;/td>
 &lt;td>權限、遮罩、加密、稽核與防護帶來多少額外責任&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/iam/" data-link-title="IAM" data-link-desc="說明 identity and access management 如何集中管理身分、角色與權限">IAM&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-masking/" data-link-title="Data Masking" data-link-desc="說明敏感資料如何在顯示、匯出、log 與測試資料中降低暴露">data masking&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表是成本索引。討論選型時，應把「技術是否強大」轉成「它是否值得目前承擔」。&lt;/p>
&lt;h2 id="判讀資安限制會改變成本模型">【判讀】資安限制會改變成本模型&lt;/h2>
&lt;p>資安成本的核心問題是「安全要求會讓原本的服務選型增加哪些責任」。同一個資料庫、cache、queue 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage&lt;/a>，在沒有敏感資料與有個資、金流、企業權限、稽核要求時，成本模型完全不同。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>匯出報表若包含個資，系統需要欄位遮罩、核准流程、下載期限、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log&lt;/a> 與存取權限。&lt;/li>
&lt;li>內部 service-to-service 呼叫若傳遞付款資料，可能需要 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">mTLS&lt;/a>、signed request、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">credential&lt;/a> rotation 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace&lt;/a> 關聯。&lt;/li>
&lt;li>客服查詢後台若能看到敏感資料，權限分級、操作稽核與資料最小揭露會成為必要成本。&lt;/li>
&lt;/ul>
&lt;p>這類取捨的核心風險是低估安全需求對操作面的影響。資安限制會增加設計、測試、稽核、教育訓練與事故處理成本；它也會降低資料外洩、權限誤用與合規事故的風險。服務章節討論選型時，必須把這兩邊一起列出。&lt;/p>
&lt;h2 id="判讀建置成本要和需求成熟度一起看">【判讀】建置成本要和需求成熟度一起看&lt;/h2>
&lt;p>建置成本的核心問題是「需求是否穩定到值得建立能力」。需求仍在探索時，過度完整的平台能力會讓修改變慢；需求已經穩定且失敗代價高時，缺少能力會讓事故與重工成本上升。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>新功能只有少量 beta 使用者，先用簡單資料模型與明確 interface 保留替換空間。&lt;/li>
&lt;li>付款流程已是正式收入來源，狀態一致性、audit、告警與回歸測試需要提前補上。&lt;/li>
&lt;li>內部報表先用每日批次匯出即可，等查詢需求穩定後再討論更完整分析平台。&lt;/li>
&lt;/ul>
&lt;p>這類取捨的陷阱是把「未來可能需要」當成現在必須導入。比較穩定的做法是先定義 interface、資料責任與測試合約，等需求成熟或風險升高，再引入具體服務能力。&lt;/p>
&lt;h2 id="判讀使用成本要看成長曲線">【判讀】使用成本要看成長曲線&lt;/h2>
&lt;p>本章的成本取捨發生在自建世界內；更早一層的成本交叉 — 託管平台月費加抽成、對上自建的工程薪資加雲端帳單 — 屬於交付形態的判斷、見 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型&lt;/a>。&lt;/p>
&lt;p>使用成本的核心問題是「流量與資料量成長後，費用如何變化」。儲存、查詢、訊息傳遞、log、trace、egress、compute 都可能隨使用量成長。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>debug log 在小流量時成本很低，流量變大後集中式 log 費用快速增加。&lt;/li>
&lt;li>trace 全量採樣對低流量服務很方便，高流量後需要採樣與欄位控制。&lt;/li>
&lt;li>長期保存大量事件可以支援 audit，但保留期限會直接影響 storage 與查詢成本。&lt;/li>
&lt;/ul>
&lt;p>這類取捨的陷阱是只看當月帳單。成本評估要看資料保留期限、查詢頻率、尖峰流量、跨區傳輸與成長速度，並把成本上限轉成明確策略。&lt;/p>
&lt;h2 id="判讀操作成本要看團隊能否承擔">【判讀】操作成本要看團隊能否承擔&lt;/h2>
&lt;p>操作成本的核心問題是「導入後誰能維護」。一項服務能力上線後，需要監控、備份、升級、權限、容量規劃、事故處理與文件。團隊若缺少操作能力，技術本身再合適也會變成風險。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>團隊導入多種 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a> 後，需要同步建立 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">dead-letter&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook&lt;/a>。&lt;/li>
&lt;li>服務開始使用多個快取層後，需要同步建立 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">失效策略&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-inconsistency/" data-link-title="Data Inconsistency" data-link-desc="說明多份資料暫時不同步時如何判斷產品後果與修復責任">資料不一致&lt;/a> 的排查方式。&lt;/li>
&lt;li>部署平台支援自動擴容後，application 需要提供 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/graceful-shutdown/" data-link-title="Graceful Shutdown" data-link-desc="說明服務停止前如何排空流量、完成工作與保存狀態">graceful shutdown&lt;/a> 合約。&lt;/li>
&lt;/ul>
&lt;p>這類取捨的陷阱是只計算開發時間。操作成本常在上線後才出現，因此選型時要把 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a>、告警、權限、備份、回復與測試環境列入範圍。&lt;/p></description><content:encoded><![CDATA[<p>成本與風險取捨的核心原則是把選型看成長期承諾。每加入一種後端服務能力，都會帶來雲端費用、人力維護、操作流程、事故風險與學習成本；它也可能降低延遲、失敗代價、開發摩擦與未來重構成本。</p>
<p>這一章的內容是所有 Backend 服務實體章節的共同段落要求。後續討論 PostgreSQL、Redis、RabbitMQ、Kafka、Prometheus、Kubernetes、<a href="/blog/backend/knowledge-cards/waf/" data-link-title="WAF" data-link-desc="說明 Web Application Firewall 如何在入口層過濾常見攻擊與濫用">WAF</a>、<a href="/blog/backend/knowledge-cards/iam/" data-link-title="IAM" data-link-desc="說明 identity and access management 如何集中管理身分、角色與權限">IAM</a>、<a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> 或任何具體服務時，都要回到同一組問題：資安限制會增加什麼成本，流量與穩定性會造成什麼壓力，伺服器與雲端費用如何成長，團隊要承擔多少操作成本，選擇這個方案會放棄哪些替代路線。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>區分建置成本、使用成本、操作成本與失敗代價</li>
<li>用產品後果評估資料遺失、重複、延遲與停機風險</li>
<li>判斷何時先用簡單設計，何時需要提前補能力</li>
<li>把成本討論轉成可比較的選型問題</li>
<li>在每個服務實體章節保留固定的成本與機會成本討論</li>
</ol>
<hr>
<h2 id="觀察後端選型同時改變成本與風險">【觀察】後端選型同時改變成本與風險</h2>
<p>選型取捨的第一個問題是「這個能力降低哪種風險，又增加哪種成本」。資料庫、快取、<a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a>、觀測平台、部署平台與可靠性流程都能提升能力，但它們也會增加操作面積。</p>
<table>
  <thead>
      <tr>
          <th>取捨面向</th>
          <th>要回答的問題</th>
          <th>常見例子</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>建置成本</td>
          <td>開發與導入要花多少時間</td>
          <td>schema、<a href="/blog/backend/knowledge-cards/repository-adapter/" data-link-title="Repository Adapter" data-link-desc="說明持久化層如何把資料模型轉成外部儲存介面">Repository Adapter</a>、pipeline、<a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a></td>
      </tr>
      <tr>
          <td>使用成本</td>
          <td>流量與資料量帶來多少費用</td>
          <td>storage、egress、request、compute</td>
      </tr>
      <tr>
          <td>操作成本</td>
          <td>誰負責維護、升級、排障</td>
          <td>backup、<a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>、權限、容量規劃</td>
      </tr>
      <tr>
          <td>失敗代價</td>
          <td>延遲、遺失、重複、停機造成什麼後果</td>
          <td>付款錯誤、通知延遲、<a href="/blog/backend/knowledge-cards/data-inconsistency/" data-link-title="Data Inconsistency" data-link-desc="說明多份資料暫時不同步時如何判斷產品後果與修復責任">資料不一致</a></td>
      </tr>
      <tr>
          <td>機會成本</td>
          <td>導入這項能力會延後哪些產品工作</td>
          <td>平台建設、功能交付、技術債</td>
      </tr>
      <tr>
          <td>資安成本</td>
          <td>權限、遮罩、加密、稽核與防護帶來多少額外責任</td>
          <td><a href="/blog/backend/knowledge-cards/iam/" data-link-title="IAM" data-link-desc="說明 identity and access management 如何集中管理身分、角色與權限">IAM</a>、<a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS</a>、<a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a>、<a href="/blog/backend/knowledge-cards/data-masking/" data-link-title="Data Masking" data-link-desc="說明敏感資料如何在顯示、匯出、log 與測試資料中降低暴露">data masking</a></td>
      </tr>
  </tbody>
</table>
<p>這張表是成本索引。討論選型時，應把「技術是否強大」轉成「它是否值得目前承擔」。</p>
<h2 id="判讀資安限制會改變成本模型">【判讀】資安限制會改變成本模型</h2>
<p>資安成本的核心問題是「安全要求會讓原本的服務選型增加哪些責任」。同一個資料庫、cache、queue 或 <a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage</a>，在沒有敏感資料與有個資、金流、企業權限、稽核要求時，成本模型完全不同。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>匯出報表若包含個資，系統需要欄位遮罩、核准流程、下載期限、<a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a> 與存取權限。</li>
<li>內部 service-to-service 呼叫若傳遞付款資料，可能需要 <a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">mTLS</a>、signed request、<a href="/blog/backend/knowledge-cards/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">credential</a> rotation 與 <a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a> 關聯。</li>
<li>客服查詢後台若能看到敏感資料，權限分級、操作稽核與資料最小揭露會成為必要成本。</li>
</ul>
<p>這類取捨的核心風險是低估安全需求對操作面的影響。資安限制會增加設計、測試、稽核、教育訓練與事故處理成本；它也會降低資料外洩、權限誤用與合規事故的風險。服務章節討論選型時，必須把這兩邊一起列出。</p>
<h2 id="判讀建置成本要和需求成熟度一起看">【判讀】建置成本要和需求成熟度一起看</h2>
<p>建置成本的核心問題是「需求是否穩定到值得建立能力」。需求仍在探索時，過度完整的平台能力會讓修改變慢；需求已經穩定且失敗代價高時，缺少能力會讓事故與重工成本上升。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>新功能只有少量 beta 使用者，先用簡單資料模型與明確 interface 保留替換空間。</li>
<li>付款流程已是正式收入來源，狀態一致性、audit、告警與回歸測試需要提前補上。</li>
<li>內部報表先用每日批次匯出即可，等查詢需求穩定後再討論更完整分析平台。</li>
</ul>
<p>這類取捨的陷阱是把「未來可能需要」當成現在必須導入。比較穩定的做法是先定義 interface、資料責任與測試合約，等需求成熟或風險升高，再引入具體服務能力。</p>
<h2 id="判讀使用成本要看成長曲線">【判讀】使用成本要看成長曲線</h2>
<p>本章的成本取捨發生在自建世界內；更早一層的成本交叉 — 託管平台月費加抽成、對上自建的工程薪資加雲端帳單 — 屬於交付形態的判斷、見 <a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型</a>。</p>
<p>使用成本的核心問題是「流量與資料量成長後，費用如何變化」。儲存、查詢、訊息傳遞、log、trace、egress、compute 都可能隨使用量成長。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>debug log 在小流量時成本很低，流量變大後集中式 log 費用快速增加。</li>
<li>trace 全量採樣對低流量服務很方便，高流量後需要採樣與欄位控制。</li>
<li>長期保存大量事件可以支援 audit，但保留期限會直接影響 storage 與查詢成本。</li>
</ul>
<p>這類取捨的陷阱是只看當月帳單。成本評估要看資料保留期限、查詢頻率、尖峰流量、跨區傳輸與成長速度，並把成本上限轉成明確策略。</p>
<h2 id="判讀操作成本要看團隊能否承擔">【判讀】操作成本要看團隊能否承擔</h2>
<p>操作成本的核心問題是「導入後誰能維護」。一項服務能力上線後，需要監控、備份、升級、權限、容量規劃、事故處理與文件。團隊若缺少操作能力，技術本身再合適也會變成風險。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>團隊導入多種 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> 後，需要同步建立 <a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag</a>、<a href="/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">dead-letter</a> 與 <a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook</a>。</li>
<li>服務開始使用多個快取層後，需要同步建立 <a href="/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">失效策略</a> 與 <a href="/blog/backend/knowledge-cards/data-inconsistency/" data-link-title="Data Inconsistency" data-link-desc="說明多份資料暫時不同步時如何判斷產品後果與修復責任">資料不一致</a> 的排查方式。</li>
<li>部署平台支援自動擴容後，application 需要提供 <a href="/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness</a> 與 <a href="/blog/backend/knowledge-cards/graceful-shutdown/" data-link-title="Graceful Shutdown" data-link-desc="說明服務停止前如何排空流量、完成工作與保存狀態">graceful shutdown</a> 合約。</li>
</ul>
<p>這類取捨的陷阱是只計算開發時間。操作成本常在上線後才出現，因此選型時要把 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a>、告警、權限、備份、回復與測試環境列入範圍。</p>
<h2 id="判讀失敗代價決定保證等級">【判讀】失敗代價決定保證等級</h2>
<p>失敗代價的核心問題是「錯誤發生時產品後果是什麼」。資料遺失、<a href="/blog/backend/knowledge-cards/duplicate-delivery/" data-link-title="Duplicate Delivery" data-link-desc="說明同一個訊息被處理多次時如何保持結果穩定">重複投遞</a>、短暫不一致、延遲、<a href="/blog/backend/knowledge-cards/partial-failure/" data-link-title="Partial Failure" data-link-desc="說明分散式系統中部分依賴失效時如何保留整體可用性">partial failure</a>、<a href="/blog/backend/knowledge-cards/cascading-failure/" data-link-title="Cascading Failure" data-link-desc="說明局部故障如何透過等待、重試與資源耗盡擴散到整個系統">cascading failure</a>、<a href="/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">降級</a>與<a href="/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">停機</a>的代價不同，對應的保證等級也不同。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>付款事件重複可能造成重複出貨或重複通知，因此 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a> 需要 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a>。</li>
<li>聊天 typing indicator 遺失通常可接受，正式訊息遺失則需要保存與補送。</li>
<li>商品價格短暫不一致可能造成客訴，庫存短暫不一致可能造成超賣。</li>
</ul>
<p>這類取捨的陷阱是追求所有資料都最高保證。高保證通常帶來更高延遲、成本與操作複雜度；合理設計會依資料語意分級，而非把所有訊息都放進同一種可靠性模型。</p>
<h2 id="判讀機會成本決定投入順序">【判讀】機會成本決定投入順序</h2>
<p>機會成本的核心問題是「做這件事會延後什麼」。後端能力建設很容易變成長期平台工程；它可能值得，也可能讓產品驗證變慢。投入順序要跟風險、成長與團隊能力對齊。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>產品仍在找市場定位時，先用清楚邊界保留替換空間，比導入完整事件平台更實際。</li>
<li>服務已經有穩定收入且事故頻繁時，補 observability、<a href="/blog/backend/knowledge-cards/deployment-contract/" data-link-title="Deployment Contract" data-link-desc="說明服務與部署平台之間的生命週期約定">Deployment Contract</a> 與 reliability pipeline 會直接降低業務風險。</li>
<li>流量即將進入大型活動前，先做 <a href="/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">load test</a>、容量預估與降級策略，比重構所有資料層更有時效。</li>
</ul>
<p>這類取捨的陷阱是把架構完整度當成目標。選型應回答目前最需要降低哪個風險，並設計能回頭修正的邊界。</p>
<h2 id="檢查進入實作前的概念邊界清單">【檢查】進入實作前的概念邊界清單</h2>
<p>當以下問題都能回答時，代表本章的概念層已完成，可以進入具體服務取捨與落地章節：</p>
<ol>
<li>成本維度是否完整（建置、使用、操作、資安、機會成本）</li>
<li>失敗代價是否分級（遺失、重複、延遲、<a href="/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">停機</a>）</li>
<li>團隊可承擔的操作責任是否明確（runbook、告警、備份、回復）</li>
<li>何時重評選型的條件是否明確（流量、法規、事故頻率）</li>
</ol>
<p>下一步建議路由：</p>
<ul>
<li><a href="/blog/backend/01-database/" data-link-title="模組一：資料庫與持久化" data-link-desc="整理 SQL、transaction、migration 與 repository adapter 的後端實務">01-database</a></li>
<li><a href="/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">03-message-queue</a></li>
<li><a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07-security-data-protection</a></li>
</ul>
<h2 id="小結">小結</h2>
<p>後端服務選型要同時看成本與風險。建置成本要看需求成熟度，使用成本要看成長曲線，操作成本要看團隊能否承擔，失敗代價決定保證等級，機會成本決定投入順序。這些取捨清楚後，後續討論具體服務才會有共同標準。</p>
]]></content:encoded></item><item><title>0.7 錯誤定位、觀測訊號與備援切換設計</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/failure-observability-design/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/failure-observability-design/</guid><description>&lt;p>服務可維護性的核心原則是把失敗設計成可分類、可定位、可降級、可恢復的狀態。穩定性表示服務在正常情況下能持續運行；可觀測性與備援設計則決定失敗發生時，團隊能否快速知道發生什麼、影響誰、如何降低傷害，以及如何切換到可用路徑。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>從需求面定義錯誤分類與定位線索&lt;/li>
&lt;li>判斷哪些錯誤需要對外回應、對內記錄、對平台告警&lt;/li>
&lt;li>設計可降級、可重試、可切換的服務行為&lt;/li>
&lt;li>把錯誤定位與備援需求連到 observability、deployment 與 reliability 模組&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="觀察錯誤設計是服務合約的一部分">【觀察】錯誤設計是服務合約的一部分&lt;/h2>
&lt;p>錯誤設計的核心問題是「失敗時系統要留下什麼線索，並給誰什麼動作」。API response、domain error、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&lt;/a>、metric、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert&lt;/a>、retry、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">fallback&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">failover&lt;/a> 都是錯誤合約的一部分。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>設計面向&lt;/th>
 &lt;th>要回答的問題&lt;/th>
 &lt;th>常見產出&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>錯誤分類&lt;/td>
 &lt;td>這是輸入錯誤、權限錯誤、狀態衝突、下游失敗，還是系統故障&lt;/td>
 &lt;td>error code、status、reason&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>定位線索&lt;/td>
 &lt;td>工程師如何找到 request、使用者、資源、下游與版本&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace-id/" data-link-title="Trace ID" data-link-desc="說明分散式追蹤中同一條呼叫路徑的識別碼">trace id&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/request-id/" data-link-title="Request ID" data-link-desc="說明單次 request 的識別碼如何支援 log 搜尋與問題定位">request id&lt;/a>、subject id、dependency&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>對外回應&lt;/td>
 &lt;td>呼叫者能否理解下一步動作&lt;/td>
 &lt;td>stable error response、retry hint&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>操作訊號&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call&lt;/a> 如何知道影響範圍與嚴重度&lt;/td>
 &lt;td>log、metric、alert、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>降級策略&lt;/td>
 &lt;td>主要路徑失敗時能否提供較低能力服務&lt;/td>
 &lt;td>fallback、cache、read-only、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a> later&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>切換策略&lt;/td>
 &lt;td>依賴或節點失效時能否轉到其他路徑&lt;/td>
 &lt;td>failover、traffic shift、draining&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表是設計索引。錯誤定位與備援切換應在服務設計時討論，而非等事故後才補欄位。&lt;/p>
&lt;h2 id="判讀錯誤分類要服務呼叫者與維護者">【判讀】錯誤分類要服務呼叫者與維護者&lt;/h2>
&lt;p>錯誤分類的核心責任是讓不同角色知道下一步。呼叫者需要知道是否能修正輸入、稍後重試或停止操作；維護者需要知道錯誤來自程式規則、資料狀態、外部依賴、容量瓶頸或平台問題。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>使用者建立訂單時庫存不足，對外 response 要表達「目前狀態不允許」，對內 log 要能定位商品與庫存版本。&lt;/li>
&lt;li>付款 API &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout&lt;/a>，對外 response 要避免承諾付款結果，對內訊號要標出 payment provider、timeout duration 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">retry policy&lt;/a>。&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">Webhook&lt;/a> payload 格式錯誤，對外要回穩定錯誤碼，對內要記錄 schema version 與來源系統。&lt;/li>
&lt;/ul>
&lt;p>這類設計的陷阱是只留下自由文字錯誤。自由文字適合人快速閱讀，但分類、查詢、告警與統計需要穩定欄位。錯誤分類要同時支援 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/api-contract/" data-link-title="API Contract" data-link-desc="說明 request / response 邊界如何維持相容與可驗證">API Contract&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">log schema&lt;/a>、metric label 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a>。&lt;/p>
&lt;p>下一步可讀：&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">操作平台選型&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台&lt;/a>。&lt;/p>
&lt;h2 id="判讀定位線索要沿著-request-與事件流傳遞">【判讀】定位線索要沿著 request 與事件流傳遞&lt;/h2>
&lt;p>定位線索的核心責任是讓工程師能把一個症狀追回完整路徑。當 request 跨過 API、資料庫、cache、queue、worker、外部服務與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/websocket/" data-link-title="WebSocket" data-link-desc="說明 WebSocket 如何提供長連線雙向即時通訊">WebSocket&lt;/a> 推送時，線索需要跟著邊界傳遞。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>checkout 變慢時，需要知道同一個 trace 經過 cart、payment、inventory 與 shipping 的哪一段。&lt;/li>
&lt;li>queue message 重試時，需要知道原始 request、event id、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer&lt;/a>、attempt count 與最後錯誤。&lt;/li>
&lt;li>即時通知漏送時，需要知道 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic&lt;/a>、client id、connection id、server instance 與 publish path。&lt;/li>
&lt;/ul>
&lt;p>這類設計的陷阱是每個元件各自產生無關 ID。request id、trace id、event id、subject id 與 dependency name 要有清楚用途，並在跨服務、跨 queue、跨 worker 時保留關聯。&lt;/p></description><content:encoded><![CDATA[<p>服務可維護性的核心原則是把失敗設計成可分類、可定位、可降級、可恢復的狀態。穩定性表示服務在正常情況下能持續運行；可觀測性與備援設計則決定失敗發生時，團隊能否快速知道發生什麼、影響誰、如何降低傷害，以及如何切換到可用路徑。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>從需求面定義錯誤分類與定位線索</li>
<li>判斷哪些錯誤需要對外回應、對內記錄、對平台告警</li>
<li>設計可降級、可重試、可切換的服務行為</li>
<li>把錯誤定位與備援需求連到 observability、deployment 與 reliability 模組</li>
</ol>
<hr>
<h2 id="觀察錯誤設計是服務合約的一部分">【觀察】錯誤設計是服務合約的一部分</h2>
<p>錯誤設計的核心問題是「失敗時系統要留下什麼線索，並給誰什麼動作」。API response、domain error、<a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a>、metric、<a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a>、<a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>、retry、<a href="/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">fallback</a> 與 <a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">failover</a> 都是錯誤合約的一部分。</p>
<table>
  <thead>
      <tr>
          <th>設計面向</th>
          <th>要回答的問題</th>
          <th>常見產出</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>錯誤分類</td>
          <td>這是輸入錯誤、權限錯誤、狀態衝突、下游失敗，還是系統故障</td>
          <td>error code、status、reason</td>
      </tr>
      <tr>
          <td>定位線索</td>
          <td>工程師如何找到 request、使用者、資源、下游與版本</td>
          <td><a href="/blog/backend/knowledge-cards/trace-id/" data-link-title="Trace ID" data-link-desc="說明分散式追蹤中同一條呼叫路徑的識別碼">trace id</a>、<a href="/blog/backend/knowledge-cards/request-id/" data-link-title="Request ID" data-link-desc="說明單次 request 的識別碼如何支援 log 搜尋與問題定位">request id</a>、subject id、dependency</td>
      </tr>
      <tr>
          <td>對外回應</td>
          <td>呼叫者能否理解下一步動作</td>
          <td>stable error response、retry hint</td>
      </tr>
      <tr>
          <td>操作訊號</td>
          <td><a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a> 如何知道影響範圍與嚴重度</td>
          <td>log、metric、alert、<a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a></td>
      </tr>
      <tr>
          <td>降級策略</td>
          <td>主要路徑失敗時能否提供較低能力服務</td>
          <td>fallback、cache、read-only、<a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a> later</td>
      </tr>
      <tr>
          <td>切換策略</td>
          <td>依賴或節點失效時能否轉到其他路徑</td>
          <td>failover、traffic shift、draining</td>
      </tr>
  </tbody>
</table>
<p>這張表是設計索引。錯誤定位與備援切換應在服務設計時討論，而非等事故後才補欄位。</p>
<h2 id="判讀錯誤分類要服務呼叫者與維護者">【判讀】錯誤分類要服務呼叫者與維護者</h2>
<p>錯誤分類的核心責任是讓不同角色知道下一步。呼叫者需要知道是否能修正輸入、稍後重試或停止操作；維護者需要知道錯誤來自程式規則、資料狀態、外部依賴、容量瓶頸或平台問題。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>使用者建立訂單時庫存不足，對外 response 要表達「目前狀態不允許」，對內 log 要能定位商品與庫存版本。</li>
<li>付款 API <a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout</a>，對外 response 要避免承諾付款結果，對內訊號要標出 payment provider、timeout duration 與 <a href="/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">retry policy</a>。</li>
<li><a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">Webhook</a> payload 格式錯誤，對外要回穩定錯誤碼，對內要記錄 schema version 與來源系統。</li>
</ul>
<p>這類設計的陷阱是只留下自由文字錯誤。自由文字適合人快速閱讀，但分類、查詢、告警與統計需要穩定欄位。錯誤分類要同時支援 <a href="/blog/backend/knowledge-cards/api-contract/" data-link-title="API Contract" data-link-desc="說明 request / response 邊界如何維持相容與可驗證">API Contract</a>、<a href="/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">log schema</a>、metric label 與 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a>。</p>
<p>下一步可讀：<a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">操作平台選型</a> 與 <a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台</a>。</p>
<h2 id="判讀定位線索要沿著-request-與事件流傳遞">【判讀】定位線索要沿著 request 與事件流傳遞</h2>
<p>定位線索的核心責任是讓工程師能把一個症狀追回完整路徑。當 request 跨過 API、資料庫、cache、queue、worker、外部服務與 <a href="/blog/backend/knowledge-cards/websocket/" data-link-title="WebSocket" data-link-desc="說明 WebSocket 如何提供長連線雙向即時通訊">WebSocket</a> 推送時，線索需要跟著邊界傳遞。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>checkout 變慢時，需要知道同一個 trace 經過 cart、payment、inventory 與 shipping 的哪一段。</li>
<li>queue message 重試時，需要知道原始 request、event id、<a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a>、attempt count 與最後錯誤。</li>
<li>即時通知漏送時，需要知道 <a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic</a>、client id、connection id、server instance 與 publish path。</li>
</ul>
<p>這類設計的陷阱是每個元件各自產生無關 ID。request id、trace id、event id、subject id 與 dependency name 要有清楚用途，並在跨服務、跨 queue、跨 worker 時保留關聯。</p>
<p>下一步可讀：<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台</a>。</p>
<h2 id="判讀對外錯誤要穩定對內錯誤要可診斷">【判讀】對外錯誤要穩定，對內錯誤要可診斷</h2>
<p>對外錯誤的核心責任是讓呼叫者知道可採取的動作；對內錯誤的核心責任是讓工程師定位原因。兩者可以關聯，但承擔不同責任。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>對外回 <code>payment_pending</code>，讓 client 顯示等待確認；對內保留 provider timeout、request payload hash、attempt count。</li>
<li>對外回 <code>rate_limited</code>，讓 client 根據 retry hint 延後；對內記錄 tenant、limit rule、current usage。</li>
<li>對外回 <code>resource_conflict</code>，讓使用者刷新狀態；對內記錄 expected version 與 actual version。</li>
</ul>
<p>這類設計的陷阱是把內部錯誤直接暴露給 client，或把對外訊息當成唯一診斷資料。對外錯誤要穩定、安全、可被產品處理；對內錯誤要保留足夠脈絡、可查詢、可關聯。</p>
<p>下一步可讀：<a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">操作平台選型</a>。</p>
<h2 id="判讀降級策略要依資料語意分級">【判讀】降級策略要依資料語意分級</h2>
<p>降級策略的核心問題是「主要能力失效時，哪些功能仍可提供」。降級可以是回舊資料、只讀模式、排隊稍後處理、停用非核心功能、限制流量或切換較慢但可靠的路徑。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>推薦服務失效時，首頁可以回熱門商品或預先產生的榜單。</li>
<li>Email provider 暫時失敗時，通知工作可以進 queue 稍後重試。</li>
<li>搜尋服務延遲升高時，後台可以先提供精確 ID 查詢，暫停全文搜尋。</li>
</ul>
<p>這類設計的陷阱是所有功能共用同一種失敗行為。付款、訊息、搜尋、推薦、通知與報表的失敗代價不同；降級策略要依資料是否可丟、是否可延遲、是否可重建、是否涉及金流或稽核分級。</p>
<p>下一步可讀：<a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">成本、風險與選型取捨</a>。</p>
<h2 id="判讀備援切換要先定義切換條件">【判讀】備援切換要先定義切換條件</h2>
<p>備援切換的核心責任是讓系統在依賴、節點或區域失效時轉到可用路徑。切換可以發生在 client、<a href="/blog/backend/knowledge-cards/load-balancer/" data-link-title="Load Balancer" data-link-desc="說明流量如何分散、排空與導向健康節點">load balancer</a>、<a href="/blog/backend/knowledge-cards/service-registry/" data-link-title="Service Registry" data-link-desc="說明服務實例如何被註冊、維護與摘除">service registry</a>、<a href="/blog/backend/knowledge-cards/service-discovery/" data-link-title="Service Discovery" data-link-desc="說明服務實例如何被查找與路由">service discovery</a>、<a href="/blog/backend/knowledge-cards/adapter/" data-link-title="Integration Adapter" data-link-desc="說明外部系統接入層如何轉換介面與隔離差異">Integration Adapter</a>、queue consumer 或資料層；每一層都需要明確條件。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>外部付款 provider 連續 timeout 後，系統暫停建立新付款並保留待確認狀態。</li>
<li>某個 service instance <a href="/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness</a> 失敗後，<a href="/blog/backend/knowledge-cards/load-balancer/" data-link-title="Load Balancer" data-link-desc="說明流量如何分散、排空與導向健康節點">load balancer</a> 停止送新流量並進入 draining。</li>
<li>主要搜尋 cluster 延遲過高時，後台切到只讀快照或簡化查詢。</li>
</ul>
<p>這類設計的陷阱是把 failover 想成自動且無代價。切換可能造成重複請求、順序改變、資料短暫不一致、成本上升或排障複雜度增加。切換條件、回切條件、資料一致性與告警都要一起設計。</p>
<p>下一步可讀：<a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">部署平台與網路入口</a> 與 <a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">可靠性驗證流程</a>。</p>
<h2 id="判讀備援設計需要驗證流程">【判讀】備援設計需要驗證流程</h2>
<p>備援設計的核心完成標準是能被演練。文件中宣稱可以重試、<a href="/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">降級</a>、切換或回復，只代表設計意圖；可靠性驗證要證明這些路徑在接近真實條件下能運作。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>在預備環境讓 payment <a href="/blog/backend/knowledge-cards/provider-adapter/" data-link-title="Provider Adapter" data-link-desc="說明第三方服務如何被包裝成內部穩定介面">Provider Adapter</a> 回 timeout，驗證訂單狀態是否停在待確認。</li>
<li>在 <a href="/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">load test</a> 中提高 queue lag，驗證 dashboard、alert 與 consumer 擴容決策。</li>
<li>在 <a href="/blog/backend/knowledge-cards/chaos-test/" data-link-title="Chaos Test" data-link-desc="說明透過受控故障注入驗證系統在異常條件下的恢復能力">chaos test</a> 中讓 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> 暫時中斷，驗證 outbox、retry 與 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a>。</li>
</ul>
<p>這類設計的陷阱是只測成功路徑。錯誤分類、定位線索、降級策略與 failover 都應有對應測試、演練或 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a>，否則事故發生時才會知道設計缺口。</p>
<p>下一步可讀：<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">可靠性驗證流程</a>。</p>
<h2 id="檢查進入實作前的概念邊界清單">【檢查】進入實作前的概念邊界清單</h2>
<p>當以下問題都能回答時，代表本章的概念層已完成，可以進入觀測與事故治理實作章節：</p>
<ol>
<li>錯誤分類是否可被查詢與統計（對外碼、對內欄位）</li>
<li>定位線索是否可跨邊界串接（request、trace、event）</li>
<li>降級與切換條件是否明確（觸發條件、回切條件）</li>
<li>演練與驗證入口是否明確（load、chaos、事故演練）</li>
</ol>
<p>下一步建議路由：</p>
<ul>
<li><a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">04-observability</a></li>
<li><a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">06-reliability</a></li>
<li><a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">08-incident-response</a></li>
</ul>
<h2 id="小結">小結</h2>
<p>可觀測性與備援設計要從服務需求開始。錯誤分類讓呼叫者與維護者知道下一步，定位線索讓症狀能追回路徑，對外與對內錯誤承擔不同責任，降級策略依資料語意分級，備援切換需要明確條件，可靠性驗證則確認這些設計能在失敗時運作。</p>
]]></content:encoded></item><item><title>0.8 資安與資料保護需求</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/security-data-protection-requirements/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/security-data-protection-requirements/</guid><description>&lt;p>資安需求分析的核心原則是先定義安全邊界，再選擇安全工具。權限分級、伺服器防護、資料匯出遮罩、傳輸加密、稽核紀錄與密鑰管理都服務同一個目標：讓資料與操作只在被授權、可追蹤、可控的路徑中流動。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>用資料分級與角色分級描述安全需求&lt;/li>
&lt;li>判斷服務入口、內部通訊與資料匯出需要哪些保護&lt;/li>
&lt;li>區分權限控制、資料遮罩、傳輸保護、伺服器防護與稽核需求&lt;/li>
&lt;li>把資安需求連到後續安全與資料保護模組&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="觀察資安需求來自資料角色與路徑">【觀察】資安需求來自資料、角色與路徑&lt;/h2>
&lt;p>資安設計的第一個問題是「誰在什麼路徑上接觸什麼資料」。同一個系統可能同時有使用者、客服、營運、工程師、背景 worker、外部合作方與管理員；每個角色需要的資料、操作與稽核等級都不同。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>需求類型&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見情境&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>權限分級&lt;/td>
 &lt;td>誰能看、改、匯出、審核或管理資料&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">authorization&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">tenant boundary&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>伺服器防護&lt;/td>
 &lt;td>哪些入口要限制來源、速率與攻擊面&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint&lt;/a>、upload、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/waf/" data-link-title="WAF" data-link-desc="說明 Web Application Firewall 如何在入口層過濾常見攻擊與濫用">WAF&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>資料遮罩&lt;/td>
 &lt;td>匯出、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&lt;/a>、客服畫面要顯示多少敏感資訊&lt;/td>
 &lt;td>email、電話、身分證、付款資訊&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>傳輸保護&lt;/td>
 &lt;td>資料在 client、service、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a>、storage 之間如何被保護&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS&lt;/a>、signed request、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-chain-trust/" data-link-title="Certificate Chain and Trust Root" data-link-desc="說明網站憑證鏈與信任根如何影響連線可用性與驗證結果">certificate chain and trust root&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>密鑰與秘密&lt;/td>
 &lt;td>token、API key、憑證如何保存、輪替與撤銷&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">Website Certificate Lifecycle&lt;/a>、key rotation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>稽核追蹤&lt;/td>
 &lt;td>高風險操作是否能被追蹤與事後審查&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log&lt;/a>、approval、admin action&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表是需求索引。資安討論要先定義資料與操作的保護等級，再決定具體平台、服務或產品。&lt;/p>
&lt;h2 id="判讀權限分級要從角色與資料責任開始">【判讀】權限分級要從角色與資料責任開始&lt;/h2>
&lt;p>權限分級的核心責任是控制角色能執行哪些操作。常見模型包括依角色授權、依屬性授權、依 tenant 隔離與依資源 owner 判斷；選型前要先定義資料責任與操作風險。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>客服可以查看訂單狀態與配送資訊，但付款敏感欄位只顯示遮罩版本。&lt;/li>
&lt;li>營運可以調整活動商品，但價格變更需要主管審核。&lt;/li>
&lt;li>企業 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">SaaS&lt;/a> 中，workspace admin 可以管理成員，普通 member 只能操作自己有權限的 project。&lt;/li>
&lt;/ul>
&lt;p>這類需求的陷阱是只用「是否登入」表示授權。登入代表身份已被確認；授權要回答這個身份能否操作特定資源、特定欄位與特定動作。權限規則也要能被測試、稽核與解釋。&lt;/p>
&lt;p>下一步可讀：&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界&lt;/a>。&lt;/p>
&lt;h2 id="判讀伺服器防護要先找暴露入口">【判讀】伺服器防護要先找暴露入口&lt;/h2>
&lt;p>伺服器防護的核心責任是降低服務入口的攻擊面。Public API、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook&lt;/a>、file upload、public asset、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/diagnostic-endpoint/" data-link-title="Diagnostic Endpoint" data-link-desc="說明健康檢查、診斷與調試入口如何控制暴露面">Diagnostic Endpoint&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/internal-endpoint/" data-link-title="Internal Endpoint" data-link-desc="說明服務內部通訊入口如何配合網路邊界與服務發現">Internal Endpoint&lt;/a> 都有不同暴露程度。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook&lt;/a> 需要驗證來源簽章、限制重放時間窗，並記錄來源系統。&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint&lt;/a> 需要更高權限、來源限制與操作稽核。&lt;/li>
&lt;li>file upload 需要限制大小、型別、掃描結果與後續存取權限。&lt;/li>
&lt;/ul>
&lt;p>這類需求的陷阱是把所有 HTTP 入口視為同一種入口。公開 API、內部 API、診斷 API、管理 API 與第三方 callback 的風險不同；防護策略要依入口用途分級。&lt;/p>
&lt;p>下一步可讀：&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">部署平台與網路入口&lt;/a>。&lt;/p>
&lt;h2 id="判讀資料遮罩要依使用情境分級">【判讀】資料遮罩要依使用情境分級&lt;/h2>
&lt;p>資料遮罩的核心責任是讓使用者完成工作，同時降低敏感資料暴露。遮罩可能發生在客服畫面、匯出報表、log、debug payload、analytics dataset、測試資料與外部分享檔案。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>客服查會員資料時，只顯示電話末三碼與 email 部分字元。&lt;/li>
&lt;li>匯出訂單報表時，付款識別碼保留交易對帳所需欄位，個資欄位轉為遮罩值。&lt;/li>
&lt;li>開發環境使用脫敏資料集，保留資料形狀與關聯，但移除真實身份資訊。&lt;/li>
&lt;/ul>
&lt;p>這類需求的陷阱是把遮罩視為顯示層問題。資料可能流入匯出、log、queue、搜尋索引、分析資料集與備份；遮罩策略要定義在資料流路徑上，而非只套在單一頁面。&lt;/p>
&lt;p>下一步可讀：&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>資安需求分析的核心原則是先定義安全邊界，再選擇安全工具。權限分級、伺服器防護、資料匯出遮罩、傳輸加密、稽核紀錄與密鑰管理都服務同一個目標：讓資料與操作只在被授權、可追蹤、可控的路徑中流動。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>用資料分級與角色分級描述安全需求</li>
<li>判斷服務入口、內部通訊與資料匯出需要哪些保護</li>
<li>區分權限控制、資料遮罩、傳輸保護、伺服器防護與稽核需求</li>
<li>把資安需求連到後續安全與資料保護模組</li>
</ol>
<hr>
<h2 id="觀察資安需求來自資料角色與路徑">【觀察】資安需求來自資料、角色與路徑</h2>
<p>資安設計的第一個問題是「誰在什麼路徑上接觸什麼資料」。同一個系統可能同時有使用者、客服、營運、工程師、背景 worker、外部合作方與管理員；每個角色需要的資料、操作與稽核等級都不同。</p>
<table>
  <thead>
      <tr>
          <th>需求類型</th>
          <th>核心問題</th>
          <th>常見情境</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>權限分級</td>
          <td>誰能看、改、匯出、審核或管理資料</td>
          <td><a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">authorization</a>、<a href="/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">tenant boundary</a></td>
      </tr>
      <tr>
          <td>伺服器防護</td>
          <td>哪些入口要限制來源、速率與攻擊面</td>
          <td><a href="/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint</a>、upload、<a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook</a>、<a href="/blog/backend/knowledge-cards/waf/" data-link-title="WAF" data-link-desc="說明 Web Application Firewall 如何在入口層過濾常見攻擊與濫用">WAF</a></td>
      </tr>
      <tr>
          <td>資料遮罩</td>
          <td>匯出、<a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a>、客服畫面要顯示多少敏感資訊</td>
          <td>email、電話、身分證、付款資訊</td>
      </tr>
      <tr>
          <td>傳輸保護</td>
          <td>資料在 client、service、<a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a>、storage 之間如何被保護</td>
          <td><a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS</a>、signed request、<a href="/blog/backend/knowledge-cards/certificate-chain-trust/" data-link-title="Certificate Chain and Trust Root" data-link-desc="說明網站憑證鏈與信任根如何影響連線可用性與驗證結果">certificate chain and trust root</a></td>
      </tr>
      <tr>
          <td>密鑰與秘密</td>
          <td>token、API key、憑證如何保存、輪替與撤銷</td>
          <td><a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a>、<a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">Website Certificate Lifecycle</a>、key rotation</td>
      </tr>
      <tr>
          <td>稽核追蹤</td>
          <td>高風險操作是否能被追蹤與事後審查</td>
          <td><a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a>、approval、admin action</td>
      </tr>
  </tbody>
</table>
<p>這張表是需求索引。資安討論要先定義資料與操作的保護等級，再決定具體平台、服務或產品。</p>
<h2 id="判讀權限分級要從角色與資料責任開始">【判讀】權限分級要從角色與資料責任開始</h2>
<p>權限分級的核心責任是控制角色能執行哪些操作。常見模型包括依角色授權、依屬性授權、依 tenant 隔離與依資源 owner 判斷；選型前要先定義資料責任與操作風險。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>客服可以查看訂單狀態與配送資訊，但付款敏感欄位只顯示遮罩版本。</li>
<li>營運可以調整活動商品，但價格變更需要主管審核。</li>
<li>企業 <a href="/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">SaaS</a> 中，workspace admin 可以管理成員，普通 member 只能操作自己有權限的 project。</li>
</ul>
<p>這類需求的陷阱是只用「是否登入」表示授權。登入代表身份已被確認；授權要回答這個身份能否操作特定資源、特定欄位與特定動作。權限規則也要能被測試、稽核與解釋。</p>
<p>下一步可讀：<a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a>。</p>
<h2 id="判讀伺服器防護要先找暴露入口">【判讀】伺服器防護要先找暴露入口</h2>
<p>伺服器防護的核心責任是降低服務入口的攻擊面。Public API、<a href="/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint</a>、<a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook</a>、file upload、public asset、<a href="/blog/backend/knowledge-cards/diagnostic-endpoint/" data-link-title="Diagnostic Endpoint" data-link-desc="說明健康檢查、診斷與調試入口如何控制暴露面">Diagnostic Endpoint</a> 與 <a href="/blog/backend/knowledge-cards/internal-endpoint/" data-link-title="Internal Endpoint" data-link-desc="說明服務內部通訊入口如何配合網路邊界與服務發現">Internal Endpoint</a> 都有不同暴露程度。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li><a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook</a> 需要驗證來源簽章、限制重放時間窗，並記錄來源系統。</li>
<li><a href="/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint</a> 需要更高權限、來源限制與操作稽核。</li>
<li>file upload 需要限制大小、型別、掃描結果與後續存取權限。</li>
</ul>
<p>這類需求的陷阱是把所有 HTTP 入口視為同一種入口。公開 API、內部 API、診斷 API、管理 API 與第三方 callback 的風險不同；防護策略要依入口用途分級。</p>
<p>下一步可讀：<a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a> 與 <a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">部署平台與網路入口</a>。</p>
<h2 id="判讀資料遮罩要依使用情境分級">【判讀】資料遮罩要依使用情境分級</h2>
<p>資料遮罩的核心責任是讓使用者完成工作，同時降低敏感資料暴露。遮罩可能發生在客服畫面、匯出報表、log、debug payload、analytics dataset、測試資料與外部分享檔案。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>客服查會員資料時，只顯示電話末三碼與 email 部分字元。</li>
<li>匯出訂單報表時，付款識別碼保留交易對帳所需欄位，個資欄位轉為遮罩值。</li>
<li>開發環境使用脫敏資料集，保留資料形狀與關聯，但移除真實身份資訊。</li>
</ul>
<p>這類需求的陷阱是把遮罩視為顯示層問題。資料可能流入匯出、log、queue、搜尋索引、分析資料集與備份；遮罩策略要定義在資料流路徑上，而非只套在單一頁面。</p>
<p>下一步可讀：<a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a> 與 <a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台</a>。</p>
<h2 id="判讀傳輸保護要覆蓋跨邊界流動">【判讀】傳輸保護要覆蓋跨邊界流動</h2>
<p>傳輸保護的核心責任是保護資料跨越邊界時的機密性、完整性與來源可信度。邊界可能是 client 到 API、service 到 service、worker 到 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a>、service 到 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a>、系統到第三方。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>client 到 API 使用 <a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS</a>，避免帳號資料在網路中被竊聽。</li>
<li>service 到 service 使用 <a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">mTLS</a> 或 signed request，確認呼叫來源與訊息完整性。</li>
<li><a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook</a> callback 驗證簽章與 timestamp，降低偽造與重放風險。</li>
</ul>
<p>這類需求的陷阱是只保護公開入口。內部網路、queue message、<a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage</a> link、backup transfer 與第三方 callback 都是資料流動路徑；傳輸保護要依邊界與資料等級設定。</p>
<p>下一步可讀：<a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">7.5 傳輸信任與憑證生命週期</a> 與 <a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">部署平台與網路入口</a>。</p>
<h2 id="判讀密鑰與秘密管理要設計生命週期">【判讀】密鑰與秘密管理要設計生命週期</h2>
<p>密鑰與秘密管理的核心責任是控制 token、API key、private key、database <a href="/blog/backend/knowledge-cards/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">Credential</a>、session secret 與加密 key 的產生、保存、使用、輪替與撤銷，並把網站憑證納入 <a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">Website Certificate Lifecycle</a>。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>第三方 API key 需要分環境保存，並能在外洩時快速撤銷。</li>
<li>database <a href="/blog/backend/knowledge-cards/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">credential</a> 需要依服務分離，避免單一 <a href="/blog/backend/knowledge-cards/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">credential</a> 擁有過大權限。</li>
<li>簽章密鑰需要支援輪替期，讓新舊 key 在過渡期間都能驗證。</li>
<li>公網站點憑證需要有 <a href="/blog/backend/knowledge-cards/acme-automation/" data-link-title="ACME Automation" data-link-desc="說明網站憑證如何透過 ACME 自動簽發與續期">ACME automation</a> 或明確續期流程，並具備 <a href="/blog/backend/knowledge-cards/certificate-revocation/" data-link-title="Certificate Revocation" data-link-desc="說明憑證洩漏或誤發時如何撤銷並控制影響範圍">certificate revocation</a> 設計。</li>
</ul>
<p>這類需求的陷阱是把秘密寫進設定檔、log、測試資料或部署指令。秘密管理要同時包含保存位置、存取權限、輪替流程、撤銷流程、憑證續期流程與稽核紀錄。</p>
<p>下一步可讀：<a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a>。</p>
<h2 id="判讀稽核追蹤要服務事後責任判斷">【判讀】稽核追蹤要服務事後責任判斷</h2>
<p>稽核追蹤的核心責任是回答「誰在何時對哪個資源做了什麼，理由與結果是什麼」。高風險操作、管理員操作、資料匯出、權限變更、金流狀態修改都需要清楚 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a>。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>管理員修改使用者角色時，記錄操作者、目標使用者、舊角色、新角色與工單 ID。</li>
<li>客服匯出訂單資料時，記錄查詢條件、匯出欄位、資料量與核准者。</li>
<li>系統輪替 API key 時，記錄 key id、使用服務、輪替時間與生效狀態。</li>
</ul>
<p>這類需求的陷阱是把 audit log 和 debug log 混在一起。debug log 服務排障，audit log 服務責任判斷；audit log 需要更穩定的 schema、保存策略、存取權限與完整性保護。</p>
<p>下一步可讀：<a href="/blog/backend/07-security-data-protection/audit-trail-and-accountability-boundary/" data-link-title="7.7 稽核追蹤與責任邊界" data-link-desc="以問題驅動方式整理高風險操作追蹤、可回查與責任切分">7.7 稽核追蹤與責任邊界</a> 與 <a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台</a>。</p>
<h2 id="檢查進入實作前的概念邊界清單">【檢查】進入實作前的概念邊界清單</h2>
<p>當以下問題都能回答時，代表本章的概念層已完成，可以進入資安與資料保護實作章節：</p>
<ol>
<li>資料分級與角色責任是否明確（誰可讀、可改、可匯出）</li>
<li>資料流路徑是否明確（client、service、queue、storage）</li>
<li>秘密與憑證生命週期是否明確（保存、輪替、撤銷、續期）</li>
<li>稽核與事故追蹤要求是否明確（audit 欄位、保存、查核流程）</li>
</ol>
<p>下一步建議路由（按本章六議題對應）：</p>
<ul>
<li>權限分級 → <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a></li>
<li>伺服器防護 → <a href="/blog/backend/07-security-data-protection/entrypoint-and-server-protection/" data-link-title="7.3 入口治理與伺服器防護" data-link-desc="以問題驅動方式整理對外入口、管理平面與伺服器邊界">7.3 入口治理與伺服器防護</a></li>
<li>資料遮罩 → <a href="/blog/backend/07-security-data-protection/data-protection-and-masking-governance/" data-link-title="7.4 資料保護與遮罩治理" data-link-desc="以問題驅動方式整理資料分級、遮罩、匯出與備份治理">7.4 資料保護與遮罩治理</a></li>
<li>傳輸保護 → <a href="/blog/backend/07-security-data-protection/transport-trust-and-certificate-lifecycle/" data-link-title="7.5 傳輸信任與憑證生命週期" data-link-desc="以問題驅動方式整理傳輸信任鏈、會話完整性與憑證節奏">7.5 傳輸信任與憑證生命週期</a></li>
<li>密鑰與秘密 → <a href="/blog/backend/07-security-data-protection/secrets-and-machine-credential-governance/" data-link-title="7.6 秘密管理與機器憑證治理" data-link-desc="以問題驅動方式整理 secret、token、key 與機器身份治理">7.6 秘密管理與機器憑證治理</a></li>
<li>稽核追蹤 → <a href="/blog/backend/07-security-data-protection/audit-trail-and-accountability-boundary/" data-link-title="7.7 稽核追蹤與責任邊界" data-link-desc="以問題驅動方式整理高風險操作追蹤、可回查與責任切分">7.7 稽核追蹤與責任邊界</a></li>
<li>事件處置 → <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">08-incident-response</a></li>
</ul>
<h2 id="小結">小結</h2>
<p>資安與資料保護要從資料、角色與路徑開始。權限分級控制誰能操作什麼，伺服器防護降低暴露入口風險，資料遮罩降低敏感資訊外流，傳輸保護保障跨邊界流動，密鑰管理控制秘密生命週期，稽核追蹤支援事後責任判斷。這些需求清楚後，後續才進入具體安全服務與平台能力。</p>
]]></content:encoded></item><item><title>0.9 知識網：訊息與事件決策路徑</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/knowledge-graph-message-flow/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/knowledge-graph-message-flow/</guid><description>&lt;p>非同步決策的核心原則是先定義投遞語意，再選擇傳遞工具。&lt;code>queue&lt;/code>、&lt;code>stream&lt;/code>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">&lt;code>pub/sub&lt;/code>&lt;/a>、&lt;code>outbox&lt;/code>、&lt;code>retry&lt;/code>、&lt;code>dead-letter&lt;/code>、&lt;code>replay&lt;/code> 與 &lt;code>idempotency&lt;/code> 是同一條決策鏈，不是獨立名詞清單。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>用事件生命週期描述非同步需求&lt;/li>
&lt;li>區分「可延遲」、「可重試」、「可重播」與「可去重」的責任邊界&lt;/li>
&lt;li>把訊息系統術語串成可檢查的決策流程&lt;/li>
&lt;li>判斷目前停在概念層，還是已經進入實作層&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="判讀事件生命週期先於產品選型">【判讀】事件生命週期先於產品選型&lt;/h2>
&lt;p>事件設計的核心問題是「事件在系統裡如何出生、傳遞、處理、失敗、重試與回放」。先回答生命週期，才有辦法判斷是否要用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a> 或 stream。&lt;/p>
&lt;p>一條最小生命週期通常包含：&lt;/p>
&lt;ol>
&lt;li>產生：&lt;code>producer&lt;/code> 何時發布事件&lt;br>
參考：&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">Producer&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/outbox-pattern/" data-link-title="Outbox Pattern" data-link-desc="說明資料庫狀態變更與事件發布如何透過 outbox 維持一致">Outbox Pattern&lt;/a>&lt;/li>
&lt;li>傳遞：事件放在哪種通道&lt;br>
參考：&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">Queue&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">Topic&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker&lt;/a>&lt;/li>
&lt;li>消費：&lt;code>consumer&lt;/code> 如何確認處理結果&lt;br>
參考：&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">Consumer&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">Ack/Nack&lt;/a>&lt;/li>
&lt;li>失敗：重試與隔離如何發生&lt;br>
參考：&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">Retry Policy&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">Dead-Letter Queue&lt;/a>&lt;/li>
&lt;li>回復：資料如何補送與重播&lt;br>
參考：&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">Replay Runbook&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">Offset&lt;/a>&lt;/li>
&lt;/ol>
&lt;p>這條鏈路完整後，才進入 RabbitMQ、Kafka、Redis Streams 或雲端託管服務比較。&lt;/p>
&lt;h2 id="判讀投遞語意決定設計強度">【判讀】投遞語意決定設計強度&lt;/h2>
&lt;p>投遞語意的核心問題是「失敗後，系統接受哪種結果」。&lt;code>at-most-once&lt;/code>、&lt;code>at-least-once&lt;/code> 與順序需求會直接決定重試、去重與補送成本。&lt;/p>
&lt;p>接近真實網路服務的判斷方式包括：&lt;/p>
&lt;ul>
&lt;li>通知類訊息可接受少量遺失：重點在低延遲與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out&lt;/a>。&lt;/li>
&lt;li>金流或庫存狀態不可遺失：重點在持久化、重試與補償，並定義 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/strong-reliability/" data-link-title="Strong Reliability" data-link-desc="說明高可靠事件路徑需要的保存、重試、去重與回復責任">strong reliability&lt;/a> 路徑。&lt;/li>
&lt;li>分析事件可接受短暫延遲：重點在可重播與批次處理。&lt;/li>
&lt;/ul>
&lt;p>對應卡片：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/duplicate-delivery/" data-link-title="Duplicate Delivery" data-link-desc="說明同一個訊息被處理多次時如何保持結果穩定">Duplicate Delivery&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">Idempotency&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/message-persistence/" data-link-title="Message Persistence" data-link-desc="說明訊息是否落盤保存，以及 broker 重啟後能否恢復">Message Persistence&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/delivery-mode/" data-link-title="Delivery Mode" data-link-desc="說明訊息投遞模式如何影響可靠性、延遲與成本">Delivery Mode&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="判讀壅塞與延遲要用同一組語言處理">【判讀】壅塞與延遲要用同一組語言處理&lt;/h2>
&lt;p>非同步壓力的核心問題是「輸入速度高於處理速度」。這會同時反映在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">queue depth&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout&lt;/a> 與重試風暴。&lt;/p>
&lt;p>對應卡片關係：&lt;/p>
&lt;ul>
&lt;li>壓力來源：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">Backpressure&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">Queue Depth&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">Consumer Lag&lt;/a>&lt;/li>
&lt;li>保護策略：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">Rate Limit&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/load-shedding/" data-link-title="Load Shedding" data-link-desc="說明服務過載時如何主動拒絕低優先工作以保護核心能力">Load Shedding&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/circuit-breaker/" data-link-title="Circuit Breaker" data-link-desc="說明下游持續失敗時如何暫停呼叫並保護系統">Circuit Breaker&lt;/a>&lt;/li>
&lt;li>失敗擴散：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retry-storm/" data-link-title="Retry Storm" data-link-desc="說明大量重試如何把局部故障放大成系統壓力">Retry Storm&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cascading-failure/" data-link-title="Cascading Failure" data-link-desc="說明局部故障如何透過等待、重試與資源耗盡擴散到整個系統">Cascading Failure&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>這一層討論完成前，不需要先決定 broker 產品或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition&lt;/a> 數量。&lt;/p></description><content:encoded><![CDATA[<p>非同步決策的核心原則是先定義投遞語意，再選擇傳遞工具。<code>queue</code>、<code>stream</code>、<a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者"><code>pub/sub</code></a>、<code>outbox</code>、<code>retry</code>、<code>dead-letter</code>、<code>replay</code> 與 <code>idempotency</code> 是同一條決策鏈，不是獨立名詞清單。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>用事件生命週期描述非同步需求</li>
<li>區分「可延遲」、「可重試」、「可重播」與「可去重」的責任邊界</li>
<li>把訊息系統術語串成可檢查的決策流程</li>
<li>判斷目前停在概念層，還是已經進入實作層</li>
</ol>
<hr>
<h2 id="判讀事件生命週期先於產品選型">【判讀】事件生命週期先於產品選型</h2>
<p>事件設計的核心問題是「事件在系統裡如何出生、傳遞、處理、失敗、重試與回放」。先回答生命週期，才有辦法判斷是否要用 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a>、<a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a> 或 stream。</p>
<p>一條最小生命週期通常包含：</p>
<ol>
<li>產生：<code>producer</code> 何時發布事件<br>
參考：<a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">Producer</a> / <a href="/blog/backend/knowledge-cards/outbox-pattern/" data-link-title="Outbox Pattern" data-link-desc="說明資料庫狀態變更與事件發布如何透過 outbox 維持一致">Outbox Pattern</a></li>
<li>傳遞：事件放在哪種通道<br>
參考：<a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">Queue</a> / <a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">Topic</a> / <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker</a></li>
<li>消費：<code>consumer</code> 如何確認處理結果<br>
參考：<a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">Consumer</a> / <a href="/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">Ack/Nack</a></li>
<li>失敗：重試與隔離如何發生<br>
參考：<a href="/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">Retry Policy</a> / <a href="/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">Dead-Letter Queue</a></li>
<li>回復：資料如何補送與重播<br>
參考：<a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">Replay Runbook</a> / <a href="/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">Offset</a></li>
</ol>
<p>這條鏈路完整後，才進入 RabbitMQ、Kafka、Redis Streams 或雲端託管服務比較。</p>
<h2 id="判讀投遞語意決定設計強度">【判讀】投遞語意決定設計強度</h2>
<p>投遞語意的核心問題是「失敗後，系統接受哪種結果」。<code>at-most-once</code>、<code>at-least-once</code> 與順序需求會直接決定重試、去重與補送成本。</p>
<p>接近真實網路服務的判斷方式包括：</p>
<ul>
<li>通知類訊息可接受少量遺失：重點在低延遲與 <a href="/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out</a>。</li>
<li>金流或庫存狀態不可遺失：重點在持久化、重試與補償，並定義 <a href="/blog/backend/knowledge-cards/strong-reliability/" data-link-title="Strong Reliability" data-link-desc="說明高可靠事件路徑需要的保存、重試、去重與回復責任">strong reliability</a> 路徑。</li>
<li>分析事件可接受短暫延遲：重點在可重播與批次處理。</li>
</ul>
<p>對應卡片：</p>
<ul>
<li><a href="/blog/backend/knowledge-cards/duplicate-delivery/" data-link-title="Duplicate Delivery" data-link-desc="說明同一個訊息被處理多次時如何保持結果穩定">Duplicate Delivery</a></li>
<li><a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">Idempotency</a></li>
<li><a href="/blog/backend/knowledge-cards/message-persistence/" data-link-title="Message Persistence" data-link-desc="說明訊息是否落盤保存，以及 broker 重啟後能否恢復">Message Persistence</a></li>
<li><a href="/blog/backend/knowledge-cards/delivery-mode/" data-link-title="Delivery Mode" data-link-desc="說明訊息投遞模式如何影響可靠性、延遲與成本">Delivery Mode</a></li>
</ul>
<h2 id="判讀壅塞與延遲要用同一組語言處理">【判讀】壅塞與延遲要用同一組語言處理</h2>
<p>非同步壓力的核心問題是「輸入速度高於處理速度」。這會同時反映在 <a href="/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">queue depth</a>、<a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag</a>、<a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout</a> 與重試風暴。</p>
<p>對應卡片關係：</p>
<ul>
<li>壓力來源：<br>
<a href="/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">Backpressure</a> / <a href="/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">Queue Depth</a> / <a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">Consumer Lag</a></li>
<li>保護策略：<br>
<a href="/blog/backend/knowledge-cards/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">Rate Limit</a> / <a href="/blog/backend/knowledge-cards/load-shedding/" data-link-title="Load Shedding" data-link-desc="說明服務過載時如何主動拒絕低優先工作以保護核心能力">Load Shedding</a> / <a href="/blog/backend/knowledge-cards/circuit-breaker/" data-link-title="Circuit Breaker" data-link-desc="說明下游持續失敗時如何暫停呼叫並保護系統">Circuit Breaker</a></li>
<li>失敗擴散：<br>
<a href="/blog/backend/knowledge-cards/retry-storm/" data-link-title="Retry Storm" data-link-desc="說明大量重試如何把局部故障放大成系統壓力">Retry Storm</a> / <a href="/blog/backend/knowledge-cards/cascading-failure/" data-link-title="Cascading Failure" data-link-desc="說明局部故障如何透過等待、重試與資源耗盡擴散到整個系統">Cascading Failure</a></li>
</ul>
<p>這一層討論完成前，不需要先決定 broker 產品或 <a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition</a> 數量。</p>
<h2 id="判讀回復流程是可靠性設計的一部分">【判讀】回復流程是可靠性設計的一部分</h2>
<p>回復設計的核心問題是「錯誤發生後如何回到正確狀態」。<code>DLQ</code>、<code>replay</code>、<a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation</a> 與 <code>runbook</code> 應該一起定義。</p>
<p>對應卡片：</p>
<ul>
<li><a href="/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">Dead-Letter Queue</a></li>
<li><a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">Replay Runbook</a></li>
<li><a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation</a></li>
<li><a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">Runbook</a></li>
</ul>
<p>若這些概念只有名詞而沒有決策順序，系統上線後會把排障責任推給個人經驗。</p>
<h2 id="邊界何時從概念章節進入實作章節">【邊界】何時從概念章節進入實作章節</h2>
<p>當以下問題都能回答時，代表概念層已完成，可以進入實作模組：</p>
<ol>
<li>哪些事件可遺失，哪些事件不可遺失</li>
<li>哪些 consumer 需要去重，語意鍵是什麼</li>
<li>何時重試、何時進 DLQ、何時啟動 replay</li>
<li>哪些指標觸發擴容或降級</li>
</ol>
<p>下一步建議路由：</p>
<ul>
<li>進入訊息系統能力比較：<a href="/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">03-message-queue</a></li>
<li>進入可觀測與事故流程：<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">04-observability</a> / <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">08-incident-response</a></li>
</ul>
]]></content:encoded></item><item><title>0.10 知識網：容量、觀測與資安決策路徑</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/knowledge-graph-operations-security/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/knowledge-graph-operations-security/</guid><description>&lt;p>服務治理的核心原則是把可用性與安全性放在同一張決策圖上。&lt;code>timeout&lt;/code>、&lt;code>deadline&lt;/code>、&lt;code>readiness&lt;/code>、&lt;code>runbook&lt;/code>、&lt;code>RTO/RPO&lt;/code>、&lt;code>authentication&lt;/code>、&lt;code>authorization&lt;/code>、&lt;code>TLS/mTLS&lt;/code> 與 &lt;code>audit log&lt;/code> 描述的是同一件事：系統如何在壓力與風險下維持可運作。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>用「容量-觀測-資安」三軸描述服務治理需求&lt;/li>
&lt;li>把術語連成可追蹤的決策鏈，而非獨立名詞&lt;/li>
&lt;li>判斷何時先補觀測與操作能力，何時先補安全控制&lt;/li>
&lt;li>明確區分概念決策與平台實作邊界&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="判讀容量控制與恢復目標是一條線">【判讀】容量控制與恢復目標是一條線&lt;/h2>
&lt;p>容量治理的核心問題是「系統在壓力下如何守住核心能力」。&lt;code>timeout&lt;/code>、&lt;code>deadline&lt;/code>、&lt;code>backpressure&lt;/code>、&lt;code>rate limit&lt;/code> 與 &lt;code>fallback&lt;/code> 應該連到同一個恢復目標。&lt;/p>
&lt;p>對應卡片關係：&lt;/p>
&lt;ul>
&lt;li>請求邊界：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">Timeout&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/deadline/" data-link-title="Deadline" data-link-desc="說明整體操作的截止時間如何沿著服務邊界傳遞">Deadline&lt;/a>&lt;/li>
&lt;li>壓力控制：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">Backpressure&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">Rate Limit&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/token-bucket/" data-link-title="Token Bucket" data-link-desc="說明 token bucket 如何用配額與補充速率控制流量">Token Bucket&lt;/a>&lt;/li>
&lt;li>退讓策略：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">Fallback&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">Degradation&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">Failover&lt;/a>&lt;/li>
&lt;li>恢復目標：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>如果只定義 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout&lt;/a>，沒有 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">fallback&lt;/a> 與回復目標，系統仍缺少操作上的可控性。&lt;/p>
&lt;h2 id="判讀可觀測訊號要服務操作決策">【判讀】可觀測訊號要服務操作決策&lt;/h2>
&lt;p>可觀測性的核心問題是「問題出現時，團隊能否在時間內採取正確動作」。&lt;code>log&lt;/code>、&lt;code>metrics&lt;/code>、&lt;code>trace&lt;/code>、&lt;code>alert&lt;/code> 與 &lt;code>runbook&lt;/code> 必須一起設計。&lt;/p>
&lt;p>對應卡片關係：&lt;/p>
&lt;ul>
&lt;li>事件與脈絡：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">Log&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">Log Schema&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/correlation-id/" data-link-title="Correlation ID" data-link-desc="說明跨事件或跨服務的關聯識別碼如何支援排障">Correlation ID&lt;/a>&lt;/li>
&lt;li>趨勢與目標：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">Metrics&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI/SLO&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/error-budget/" data-link-title="Error Budget" data-link-desc="說明 SLO 允許的失敗額度如何影響發版與可靠性投入">Error Budget&lt;/a>&lt;/li>
&lt;li>路徑與定位：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">Trace&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace-context/" data-link-title="Trace Context" data-link-desc="說明跨服務 request 如何用 trace context 串起路徑與耗時">Trace Context&lt;/a>&lt;/li>
&lt;li>執行與回應：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">Alert&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert-runbook/" data-link-title="Alert Runbook" data-link-desc="說明告警如何連到可執行的排障與恢復流程">Alert Runbook&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">Runbook&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>當觀測鏈完整後，才適合比較具體平台組合。&lt;/p>
&lt;h2 id="判讀資安控制要對齊資料流與角色責任">【判讀】資安控制要對齊資料流與角色責任&lt;/h2>
&lt;p>資安治理的核心問題是「誰可以在什麼條件下接觸哪類資料」。身份、授權、傳輸保護、秘密管理與稽核需要同時成立。&lt;/p>
&lt;p>對應卡片關係：&lt;/p>
&lt;ul>
&lt;li>身份與存取：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">Least Privilege&lt;/a>&lt;/li>
&lt;li>傳輸與憑證：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS/mTLS&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-chain-trust/" data-link-title="Certificate Chain and Trust Root" data-link-desc="說明網站憑證鏈與信任根如何影響連線可用性與驗證結果">Certificate Chain and Trust&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-revocation/" data-link-title="Certificate Revocation" data-link-desc="說明憑證洩漏或誤發時如何撤銷並控制影響範圍">Certificate Revocation&lt;/a>&lt;/li>
&lt;li>秘密與輪替：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-rotation-renewal/" data-link-title="Certificate Rotation and Renewal" data-link-desc="說明網站憑證如何安全續期與輪替以避免停機">Certificate Rotation and Renewal&lt;/a>&lt;/li>
&lt;li>敏感資料與稽核：&lt;br>
&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pii/" data-link-title="PII" data-link-desc="說明可識別個人的資料如何影響權限、遮罩、保留與稽核">PII&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-masking/" data-link-title="Data Masking" data-link-desc="說明敏感資料如何在顯示、匯出、log 與測試資料中降低暴露">Data Masking&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>若資安設計只停在單一工具，缺少資料流路徑與角色責任描述，章節仍停在術語層。&lt;/p>
&lt;h2 id="判讀事故治理把容量觀測與資安接起來">【判讀】事故治理把容量、觀測與資安接起來&lt;/h2>
&lt;p>事故治理的核心問題是「異常發生時，如何在可接受風險下恢復服務」。severity、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call&lt;/a>、timeline、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rca/" data-link-title="RCA" data-link-desc="說明根因分析如何區分觸發事件、系統弱點與防線缺口">RCA&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/game-day/" data-link-title="Game Day" data-link-desc="說明事故演練如何驗證流程、工具與團隊協作">game day&lt;/a> 是將前面三軸落地的操作語言。&lt;/p></description><content:encoded><![CDATA[<p>服務治理的核心原則是把可用性與安全性放在同一張決策圖上。<code>timeout</code>、<code>deadline</code>、<code>readiness</code>、<code>runbook</code>、<code>RTO/RPO</code>、<code>authentication</code>、<code>authorization</code>、<code>TLS/mTLS</code> 與 <code>audit log</code> 描述的是同一件事：系統如何在壓力與風險下維持可運作。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>用「容量-觀測-資安」三軸描述服務治理需求</li>
<li>把術語連成可追蹤的決策鏈，而非獨立名詞</li>
<li>判斷何時先補觀測與操作能力，何時先補安全控制</li>
<li>明確區分概念決策與平台實作邊界</li>
</ol>
<hr>
<h2 id="判讀容量控制與恢復目標是一條線">【判讀】容量控制與恢復目標是一條線</h2>
<p>容量治理的核心問題是「系統在壓力下如何守住核心能力」。<code>timeout</code>、<code>deadline</code>、<code>backpressure</code>、<code>rate limit</code> 與 <code>fallback</code> 應該連到同一個恢復目標。</p>
<p>對應卡片關係：</p>
<ul>
<li>請求邊界：<br>
<a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">Timeout</a> / <a href="/blog/backend/knowledge-cards/deadline/" data-link-title="Deadline" data-link-desc="說明整體操作的截止時間如何沿著服務邊界傳遞">Deadline</a></li>
<li>壓力控制：<br>
<a href="/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">Backpressure</a> / <a href="/blog/backend/knowledge-cards/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">Rate Limit</a> / <a href="/blog/backend/knowledge-cards/token-bucket/" data-link-title="Token Bucket" data-link-desc="說明 token bucket 如何用配額與補充速率控制流量">Token Bucket</a></li>
<li>退讓策略：<br>
<a href="/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">Fallback</a> / <a href="/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">Degradation</a> / <a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">Failover</a></li>
<li>恢復目標：<br>
<a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO</a> / <a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a></li>
</ul>
<p>如果只定義 <a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout</a>，沒有 <a href="/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">fallback</a> 與回復目標，系統仍缺少操作上的可控性。</p>
<h2 id="判讀可觀測訊號要服務操作決策">【判讀】可觀測訊號要服務操作決策</h2>
<p>可觀測性的核心問題是「問題出現時，團隊能否在時間內採取正確動作」。<code>log</code>、<code>metrics</code>、<code>trace</code>、<code>alert</code> 與 <code>runbook</code> 必須一起設計。</p>
<p>對應卡片關係：</p>
<ul>
<li>事件與脈絡：<br>
<a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">Log</a> / <a href="/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">Log Schema</a> / <a href="/blog/backend/knowledge-cards/correlation-id/" data-link-title="Correlation ID" data-link-desc="說明跨事件或跨服務的關聯識別碼如何支援排障">Correlation ID</a></li>
<li>趨勢與目標：<br>
<a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">Metrics</a> / <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI/SLO</a> / <a href="/blog/backend/knowledge-cards/error-budget/" data-link-title="Error Budget" data-link-desc="說明 SLO 允許的失敗額度如何影響發版與可靠性投入">Error Budget</a></li>
<li>路徑與定位：<br>
<a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">Trace</a> / <a href="/blog/backend/knowledge-cards/trace-context/" data-link-title="Trace Context" data-link-desc="說明跨服務 request 如何用 trace context 串起路徑與耗時">Trace Context</a></li>
<li>執行與回應：<br>
<a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">Alert</a> / <a href="/blog/backend/knowledge-cards/alert-runbook/" data-link-title="Alert Runbook" data-link-desc="說明告警如何連到可執行的排障與恢復流程">Alert Runbook</a> / <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">Runbook</a></li>
</ul>
<p>當觀測鏈完整後，才適合比較具體平台組合。</p>
<h2 id="判讀資安控制要對齊資料流與角色責任">【判讀】資安控制要對齊資料流與角色責任</h2>
<p>資安治理的核心問題是「誰可以在什麼條件下接觸哪類資料」。身份、授權、傳輸保護、秘密管理與稽核需要同時成立。</p>
<p>對應卡片關係：</p>
<ul>
<li>身份與存取：<br>
<a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication</a> / <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a> / <a href="/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">Least Privilege</a></li>
<li>傳輸與憑證：<br>
<a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS/mTLS</a> / <a href="/blog/backend/knowledge-cards/certificate-chain-trust/" data-link-title="Certificate Chain and Trust Root" data-link-desc="說明網站憑證鏈與信任根如何影響連線可用性與驗證結果">Certificate Chain and Trust</a> / <a href="/blog/backend/knowledge-cards/certificate-revocation/" data-link-title="Certificate Revocation" data-link-desc="說明憑證洩漏或誤發時如何撤銷並控制影響範圍">Certificate Revocation</a></li>
<li>秘密與輪替：<br>
<a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> / <a href="/blog/backend/knowledge-cards/certificate-rotation-renewal/" data-link-title="Certificate Rotation and Renewal" data-link-desc="說明網站憑證如何安全續期與輪替以避免停機">Certificate Rotation and Renewal</a></li>
<li>敏感資料與稽核：<br>
<a href="/blog/backend/knowledge-cards/pii/" data-link-title="PII" data-link-desc="說明可識別個人的資料如何影響權限、遮罩、保留與稽核">PII</a> / <a href="/blog/backend/knowledge-cards/data-masking/" data-link-title="Data Masking" data-link-desc="說明敏感資料如何在顯示、匯出、log 與測試資料中降低暴露">Data Masking</a> / <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a></li>
</ul>
<p>若資安設計只停在單一工具，缺少資料流路徑與角色責任描述，章節仍停在術語層。</p>
<h2 id="判讀事故治理把容量觀測與資安接起來">【判讀】事故治理把容量、觀測與資安接起來</h2>
<p>事故治理的核心問題是「異常發生時，如何在可接受風險下恢復服務」。severity、<a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a>、timeline、<a href="/blog/backend/knowledge-cards/rca/" data-link-title="RCA" data-link-desc="說明根因分析如何區分觸發事件、系統弱點與防線缺口">RCA</a> 與 <a href="/blog/backend/knowledge-cards/game-day/" data-link-title="Game Day" data-link-desc="說明事故演練如何驗證流程、工具與團隊協作">game day</a> 是將前面三軸落地的操作語言。</p>
<p>對應卡片：</p>
<ul>
<li><a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity</a></li>
<li><a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">On-call</a></li>
<li><a href="/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">Incident Timeline</a></li>
<li><a href="/blog/backend/knowledge-cards/rca/" data-link-title="RCA" data-link-desc="說明根因分析如何區分觸發事件、系統弱點與防線缺口">RCA</a></li>
<li><a href="/blog/backend/knowledge-cards/game-day/" data-link-title="Game Day" data-link-desc="說明事故演練如何驗證流程、工具與團隊協作">Game Day</a></li>
</ul>
<p>這些概念建立後，事故處理不會只依賴個人臨場反應。</p>
<h2 id="邊界何時從概念章節進入實作章節">【邊界】何時從概念章節進入實作章節</h2>
<p>當以下問題都能回答時，代表概念層已完成，可以進入實作模組：</p>
<ol>
<li>核心服務的容量保護鏈是什麼（timeout 到 fallback）</li>
<li>告警觸發後，<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 的第一個與第二個動作是什麼</li>
<li>高風險資料在系統內的流動路徑與存取角色是什麼</li>
<li>事故升級與回報節點如何定義</li>
</ol>
<p>下一步建議路由：</p>
<ul>
<li>進入可觀測實作能力：<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">04-observability</a></li>
<li>進入部署與可靠性能力：<a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">05-deployment-platform</a> / <a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">06-reliability</a></li>
<li>進入資安與資料保護能力：<a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07-security-data-protection</a></li>
<li>進入事故治理能力：<a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">08-incident-response</a></li>
</ul>
]]></content:encoded></item><item><title>0.11 攻擊者視角（紅隊）：跨服務弱點判讀總表</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/red-team-cross-service-weaknesses/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/red-team-cross-service-weaknesses/</guid><description>&lt;p>跨服務紅隊判讀的核心目標是把「哪裡最容易被打穿」先標出來，再決定服務能力的補強順序。這裡的紅隊是「攻擊者視角的風險檢查方法」：用攻擊者可能採取的路徑反向驗證系統設計。這份總表維持純概念層，不進入實作細節，重點是先回答四件事：暴露面在哪裡、弱點訊號長什麼樣、失敗代價是什麼、最低控制面要先有哪些。&lt;/p>
&lt;h2 id="總表服務類型與弱點判讀">【總表】服務類型與弱點判讀&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>服務類型&lt;/th>
 &lt;th>常見弱點&lt;/th>
 &lt;th>可觀察訊號&lt;/th>
 &lt;th>失敗代價&lt;/th>
 &lt;th>最低控制面&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a>&lt;/td>
 &lt;td>越權查詢、交易邊界混亂、schema 變更風險&lt;/td>
 &lt;td>權限模型複雜、跨租戶查詢、migration 頻繁&lt;/td>
 &lt;td>資料錯誤、資料洩漏、長時間修復&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">authorization&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/transaction-boundary/" data-link-title="Transaction Boundary" data-link-desc="說明哪些資料變更應在同一個交易中一起成功或一起回復">transaction boundary&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>cache / &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model&lt;/a>&lt;/td>
 &lt;td>資料陳舊、快取污染、索引暴露&lt;/td>
 &lt;td>hit rate 波動、回源突增、欄位暴露不一致&lt;/td>
 &lt;td>錯誤決策、客訴、壓力擴散到主存&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">cache invalidation&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-classification/" data-link-title="Data Classification" data-link-desc="說明資料分級如何決定保護、存取、保留與匯出規則">data classification&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">fallback&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>message &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a> / stream&lt;/td>
 &lt;td>重複投遞、重放濫用、毒訊息擴散&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">DLQ&lt;/a>、重試風暴&lt;/td>
 &lt;td>重複執行、狀態偏移、恢復時間拉長&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retry-budget/" data-link-title="Retry Budget" data-link-desc="說明重試次數如何受整體容量與錯誤預算限制">retry budget&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>observability&lt;/td>
 &lt;td>盲區告警、敏感資料進 log、追蹤斷點&lt;/td>
 &lt;td>告警無法定位、trace 斷鏈、log 欄位失衡&lt;/td>
 &lt;td>修復延遲、誤判、資安風險提升&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">log schema&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>deployment / network entry&lt;/td>
 &lt;td>隱藏入口、錯誤設定、切換窗口失控&lt;/td>
 &lt;td>readiness 不穩、error rate 突增、unknown endpoint 被命中&lt;/td>
 &lt;td>擴散式故障、服務中斷、恢復成本升高&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/graceful-shutdown/" data-link-title="Graceful Shutdown" data-link-desc="說明服務停止前如何排空流量、完成工作與保存狀態">graceful shutdown&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/waf/" data-link-title="WAF" data-link-desc="說明 Web Application Firewall 如何在入口層過濾常見攻擊與濫用">WAF&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">release gate&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="判讀攻擊者視角總表在選型流程的位置">【判讀】攻擊者視角總表在選型流程的位置&lt;/h2>
&lt;p>攻擊者視角總表放在產品需求與服務實體之間。流程上先做需求分類，再用這份總表檢查弱點與代價，最後才進入產品比較。這個順序能讓選型討論同步納入攻擊面與操作成本，避免把風險留到上線後才處理。&lt;/p>
&lt;h2 id="判讀弱點討論要對齊成本模型">【判讀】弱點討論要對齊成本模型&lt;/h2>
&lt;p>弱點判讀的核心價值是提早看見操作成本。若只看開發速度，常見結果是上線後才補 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a>、權限分級、告警路由與備援切換。把弱點表納入選型初期，可以同時估算人力成本、容量成本與事故成本，讓服務能力與團隊負擔一起被評估。&lt;/p>
&lt;h2 id="下一步對應模組">【下一步】對應模組&lt;/h2>
&lt;ul>
&lt;li>資料層弱點路徑：模組一 database&lt;/li>
&lt;li>訊息層弱點路徑：模組三 message queue&lt;/li>
&lt;li>平台與入口弱點路徑：模組五 deployment platform&lt;/li>
&lt;li>可觀測性弱點路徑：模組四 observability&lt;/li>
&lt;li>資安與紅隊弱點路徑：模組七 security / red-team&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>跨服務紅隊判讀的核心目標是把「哪裡最容易被打穿」先標出來，再決定服務能力的補強順序。這裡的紅隊是「攻擊者視角的風險檢查方法」：用攻擊者可能採取的路徑反向驗證系統設計。這份總表維持純概念層，不進入實作細節，重點是先回答四件事：暴露面在哪裡、弱點訊號長什麼樣、失敗代價是什麼、最低控制面要先有哪些。</p>
<h2 id="總表服務類型與弱點判讀">【總表】服務類型與弱點判讀</h2>
<table>
  <thead>
      <tr>
          <th>服務類型</th>
          <th>常見弱點</th>
          <th>可觀察訊號</th>
          <th>失敗代價</th>
          <th>最低控制面</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a></td>
          <td>越權查詢、交易邊界混亂、schema 變更風險</td>
          <td>權限模型複雜、跨租戶查詢、migration 頻繁</td>
          <td>資料錯誤、資料洩漏、長時間修復</td>
          <td><a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">authorization</a>、<a href="/blog/backend/knowledge-cards/transaction-boundary/" data-link-title="Transaction Boundary" data-link-desc="說明哪些資料變更應在同一個交易中一起成功或一起回復">transaction boundary</a>、<a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a></td>
      </tr>
      <tr>
          <td>cache / <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a></td>
          <td>資料陳舊、快取污染、索引暴露</td>
          <td>hit rate 波動、回源突增、欄位暴露不一致</td>
          <td>錯誤決策、客訴、壓力擴散到主存</td>
          <td><a href="/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">cache invalidation</a>、<a href="/blog/backend/knowledge-cards/data-classification/" data-link-title="Data Classification" data-link-desc="說明資料分級如何決定保護、存取、保留與匯出規則">data classification</a>、<a href="/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">fallback</a></td>
      </tr>
      <tr>
          <td>message <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a> / stream</td>
          <td>重複投遞、重放濫用、毒訊息擴散</td>
          <td><a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag</a>、<a href="/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">DLQ</a>、重試風暴</td>
          <td>重複執行、狀態偏移、恢復時間拉長</td>
          <td><a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a>、<a href="/blog/backend/knowledge-cards/retry-budget/" data-link-title="Retry Budget" data-link-desc="說明重試次數如何受整體容量與錯誤預算限制">retry budget</a>、<a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook</a></td>
      </tr>
      <tr>
          <td>observability</td>
          <td>盲區告警、敏感資料進 log、追蹤斷點</td>
          <td>告警無法定位、trace 斷鏈、log 欄位失衡</td>
          <td>修復延遲、誤判、資安風險提升</td>
          <td><a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics</a>、<a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a>、<a href="/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">log schema</a>、<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a></td>
      </tr>
      <tr>
          <td>deployment / network entry</td>
          <td>隱藏入口、錯誤設定、切換窗口失控</td>
          <td>readiness 不穩、error rate 突增、unknown endpoint 被命中</td>
          <td>擴散式故障、服務中斷、恢復成本升高</td>
          <td><a href="/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness</a>、<a href="/blog/backend/knowledge-cards/graceful-shutdown/" data-link-title="Graceful Shutdown" data-link-desc="說明服務停止前如何排空流量、完成工作與保存狀態">graceful shutdown</a>、<a href="/blog/backend/knowledge-cards/waf/" data-link-title="WAF" data-link-desc="說明 Web Application Firewall 如何在入口層過濾常見攻擊與濫用">WAF</a>、<a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">release gate</a></td>
      </tr>
  </tbody>
</table>
<h2 id="判讀攻擊者視角總表在選型流程的位置">【判讀】攻擊者視角總表在選型流程的位置</h2>
<p>攻擊者視角總表放在產品需求與服務實體之間。流程上先做需求分類，再用這份總表檢查弱點與代價，最後才進入產品比較。這個順序能讓選型討論同步納入攻擊面與操作成本，避免把風險留到上線後才處理。</p>
<h2 id="判讀弱點討論要對齊成本模型">【判讀】弱點討論要對齊成本模型</h2>
<p>弱點判讀的核心價值是提早看見操作成本。若只看開發速度，常見結果是上線後才補 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a>、權限分級、告警路由與備援切換。把弱點表納入選型初期，可以同時估算人力成本、容量成本與事故成本，讓服務能力與團隊負擔一起被評估。</p>
<h2 id="下一步對應模組">【下一步】對應模組</h2>
<ul>
<li>資料層弱點路徑：模組一 database</li>
<li>訊息層弱點路徑：模組三 message queue</li>
<li>平台與入口弱點路徑：模組五 deployment platform</li>
<li>可觀測性弱點路徑：模組四 observability</li>
<li>資安與紅隊弱點路徑：模組七 security / red-team</li>
</ul>
]]></content:encoded></item><item><title>0.12 觀測、可靠性與事故服務選型</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/operations-control-service-selection/</link><pubDate>Sat, 02 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/operations-control-service-selection/</guid><description>&lt;p>觀測、可靠性與事故服務選型的核心責任是把操作風險拆成「看得見、驗得過、接得住」三層能力。&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台&lt;/a>處理訊號是否足以支援判讀，&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">可靠性驗證流程&lt;/a>處理失敗是否能被安全預演，&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">事故處理與復盤&lt;/a>處理事故是否能被接住、分工與回寫。&lt;/p>
&lt;p>這三類服務常被一起採購或一起導入，但它們回答不同問題。觀測平台回答「現在發生什麼」，可靠性工具回答「失敗前能否先驗證」，事故平台回答「事情發生後誰做什麼」。選型時先分清能力層，再比較 vendor、SaaS、OSS 或自建方案，能降低工具堆疊與流程空轉的風險。&lt;/p>
&lt;h2 id="選型錨點">選型錨點&lt;/h2>
&lt;p>選型錨點是先問服務要降低哪一種操作不確定性。當團隊只知道系統「好像怪怪的」，優先補訊號；當團隊知道風險但缺少安全驗證路徑，優先補可靠性驗證；當團隊知道事故已發生但協作混亂，優先補事故流程。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>能力層&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>對應模組&lt;/th>
 &lt;th>常見服務類型&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>訊號層&lt;/td>
 &lt;td>發生什麼、影響哪裡&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台&lt;/a>&lt;/td>
 &lt;td>telemetry、APM、log、dashboard&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>驗證層&lt;/td>
 &lt;td>風險能否提前預演&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">可靠性驗證流程&lt;/a>&lt;/td>
 &lt;td>CI、load test、chaos、SLO&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>響應層&lt;/td>
 &lt;td>誰接手、如何收斂&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">事故處理與復盤&lt;/a>&lt;/td>
 &lt;td>on-call、IR、status、postmortem&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>閉環層&lt;/td>
 &lt;td>教訓如何回寫&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/observability-reliability-incident-loop/" data-link-title="8.11 Observability / Reliability / Incident Response 閉環" data-link-desc="把 04 / 06 / 08 三個模組的雙向反饋串成可判讀循環，定義閉環健康度判讀訊號">觀測、驗證與事故閉環&lt;/a>&lt;/td>
 &lt;td>workflow、action tracking&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>訊號層的責任是讓系統行為可被查詢與判讀。這一層的選型重點是資料模型、查詢能力、關聯能力、保留成本與告警品質；產品名稱排在後面，因為 log、metric、trace 與 error event 是否能互相串接，才是事故時真正影響判讀速度的條件。&lt;/p>
&lt;p>驗證層的責任是讓風險在事故前被安全暴露。這一層的選型重點是測試是否接近真實 workload、故障注入是否有停止條件、SLO 是否能被量測、release gate 是否能阻止高風險變更；工具越強，越需要 blast radius 與權限邊界。&lt;/p>
&lt;p>響應層的責任是讓事故進入可交接流程。這一層的選型重點是 paging、升級、角色分工、狀態更新、decision log、stakeholder mapping 與 post-incident action tracking；工具的價值來自流程一致性，通知訊息數量只是輔助訊號。&lt;/p>
&lt;p>閉環層的責任是把事故與演練教訓回寫到系統設計。這一層可能由 incident platform、ticket system、runbook repository 或內部 workflow 承擔；判準是 action item 是否能被排序、驗證、關閉，並回到訊號治理、可靠性演練或事故流程。&lt;/p>
&lt;h2 id="判讀順序">判讀順序&lt;/h2>
&lt;p>操作服務選型的穩定順序是「症狀 → 缺口 → 能力 → 工具」。症狀描述使用者痛點或工程痛點，缺口描述目前缺少的判讀或流程，能力描述需要補的系統責任，工具才是最後的落地選項。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>症狀&lt;/th>
 &lt;th>主要缺口&lt;/th>
 &lt;th>優先能力&lt;/th>
 &lt;th>下一步路由&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>客訴比告警早&lt;/td>
 &lt;td>訊號覆蓋不足&lt;/td>
 &lt;td>symptom-based alert&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/dashboard-alert/" data-link-title="4.4 dashboard 與 alert 設計" data-link-desc="讓 dashboard 與 alert 對應 runbook 與容量趨勢">dashboard 與 alert&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>事故時 trace 接不上 queue&lt;/td>
 &lt;td>關聯線索斷裂&lt;/td>
 &lt;td>context propagation&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/tracing-context/" data-link-title="4.3 tracing 與 context link" data-link-desc="整理 trace id、span 與跨服務 context propagation">tracing 與 context link&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>發版後才發現容量曲線崩壞&lt;/td>
 &lt;td>失敗前驗證不足&lt;/td>
 &lt;td>load / perf gate&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/load-testing/" data-link-title="6.2 load test" data-link-desc="把 production 流量結構轉成可重播壓力情境，定位 saturation 轉折與容量邊界">load test&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>chaos 實驗影響超出預期&lt;/td>
 &lt;td>實驗安全邊界不足&lt;/td>
 &lt;td>experiment guardrail&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">experiment safety boundary&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>多人同時修事故但決策互相覆蓋&lt;/td>
 &lt;td>指揮與紀錄不足&lt;/td>
 &lt;td>command / decision log&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">incident decision log&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>對外狀態更新慢於內部復原&lt;/td>
 &lt;td>stakeholder 節奏不足&lt;/td>
 &lt;td>status / comms&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/08-incident-response/stakeholder-communication/" data-link-title="8.10 Stakeholder 通訊與外部狀態頁" data-link-desc="把 impact scope、status page、補償政策串成節奏">stakeholder comms&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>客訴比告警早代表系統的外部痛點先於內部訊號出現。這種情境應先補服務健康指標、使用者可感知訊號與 alert runbook，再討論要用哪個監控平台；否則平台上線後仍可能只收集到工程師方便看的資料。&lt;/p></description><content:encoded><![CDATA[<p>觀測、可靠性與事故服務選型的核心責任是把操作風險拆成「看得見、驗得過、接得住」三層能力。<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台</a>處理訊號是否足以支援判讀，<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">可靠性驗證流程</a>處理失敗是否能被安全預演，<a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">事故處理與復盤</a>處理事故是否能被接住、分工與回寫。</p>
<p>這三類服務常被一起採購或一起導入，但它們回答不同問題。觀測平台回答「現在發生什麼」，可靠性工具回答「失敗前能否先驗證」，事故平台回答「事情發生後誰做什麼」。選型時先分清能力層，再比較 vendor、SaaS、OSS 或自建方案，能降低工具堆疊與流程空轉的風險。</p>
<h2 id="選型錨點">選型錨點</h2>
<p>選型錨點是先問服務要降低哪一種操作不確定性。當團隊只知道系統「好像怪怪的」，優先補訊號；當團隊知道風險但缺少安全驗證路徑，優先補可靠性驗證；當團隊知道事故已發生但協作混亂，優先補事故流程。</p>
<table>
  <thead>
      <tr>
          <th>能力層</th>
          <th>核心問題</th>
          <th>對應模組</th>
          <th>常見服務類型</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>訊號層</td>
          <td>發生什麼、影響哪裡</td>
          <td><a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台</a></td>
          <td>telemetry、APM、log、dashboard</td>
      </tr>
      <tr>
          <td>驗證層</td>
          <td>風險能否提前預演</td>
          <td><a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">可靠性驗證流程</a></td>
          <td>CI、load test、chaos、SLO</td>
      </tr>
      <tr>
          <td>響應層</td>
          <td>誰接手、如何收斂</td>
          <td><a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">事故處理與復盤</a></td>
          <td>on-call、IR、status、postmortem</td>
      </tr>
      <tr>
          <td>閉環層</td>
          <td>教訓如何回寫</td>
          <td><a href="/blog/backend/08-incident-response/observability-reliability-incident-loop/" data-link-title="8.11 Observability / Reliability / Incident Response 閉環" data-link-desc="把 04 / 06 / 08 三個模組的雙向反饋串成可判讀循環，定義閉環健康度判讀訊號">觀測、驗證與事故閉環</a></td>
          <td>workflow、action tracking</td>
      </tr>
  </tbody>
</table>
<p>訊號層的責任是讓系統行為可被查詢與判讀。這一層的選型重點是資料模型、查詢能力、關聯能力、保留成本與告警品質；產品名稱排在後面，因為 log、metric、trace 與 error event 是否能互相串接，才是事故時真正影響判讀速度的條件。</p>
<p>驗證層的責任是讓風險在事故前被安全暴露。這一層的選型重點是測試是否接近真實 workload、故障注入是否有停止條件、SLO 是否能被量測、release gate 是否能阻止高風險變更；工具越強，越需要 blast radius 與權限邊界。</p>
<p>響應層的責任是讓事故進入可交接流程。這一層的選型重點是 paging、升級、角色分工、狀態更新、decision log、stakeholder mapping 與 post-incident action tracking；工具的價值來自流程一致性，通知訊息數量只是輔助訊號。</p>
<p>閉環層的責任是把事故與演練教訓回寫到系統設計。這一層可能由 incident platform、ticket system、runbook repository 或內部 workflow 承擔；判準是 action item 是否能被排序、驗證、關閉，並回到訊號治理、可靠性演練或事故流程。</p>
<h2 id="判讀順序">判讀順序</h2>
<p>操作服務選型的穩定順序是「症狀 → 缺口 → 能力 → 工具」。症狀描述使用者痛點或工程痛點，缺口描述目前缺少的判讀或流程，能力描述需要補的系統責任，工具才是最後的落地選項。</p>
<table>
  <thead>
      <tr>
          <th>症狀</th>
          <th>主要缺口</th>
          <th>優先能力</th>
          <th>下一步路由</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>客訴比告警早</td>
          <td>訊號覆蓋不足</td>
          <td>symptom-based alert</td>
          <td><a href="/blog/backend/04-observability/dashboard-alert/" data-link-title="4.4 dashboard 與 alert 設計" data-link-desc="讓 dashboard 與 alert 對應 runbook 與容量趨勢">dashboard 與 alert</a></td>
      </tr>
      <tr>
          <td>事故時 trace 接不上 queue</td>
          <td>關聯線索斷裂</td>
          <td>context propagation</td>
          <td><a href="/blog/backend/04-observability/tracing-context/" data-link-title="4.3 tracing 與 context link" data-link-desc="整理 trace id、span 與跨服務 context propagation">tracing 與 context link</a></td>
      </tr>
      <tr>
          <td>發版後才發現容量曲線崩壞</td>
          <td>失敗前驗證不足</td>
          <td>load / perf gate</td>
          <td><a href="/blog/backend/06-reliability/load-testing/" data-link-title="6.2 load test" data-link-desc="把 production 流量結構轉成可重播壓力情境，定位 saturation 轉折與容量邊界">load test</a></td>
      </tr>
      <tr>
          <td>chaos 實驗影響超出預期</td>
          <td>實驗安全邊界不足</td>
          <td>experiment guardrail</td>
          <td><a href="/blog/backend/06-reliability/experiment-safety-boundary/" data-link-title="6.20 Experiment Safety Boundary" data-link-desc="定義 chaos、load test、DR drill 的 [blast radius](/backend/knowledge-cards/blast-radius/)、停止條件與權限約束">experiment safety boundary</a></td>
      </tr>
      <tr>
          <td>多人同時修事故但決策互相覆蓋</td>
          <td>指揮與紀錄不足</td>
          <td>command / decision log</td>
          <td><a href="/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">incident decision log</a></td>
      </tr>
      <tr>
          <td>對外狀態更新慢於內部復原</td>
          <td>stakeholder 節奏不足</td>
          <td>status / comms</td>
          <td><a href="/blog/backend/08-incident-response/stakeholder-communication/" data-link-title="8.10 Stakeholder 通訊與外部狀態頁" data-link-desc="把 impact scope、status page、補償政策串成節奏">stakeholder comms</a></td>
      </tr>
  </tbody>
</table>
<p>客訴比告警早代表系統的外部痛點先於內部訊號出現。這種情境應先補服務健康指標、使用者可感知訊號與 alert runbook，再討論要用哪個監控平台；否則平台上線後仍可能只收集到工程師方便看的資料。</p>
<p>trace 接不上 queue 代表跨邊界關聯失效。這種情境應先檢查 trace context、correlation id、message metadata 與 sampling 策略，再選擇 OpenTelemetry backend、APM SaaS 或 log search 方案。</p>
<p>發版後才發現容量曲線崩壞代表驗證層缺少 gate。這種情境應先建立 workload model、baseline、回歸門檻與 release gate，再選 load test 工具或 performance dashboard。</p>
<p>chaos 實驗影響超出預期代表驗證工具先於安全邊界。這種情境應先定義 steady state、blast radius、停止條件與授權範圍，再決定使用 chaos mesh、fault proxy 或商業 chaos 平台。</p>
<p>多人同時修事故但決策互相覆蓋代表響應層缺少 command model。這種情境應先定義 incident commander、scribe、owner、decision log 與 handoff，再導入 IR 平台或 chat workflow。</p>
<p>對外狀態更新慢於內部復原代表 stakeholder 節奏不足。這種情境應先定義影響評估、更新頻率、外部狀態頁與客戶溝通責任，再選 status page 或 customer comms 工具。</p>
<h2 id="服務組合策略">服務組合策略</h2>
<p>服務組合策略的核心原則是先選最小閉環，再擴展平台覆蓋。完整閉環至少包含一個可判讀訊號、一個可驗證門檻、一個可接手流程與一個可回寫的 action tracking；缺任一層時，工具組合就會變成單點能力。</p>
<table>
  <thead>
      <tr>
          <th>組合型態</th>
          <th>適合情境</th>
          <th>主要風險</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>雲端原生整合</td>
          <td>團隊集中在單一 cloud provider</td>
          <td>跨雲、跨 SaaS 與高階查詢受限</td>
      </tr>
      <tr>
          <td>OSS 可組裝平台</td>
          <td>團隊有平台工程能力</td>
          <td>維護、升級、容量與成本治理重</td>
      </tr>
      <tr>
          <td>All-in-one SaaS</td>
          <td>團隊需要快速覆蓋與低維運</td>
          <td>成本、資料鎖定與自訂邊界受限</td>
      </tr>
      <tr>
          <td>混合式最小閉環</td>
          <td>既有工具已分散</td>
          <td>整合責任與 ownership 容易模糊</td>
      </tr>
  </tbody>
</table>
<p>雲端原生整合適合雲端邊界清楚的團隊。它能快速取得 infrastructure 訊號、IAM 整合與預設 dashboard，但跨外部 SaaS、跨語言 trace 或高基數探索時，需要提前確認資料出口與查詢能力。</p>
<p>OSS 可組裝平台適合有平台團隊維護 ingestion、storage、query 與 dashboard 的組織。它能降低 vendor lock-in 並保留彈性，但容量規劃、升級、安全修補、保留策略與 on-call 都會變成內部成本。</p>
<p>All-in-one SaaS 適合需要快速建立可觀測、告警與事故協作的團隊。它能把 log、metric、trace、APM、paging 或 workflow 整合在單一產品，但成本模型、資料保留、客製化限制與資料治理要在導入前確認。</p>
<p>混合式最小閉環適合已經有多套工具的團隊。它的重點是定義哪個系統是 alert source、哪個系統是 incident source of truth、哪個系統負責 action item closure；整合邊界比新增工具更重要。</p>
<h2 id="導入順序">導入順序</h2>
<p>導入順序的責任是降低一次導入多套工具的失敗風險。觀測、驗證與事故服務應依照事故風險與團隊成熟度逐層補齊，功能清單只適合放在能力判準之後。</p>
<ol>
<li>先補最小訊號：定義 SLI、error rate、latency、dependency failure、queue lag 與 customer-facing symptom。</li>
<li>再補最小告警與 runbook：讓 alert 指向可執行動作，避免只把噪音送到 on-call。</li>
<li>接著補驗證門檻：把 load、contract、migration、chaos 或 SLO 變成 release 前後的 gate。</li>
<li>然後補事故協作：定義 paging、severity、角色、decision log、status update 與 post-incident review。</li>
<li>最後補閉環治理：把偵測缺口、演練缺口與 action item 回寫到觀測、驗證與事故流程。</li>
</ol>
<p>這個順序讓工具投資跟風險暴露同步。若團隊在沒有基本訊號時先導入 incident workflow，事故流程會缺少證據；若在沒有實驗安全邊界時先導入 chaos 工具，驗證本身會變成風險來源；若在沒有 action tracking 時只做 postmortem，復盤會停在文字紀錄。</p>
<h2 id="交接路由">交接路由</h2>
<p>交接路由的責任是把服務選型判斷送到正確模組。選型章只決定「需要哪一類能力」，後續模組負責欄位、流程、工具與實作細節。</p>
<ul>
<li>需要判斷訊號是否足以支援診斷時，進入 <a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">可觀測性平台</a>。</li>
<li>需要判斷失敗是否能被安全驗證時，進入 <a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">可靠性驗證流程</a>。</li>
<li>需要判斷事故是否能被接住與回寫時，進入 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">事故處理與復盤</a>。</li>
<li>需要比較具體 vendor 時，先讀各模組的 vendors index，再回到本章確認工具是否補到正確能力層。</li>
</ul>
<h2 id="完成判準">完成判準</h2>
<p>本章完成的判準是能把工具需求翻成能力需求。當團隊能說清楚「我們缺的是訊號、驗證、響應還是閉環」，選型討論才適合進入 vendor 比較。</p>
<p>檢查時可以問四個問題：</p>
<ol>
<li>現在的痛點是看不見、驗不過、接不住，還是回寫斷掉？</li>
<li>這個工具補的是哪一層能力，會產生哪些新操作成本？</li>
<li>導入後誰負責維護資料品質、流程品質與 action closure？</li>
<li>如果三個月後事故型態改變，哪個 tripwire 會提醒團隊重新評估？</li>
</ol>
]]></content:encoded></item><item><title>0.14 企業選型案例圖譜</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/enterprise-selection-case-atlas/</link><pubDate>Thu, 07 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/enterprise-selection-case-atlas/</guid><description>&lt;p>企業選型案例圖譜的核心責任是提供「跨規模、跨產業、跨階段」的選型樣本，讓讀者知道同一種技術問題在不同公司會如何被定義、取捨與落地。&lt;/p>
&lt;h2 id="概念定位">概念定位&lt;/h2>
&lt;p>這一頁的責任是回答三件事：這家公司遇到什麼壓力、做了什麼選型決策、代價與回寫是什麼。提供企業層面的選型壓力對照，跟 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cloud-vendor-capability-mapping/" data-link-title="0.19 雲端服務對照地圖（AWS / GCP / Azure）" data-link-desc="把後端能力分類對照到 AWS / GCP / Azure 的具體服務名稱、保留跨雲遷移與選型差異的判讀重點">0.19 雲端服務對照地圖&lt;/a> 是 sibling：本頁是「實際企業怎麼決策」、0.19 是「能力 × vendor 名稱對照」。兩者並讀能避免「光看對照表選 vendor」或「光看案例抄架構」的兩種誤用。&lt;/p>
&lt;p>使用方式是先從你的需求壓力切入，再對照對應案例，而不是先選喜歡的公司再倒推技術。這樣可以避免「抄架構」而忽略上下文差異。&lt;/p>
&lt;h2 id="使用方式">使用方式&lt;/h2>
&lt;ol>
&lt;li>先回到 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0 後端需求分類地圖&lt;/a> 定位你的問題類型。&lt;/li>
&lt;li>用本頁找 2 到 3 個不同規模企業的對照案例。&lt;/li>
&lt;li>把案例中的決策壓力回寫到 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6 成本、風險與選型取捨&lt;/a>。&lt;/li>
&lt;li>再進入對應模組（01-08）看實作與控制面細節。&lt;/li>
&lt;/ol>
&lt;h2 id="案例地圖">案例地圖&lt;/h2>
&lt;p>案例按照「企業型態 × 規模階段」分組，目的是讓你先找到最接近自己情境的壓力來源，再看選型動作。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>企業型態與規模階段&lt;/th>
 &lt;th>企業案例&lt;/th>
 &lt;th>主要選型問題&lt;/th>
 &lt;th>優先回讀章節&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>SaaS（成長期，單體資料庫瓶頸）&lt;/td>
 &lt;td>&lt;a href="https://www.notion.com/blog/sharding-postgres-at-notion">Notion: Sharding Postgres&lt;/a>&lt;/td>
 &lt;td>單體 Postgres 何時拆分成分片架構&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DevTool（成長期，職能拆分）&lt;/td>
 &lt;td>&lt;a href="https://about.gitlab.com/blog/2022/06/02/splitting-database-into-main-and-ci/">GitLab: Splitting Main and CI DB&lt;/a>&lt;/td>
 &lt;td>功能分解如何換取容量與可靠性&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>DevTool（成熟期，升級風險控制）&lt;/td>
 &lt;td>&lt;a href="https://about.gitlab.com/blog/2020/09/11/gitlab-pg-upgrade/">GitLab: Major PostgreSQL Upgrade&lt;/a>&lt;/td>
 &lt;td>高流量環境下升級策略與回退設計&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">06&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Commerce（高速成長，資料庫升級）&lt;/td>
 &lt;td>&lt;a href="https://shopify.engineering/upgrading-mysql-shopify">Shopify: Upgrading MySQL&lt;/a>&lt;/td>
 &lt;td>大規模 MySQL 維運成本與可靠性治理&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Commerce（超大規模，水平擴充）&lt;/td>
 &lt;td>&lt;a href="https://shopify.engineering/blogs/engineering/horizontally-scaling-the-rails-backend-of-shop-app-with-vitess">Shopify: Scaling with Vitess&lt;/a>&lt;/td>
 &lt;td>什麼時候引入 Vitess 以取得水平擴充能力&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Social / Chat（高吞吐事件流）&lt;/td>
 &lt;td>&lt;a href="https://slack.engineering/scaling-slacks-job-queue/">Slack: Scaling Job Queue&lt;/a>&lt;/td>
 &lt;td>高吞吐背景工作為何改採 Kafka + Redis&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">03&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Social（超大規模，多租戶優先序）&lt;/td>
 &lt;td>&lt;a href="https://engineering.fb.com/2021/02/22/production-engineering/foqs-scaling-a-distributed-priority-queue/">Meta: FOQS Distributed Priority Queue&lt;/a>&lt;/td>
 &lt;td>多租戶 priority queue 如何做持久化與隔離&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Ride-hailing（全球規模，監控平台）&lt;/td>
 &lt;td>&lt;a href="https://www.uber.com/en-GB/blog/m3/">Uber: M3 Metrics Platform&lt;/a>&lt;/td>
 &lt;td>單點監控系統何時要走平台化與多租戶存儲&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">04&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>CDN / Security（邊緣規模，可觀測）&lt;/td>
 &lt;td>&lt;a href="https://blog.cloudflare.com/building-cloudflare-on-cloudflare/">Cloudflare: Building Cloudflare on Cloudflare&lt;/a>&lt;/td>
 &lt;td>logs/metrics/traces 如何一起成為操作能力&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Commerce（成熟期，韌性驗證）&lt;/td>
 &lt;td>&lt;a href="https://shopify.engineering/four-steps-creating-effective-game-day-tests">Shopify: Effective Game Day Tests&lt;/a>&lt;/td>
 &lt;td>如何把演練從活動變成驗證制度&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">06&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Commerce（大促前容量治理）&lt;/td>
 &lt;td>&lt;a href="https://shopify.engineering/resiliency-planning-for-high-traffic-events">Shopify: Resiliency Planning for High-Traffic Events&lt;/a>&lt;/td>
 &lt;td>高峰活動前容量與風險如何建模&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/capacity-cost/" data-link-title="6.9 容量與成本邊界" data-link-desc="把容量規劃跟成本約束變成驗證輸入">6.9&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cloud Platform（多租戶隔離）&lt;/td>
 &lt;td>&lt;a href="https://aws.amazon.com/builders-library/workload-isolation-using-shuffle-sharding/">AWS Builders’ Library: Shuffle-sharding&lt;/a>&lt;/td>
 &lt;td>多租戶故障隔離如何影響資料與佇列設計&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Platform（組織擴張，邊界重整）&lt;/td>
 &lt;td>&lt;a href="https://www.uber.com/en-GB/blog/microservice-architecture/">Uber: Domain-Oriented Microservice Architecture&lt;/a>&lt;/td>
 &lt;td>微服務規模變大後如何重新治理邊界與依賴&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Social（儲存成本壓力）&lt;/td>
 &lt;td>&lt;a href="https://engineering.fb.com/2016/08/31/core-infra/myrocks-a-space-and-write-optimized-mysql-database/">Meta: MyRocks&lt;/a>&lt;/td>
 &lt;td>何時用新 storage engine 換取成本與寫入效率&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Social（平台化分片）&lt;/td>
 &lt;td>&lt;a href="https://engineering.fb.com/2020/08/24/production-engineering/scaling-services-with-shard-manager/">Meta: Shard Manager&lt;/a>&lt;/td>
 &lt;td>分片能力何時應該平台化而不是各隊自建&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="類型覆蓋檢查">類型覆蓋檢查&lt;/h2>
&lt;p>案例蒐集的完成條件是覆蓋度，篇數本身沒有意義。每次補案例都用這四個維度檢查缺口。&lt;/p></description><content:encoded><![CDATA[<p>企業選型案例圖譜的核心責任是提供「跨規模、跨產業、跨階段」的選型樣本，讓讀者知道同一種技術問題在不同公司會如何被定義、取捨與落地。</p>
<h2 id="概念定位">概念定位</h2>
<p>這一頁的責任是回答三件事：這家公司遇到什麼壓力、做了什麼選型決策、代價與回寫是什麼。提供企業層面的選型壓力對照，跟 <a href="/blog/backend/00-service-selection/cloud-vendor-capability-mapping/" data-link-title="0.19 雲端服務對照地圖（AWS / GCP / Azure）" data-link-desc="把後端能力分類對照到 AWS / GCP / Azure 的具體服務名稱、保留跨雲遷移與選型差異的判讀重點">0.19 雲端服務對照地圖</a> 是 sibling：本頁是「實際企業怎麼決策」、0.19 是「能力 × vendor 名稱對照」。兩者並讀能避免「光看對照表選 vendor」或「光看案例抄架構」的兩種誤用。</p>
<p>使用方式是先從你的需求壓力切入，再對照對應案例，而不是先選喜歡的公司再倒推技術。這樣可以避免「抄架構」而忽略上下文差異。</p>
<h2 id="使用方式">使用方式</h2>
<ol>
<li>先回到 <a href="/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0 後端需求分類地圖</a> 定位你的問題類型。</li>
<li>用本頁找 2 到 3 個不同規模企業的對照案例。</li>
<li>把案例中的決策壓力回寫到 <a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6 成本、風險與選型取捨</a>。</li>
<li>再進入對應模組（01-08）看實作與控制面細節。</li>
</ol>
<h2 id="案例地圖">案例地圖</h2>
<p>案例按照「企業型態 × 規模階段」分組，目的是讓你先找到最接近自己情境的壓力來源，再看選型動作。</p>
<table>
  <thead>
      <tr>
          <th>企業型態與規模階段</th>
          <th>企業案例</th>
          <th>主要選型問題</th>
          <th>優先回讀章節</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>SaaS（成長期，單體資料庫瓶頸）</td>
          <td><a href="https://www.notion.com/blog/sharding-postgres-at-notion">Notion: Sharding Postgres</a></td>
          <td>單體 Postgres 何時拆分成分片架構</td>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a>、<a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a></td>
      </tr>
      <tr>
          <td>DevTool（成長期，職能拆分）</td>
          <td><a href="https://about.gitlab.com/blog/2022/06/02/splitting-database-into-main-and-ci/">GitLab: Splitting Main and CI DB</a></td>
          <td>功能分解如何換取容量與可靠性</td>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a>、<a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
      </tr>
      <tr>
          <td>DevTool（成熟期，升級風險控制）</td>
          <td><a href="https://about.gitlab.com/blog/2020/09/11/gitlab-pg-upgrade/">GitLab: Major PostgreSQL Upgrade</a></td>
          <td>高流量環境下升級策略與回退設計</td>
          <td><a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a>、<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">06</a></td>
      </tr>
      <tr>
          <td>Commerce（高速成長，資料庫升級）</td>
          <td><a href="https://shopify.engineering/upgrading-mysql-shopify">Shopify: Upgrading MySQL</a></td>
          <td>大規模 MySQL 維運成本與可靠性治理</td>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a>、<a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
      </tr>
      <tr>
          <td>Commerce（超大規模，水平擴充）</td>
          <td><a href="https://shopify.engineering/blogs/engineering/horizontally-scaling-the-rails-backend-of-shop-app-with-vitess">Shopify: Scaling with Vitess</a></td>
          <td>什麼時候引入 Vitess 以取得水平擴充能力</td>
          <td><a href="/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1</a>、<a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a></td>
      </tr>
      <tr>
          <td>Social / Chat（高吞吐事件流）</td>
          <td><a href="https://slack.engineering/scaling-slacks-job-queue/">Slack: Scaling Job Queue</a></td>
          <td>高吞吐背景工作為何改採 Kafka + Redis</td>
          <td><a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3</a>、<a href="/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">03</a></td>
      </tr>
      <tr>
          <td>Social（超大規模，多租戶優先序）</td>
          <td><a href="https://engineering.fb.com/2021/02/22/production-engineering/foqs-scaling-a-distributed-priority-queue/">Meta: FOQS Distributed Priority Queue</a></td>
          <td>多租戶 priority queue 如何做持久化與隔離</td>
          <td><a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3</a>、<a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
      </tr>
      <tr>
          <td>Ride-hailing（全球規模，監控平台）</td>
          <td><a href="https://www.uber.com/en-GB/blog/m3/">Uber: M3 Metrics Platform</a></td>
          <td>單點監控系統何時要走平台化與多租戶存儲</td>
          <td><a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4</a>、<a href="/blog/backend/04-observability/" data-link-title="模組四：可觀測性平台" data-link-desc="整理 log、metric、trace、dashboard 與 alert 的後端操作實務">04</a></td>
      </tr>
      <tr>
          <td>CDN / Security（邊緣規模，可觀測）</td>
          <td><a href="https://blog.cloudflare.com/building-cloudflare-on-cloudflare/">Cloudflare: Building Cloudflare on Cloudflare</a></td>
          <td>logs/metrics/traces 如何一起成為操作能力</td>
          <td><a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4</a>、<a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20</a></td>
      </tr>
      <tr>
          <td>Commerce（成熟期，韌性驗證）</td>
          <td><a href="https://shopify.engineering/four-steps-creating-effective-game-day-tests">Shopify: Effective Game Day Tests</a></td>
          <td>如何把演練從活動變成驗證制度</td>
          <td><a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a>、<a href="/blog/backend/06-reliability/" data-link-title="模組六：可靠性驗證流程" data-link-desc="用 SRE 領域詞彙建問題節點、以服務級案例庫累積驗證脈絡，先建概念與案例庫再進實作交接">06</a></td>
      </tr>
      <tr>
          <td>Commerce（大促前容量治理）</td>
          <td><a href="https://shopify.engineering/resiliency-planning-for-high-traffic-events">Shopify: Resiliency Planning for High-Traffic Events</a></td>
          <td>高峰活動前容量與風險如何建模</td>
          <td><a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a>、<a href="/blog/backend/06-reliability/capacity-cost/" data-link-title="6.9 容量與成本邊界" data-link-desc="把容量規劃跟成本約束變成驗證輸入">6.9</a></td>
      </tr>
      <tr>
          <td>Cloud Platform（多租戶隔離）</td>
          <td><a href="https://aws.amazon.com/builders-library/workload-isolation-using-shuffle-sharding/">AWS Builders’ Library: Shuffle-sharding</a></td>
          <td>多租戶故障隔離如何影響資料與佇列設計</td>
          <td><a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a>、<a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a></td>
      </tr>
      <tr>
          <td>Platform（組織擴張，邊界重整）</td>
          <td><a href="https://www.uber.com/en-GB/blog/microservice-architecture/">Uber: Domain-Oriented Microservice Architecture</a></td>
          <td>微服務規模變大後如何重新治理邊界與依賴</td>
          <td><a href="/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0</a>、<a href="/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1</a></td>
      </tr>
      <tr>
          <td>Social（儲存成本壓力）</td>
          <td><a href="https://engineering.fb.com/2016/08/31/core-infra/myrocks-a-space-and-write-optimized-mysql-database/">Meta: MyRocks</a></td>
          <td>何時用新 storage engine 換取成本與寫入效率</td>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a>、<a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
      </tr>
      <tr>
          <td>Social（平台化分片）</td>
          <td><a href="https://engineering.fb.com/2020/08/24/production-engineering/scaling-services-with-shard-manager/">Meta: Shard Manager</a></td>
          <td>分片能力何時應該平台化而不是各隊自建</td>
          <td><a href="/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1</a>、<a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a></td>
      </tr>
  </tbody>
</table>
<h2 id="類型覆蓋檢查">類型覆蓋檢查</h2>
<p>案例蒐集的完成條件是覆蓋度，篇數本身沒有意義。每次補案例都用這四個維度檢查缺口。</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>已覆蓋示例</th>
          <th>常見缺口</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>企業型態</td>
          <td>SaaS、DevTool、Commerce、Social、Ride-hailing、Cloud Platform、CDN/Security</td>
          <td>FinTech、Gaming、Healthcare、製造業平台</td>
      </tr>
      <tr>
          <td>規模階段</td>
          <td>成長期、成熟期、超大規模</td>
          <td>早期產品（小團隊）與跨國多區治理</td>
      </tr>
      <tr>
          <td>選型問題類型</td>
          <td>資料分片、佇列架構、可觀測平台、容量韌性、多租戶隔離、組織邊界</td>
          <td>成本治理、合規（PCI/SOX/GDPR）與資料主權</td>
      </tr>
      <tr>
          <td>決策生命週期</td>
          <td>遷移、升級、平台化、演練</td>
          <td>退場策略（decommission）與 vendor 轉移</td>
      </tr>
  </tbody>
</table>
<h2 id="第一批缺口回填清單">第一批缺口回填清單</h2>
<p>第一批回填先補三個目前缺口最大的產業類型，目標是讓案例圖譜從「網路平台公司視角」擴展到「高合規與高事件密度」場景。</p>
<table>
  <thead>
      <tr>
          <th>缺口類型</th>
          <th>優先蒐集的選型議題</th>
          <th>回寫章節起點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>FinTech</td>
          <td>合規壓力下的資料分區、審計留存、變更放行與風險隔離</td>
          <td><a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a>、<a href="/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8</a></td>
      </tr>
      <tr>
          <td>Gaming</td>
          <td>高峰事件流、低延遲路徑、規則推送風險與跨區回復</td>
          <td><a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3</a>、<a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a></td>
      </tr>
      <tr>
          <td>Healthcare</td>
          <td>資料主權、存取邊界、可追溯性與災難回復流程</td>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a>、<a href="/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8</a></td>
      </tr>
  </tbody>
</table>
<p>這份清單的用途是定義下一輪蒐集方向。每補一個案例，至少要同步回寫一個 04 觀測章節、一個 06 驗證章節與一個 08 事故章節，避免案例只停留在選型敘事。</p>
<h2 id="第一批案例清單fintech--gaming--healthcare">第一批案例清單（FinTech / Gaming / Healthcare）</h2>
<p>第一批案例的責任是先補齊產業覆蓋，並建立可直接回寫到 04/06/08 的共同語言。</p>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>企業案例</th>
          <th>主要選型問題</th>
          <th>優先回讀章節</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>FinTech</td>
          <td><a href="https://stripe.com/blog">Stripe: Scaling Payments APIs</a></td>
          <td>金流 API 的一致性、冪等與放行門檻</td>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a>、<a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
      </tr>
      <tr>
          <td>FinTech</td>
          <td><a href="https://www.adyen.com/knowledge-hub">Adyen Engineering</a></td>
          <td>合規要求下的資料保留、稽核追溯與跨區部署</td>
          <td><a href="/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8</a>、<a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a></td>
      </tr>
      <tr>
          <td>Gaming</td>
          <td><a href="https://technology.riotgames.com/">Riot Games Tech Blog</a></td>
          <td>高峰活動期間的低延遲路徑與跨區容量治理</td>
          <td><a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a>、<a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3</a></td>
      </tr>
      <tr>
          <td>Gaming</td>
          <td><a href="https://dev.epicgames.com/community/">Epic Games Unreal Engine / Fortnite Scale Articles</a></td>
          <td>大型即時服務的事件流、匹配與故障隔離</td>
          <td><a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3</a>、<a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
      </tr>
      <tr>
          <td>Healthcare</td>
          <td><a href="https://cloud.google.com/architecture/healthcare-life-sciences">Google Cloud Healthcare Architecture Guides</a></td>
          <td>資料主權、存取邊界與審計證據鏈</td>
          <td><a href="/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8</a>、<a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a></td>
      </tr>
      <tr>
          <td>Healthcare</td>
          <td><a href="https://aws.amazon.com/health/">AWS Healthcare and Life Sciences Architecture</a></td>
          <td>多區備援下的資料保護與恢復順序</td>
          <td><a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a>、<a href="/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8</a></td>
      </tr>
  </tbody>
</table>
<p>這批案例以「產業壓力類型」為主，不以單一公司唯一做法當標準答案。後續第二批再補製造業平台與跨國多區治理案例。</p>
<h2 id="對應正文入口">對應正文入口</h2>
<p>第一批缺口已補對應正文，圖譜可直接連到可回寫文章：</p>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>正文入口</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>FinTech</td>
          <td><a href="/blog/backend/00-service-selection/cases/fintech-compliance-and-selection-pressure/" data-link-title="FinTech：合規壓力下的後端選型" data-link-desc="在審計、留存與交易正確性要求下，如何平衡成本、風險與交付速度。">0.C1 FinTech：合規壓力下的後端選型</a></td>
      </tr>
      <tr>
          <td>Gaming</td>
          <td><a href="/blog/backend/00-service-selection/cases/gaming-peak-traffic-and-isolation/" data-link-title="Gaming：高峰流量與隔離邊界選型" data-link-desc="大型活動流量下，如何在低延遲與穩定性之間做可持續取捨。">0.C2 Gaming：高峰流量與隔離邊界選型</a></td>
      </tr>
      <tr>
          <td>Healthcare</td>
          <td><a href="/blog/backend/00-service-selection/cases/healthcare-data-sovereignty-and-recovery/" data-link-title="Healthcare：資料主權與回復順序選型" data-link-desc="醫療場景下，如何把資料主權、存取邊界與災難回復放進同一套決策。">0.C3 Healthcare：資料主權與回復順序選型</a></td>
      </tr>
  </tbody>
</table>
<p>營運一段時間後的語言、工具或架構轉換案例，見 <a href="/blog/backend/00-service-selection/cases/post-scale-migration-language-tool-architecture/" data-link-title="營運後技術轉換：語言、工具與架構何時該換" data-link-desc="服務營運一段時間後，如何判讀何時該轉語言、工具或架構，並用案例說明轉換動機。">0.C4 營運後技術轉換</a>。</p>
<h2 id="讀法提醒">讀法提醒</h2>
<p>同一家公司不代表同一答案。公司不同時期的選型結論可能相反，因為負載、組織、預算與產品階段已經改變。把案例當成「決策壓力樣本」，比當成「標準答案」更可靠。</p>
<p>當兩個案例做出不同選擇，先檢查四件事：流量形狀、資料生命週期、失敗代價、維運能力。這四件事通常比語言與框架更能解釋選型差異。</p>
]]></content:encoded></item><item><title>0.15 跨模組 Checkout Episode：從資料寫入到觀測證據</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/cross-module-checkout-episode/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/cross-module-checkout-episode/</guid><description>&lt;p>跨模組 checkout episode 的核心責任是用同一條服務路徑，把資料庫、快取、訊息佇列與可觀測性四個模組的責任串在一起。讀者看完後能判斷一次 checkout 請求觸發的狀態寫入、快取失效、事件發布與訊號記錄分別由誰負責，以及任何一層失敗時該看哪組訊號。&lt;/p>
&lt;p>本篇與 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/operations-control-vertical-slice/" data-link-title="0.13 操作控制 vertical slice 實作入口" data-link-desc="用一個服務串起觀測證據、可靠性驗證、事故決策與回寫閉環">0.13 操作控制 vertical slice&lt;/a> 互補：0.13 走的是 04/06/08 的操作控制閉環（觀測 → 驗證 → 事故 → 回寫），本篇走的是 01/02/03/04 的資料基礎設施鏈（狀態 → 副本 → 事件 → 訊號）。&lt;/p>
&lt;h2 id="服務路徑">服務路徑&lt;/h2>
&lt;p>一次 checkout 的最小路徑：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">client
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> → checkout-api
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> → order-db (01: 寫入正式狀態)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl"> → cache invalidation (02: 失效商品快取)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> → event publish (03: 發布 order.created 事件)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> → telemetry (04: span / log / metric 記錄)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>這條路徑刻意簡化。真實系統可能還有 payment adapter、inventory lock、notification service、search index sync 等環節，但四層串聯的責任分工用最小路徑就能說明。後續章節把各層展開。&lt;/p>
&lt;h2 id="第一層資料庫寫入01">第一層：資料庫寫入（01）&lt;/h2>
&lt;p>Checkout 的正式狀態是訂單紀錄。這筆寫入必須在 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/transaction-boundary/" data-link-title="1.3 Transaction 與一致性邊界" data-link-desc="交易邊界、isolation level、retry 策略、distributed transaction（2PC、Saga）與跨 region 強一致取捨">transaction boundary&lt;/a> 內完成，確保訂單、明細與付款紀錄一起成功或一起失敗。&lt;/p>
&lt;p>&lt;strong>責任邊界&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>訂單狀態是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth&lt;/a>，快取和事件都是下游副本&lt;/li>
&lt;li>Transaction 範圍盡量小：寫入訂單 + 明細 + outbox record，不在同一個 transaction 裡做外部 API 呼叫&lt;/li>
&lt;li>Schema 需要支援狀態演進：訂單從 &lt;code>pending&lt;/code> → &lt;code>paid&lt;/code> → &lt;code>shipped&lt;/code> 的欄位設計見 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/schema-migration-rollout-evidence/" data-link-title="1.7 Schema Migration Rollout 證據（Schema Migration Rollout Evidence）實作示範" data-link-desc="以訂單付款狀態欄位演進示範 schema migration 如何產出 evidence、release gate 與 incident decision log。">1.7 schema migration rollout evidence&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>失敗判讀&lt;/strong>：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>失敗訊號&lt;/th>
 &lt;th>判讀&lt;/th>
 &lt;th>下一步&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Transaction timeout&lt;/td>
 &lt;td>連線池飽和或長 transaction 鎖等待&lt;/td>
 &lt;td>回 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/high-concurrency-access/" data-link-title="1.1 高併發下的 SQL 讀寫邊界" data-link-desc="說明高併發服務如何共用資料庫 client、控制 transaction、管理 connection pool、避免資料庫成為瓶頸">1.1 高併發讀寫邊界&lt;/a> 檢查連線池與 transaction 範圍&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Deadlock&lt;/td>
 &lt;td>多個 checkout 同時更新重疊資源&lt;/td>
 &lt;td>回 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/transaction-boundary/" data-link-title="1.3 Transaction 與一致性邊界" data-link-desc="交易邊界、isolation level、retry 策略、distributed transaction（2PC、Saga）與跨 region 強一致取捨">1.3 transaction boundary&lt;/a> 檢查 lock ordering&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Schema migration 中斷&lt;/td>
 &lt;td>欄位變更與正在執行的寫入衝突&lt;/td>
 &lt;td>回 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6 migration playbook&lt;/a> 確認 expand/contract 流程&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>交接給下一層的資訊&lt;/strong>：transaction commit 成功後，訂單 ID 與狀態就緒。Outbox record 已寫入同一個 transaction。&lt;/p></description><content:encoded><![CDATA[<p>跨模組 checkout episode 的核心責任是用同一條服務路徑，把資料庫、快取、訊息佇列與可觀測性四個模組的責任串在一起。讀者看完後能判斷一次 checkout 請求觸發的狀態寫入、快取失效、事件發布與訊號記錄分別由誰負責，以及任何一層失敗時該看哪組訊號。</p>
<p>本篇與 <a href="/blog/backend/00-service-selection/operations-control-vertical-slice/" data-link-title="0.13 操作控制 vertical slice 實作入口" data-link-desc="用一個服務串起觀測證據、可靠性驗證、事故決策與回寫閉環">0.13 操作控制 vertical slice</a> 互補：0.13 走的是 04/06/08 的操作控制閉環（觀測 → 驗證 → 事故 → 回寫），本篇走的是 01/02/03/04 的資料基礎設施鏈（狀態 → 副本 → 事件 → 訊號）。</p>
<h2 id="服務路徑">服務路徑</h2>
<p>一次 checkout 的最小路徑：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">client
</span></span><span class="line"><span class="ln">2</span><span class="cl">  → checkout-api
</span></span><span class="line"><span class="ln">3</span><span class="cl">    → order-db          (01: 寫入正式狀態)
</span></span><span class="line"><span class="ln">4</span><span class="cl">    → cache invalidation (02: 失效商品快取)
</span></span><span class="line"><span class="ln">5</span><span class="cl">    → event publish      (03: 發布 order.created 事件)
</span></span><span class="line"><span class="ln">6</span><span class="cl">    → telemetry          (04: span / log / metric 記錄)</span></span></code></pre></div><p>這條路徑刻意簡化。真實系統可能還有 payment adapter、inventory lock、notification service、search index sync 等環節，但四層串聯的責任分工用最小路徑就能說明。後續章節把各層展開。</p>
<h2 id="第一層資料庫寫入01">第一層：資料庫寫入（01）</h2>
<p>Checkout 的正式狀態是訂單紀錄。這筆寫入必須在 <a href="/blog/backend/01-database/transaction-boundary/" data-link-title="1.3 Transaction 與一致性邊界" data-link-desc="交易邊界、isolation level、retry 策略、distributed transaction（2PC、Saga）與跨 region 強一致取捨">transaction boundary</a> 內完成，確保訂單、明細與付款紀錄一起成功或一起失敗。</p>
<p><strong>責任邊界</strong>：</p>
<ul>
<li>訂單狀態是 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a>，快取和事件都是下游副本</li>
<li>Transaction 範圍盡量小：寫入訂單 + 明細 + outbox record，不在同一個 transaction 裡做外部 API 呼叫</li>
<li>Schema 需要支援狀態演進：訂單從 <code>pending</code> → <code>paid</code> → <code>shipped</code> 的欄位設計見 <a href="/blog/backend/01-database/schema-migration-rollout-evidence/" data-link-title="1.7 Schema Migration Rollout 證據（Schema Migration Rollout Evidence）實作示範" data-link-desc="以訂單付款狀態欄位演進示範 schema migration 如何產出 evidence、release gate 與 incident decision log。">1.7 schema migration rollout evidence</a></li>
</ul>
<p><strong>失敗判讀</strong>：</p>
<table>
  <thead>
      <tr>
          <th>失敗訊號</th>
          <th>判讀</th>
          <th>下一步</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Transaction timeout</td>
          <td>連線池飽和或長 transaction 鎖等待</td>
          <td>回 <a href="/blog/backend/01-database/high-concurrency-access/" data-link-title="1.1 高併發下的 SQL 讀寫邊界" data-link-desc="說明高併發服務如何共用資料庫 client、控制 transaction、管理 connection pool、避免資料庫成為瓶頸">1.1 高併發讀寫邊界</a> 檢查連線池與 transaction 範圍</td>
      </tr>
      <tr>
          <td>Deadlock</td>
          <td>多個 checkout 同時更新重疊資源</td>
          <td>回 <a href="/blog/backend/01-database/transaction-boundary/" data-link-title="1.3 Transaction 與一致性邊界" data-link-desc="交易邊界、isolation level、retry 策略、distributed transaction（2PC、Saga）與跨 region 強一致取捨">1.3 transaction boundary</a> 檢查 lock ordering</td>
      </tr>
      <tr>
          <td>Schema migration 中斷</td>
          <td>欄位變更與正在執行的寫入衝突</td>
          <td>回 <a href="/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6 migration playbook</a> 確認 expand/contract 流程</td>
      </tr>
  </tbody>
</table>
<p><strong>交接給下一層的資訊</strong>：transaction commit 成功後，訂單 ID 與狀態就緒。Outbox record 已寫入同一個 transaction。</p>
<h2 id="第二層快取失效02">第二層：快取失效（02）</h2>
<p>訂單成功後，商品庫存或價格的快取副本可能已經過期。快取失效的責任是讓後續讀取拿到正確狀態，同時保護資料庫不被回源壓力打穿。</p>
<p><strong>責任邊界</strong>：</p>
<ul>
<li>快取是 <a href="/blog/backend/02-cache-redis/cache-copy-freshness-boundary/" data-link-title="2.7 Cache Copy Boundary 與 Freshness" data-link-desc="說明快取何時只是可重建副本，何時會影響交易、權限或配額正確性。">可重建副本</a>，資料來源是資料庫的正式狀態。失效後的 cache miss 會回源到資料庫</li>
<li>失效策略用 <a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">cache aside</a>：寫入後主動 invalidate，下次讀取時 lazy reload</li>
<li>Invalidation 的順序：先 invalidate 應用層快取（Redis），再考慮是否需要 purge CDN 層（若商品頁有 edge cache）</li>
</ul>
<p><strong>失敗判讀</strong>：</p>
<table>
  <thead>
      <tr>
          <th>失敗訊號</th>
          <th>判讀</th>
          <th>下一步</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Invalidation 失敗但 DB 已 commit</td>
          <td>快取短暫提供舊資料，freshness window 內自動修正</td>
          <td>確認 <a href="/blog/backend/02-cache-redis/ttl-eviction/" data-link-title="2.3 TTL 與 eviction" data-link-desc="整理過期策略、容量控制與熱點資料">TTL</a> 是否足夠短，或補 retry</td>
      </tr>
      <tr>
          <td>Cache stampede</td>
          <td>大量 invalidation 同時觸發 origin 回源</td>
          <td>回 <a href="/blog/backend/02-cache-redis/cache-migration-stampede-rollback/" data-link-title="2.9 Cache Migration 與 Stampede Rollback（實作示範）" data-link-desc="以商品詳情與價格快取示範 cache migration 如何交付 evidence package、release gate 與 incident decision log。">2.9 cache migration stampede rollback</a> 補 singleflight 或 lock</td>
      </tr>
      <tr>
          <td>Hot key 集中失效</td>
          <td>單一商品被大量並發 checkout 同時 invalidate</td>
          <td>回 <a href="/blog/backend/02-cache-redis/high-concurrency-access/" data-link-title="2.1 高併發下的 Redis 讀寫邊界" data-link-desc="說明高併發服務如何共用 Redis client、控制 pipeline 與避免 cache stampede">2.1 高併發讀寫邊界</a> 檢查 hot key 分散策略</td>
      </tr>
  </tbody>
</table>
<p><strong>交接給下一層的資訊</strong>：快取失效完成（或 TTL 保底）。接下來的事件發布不依賴快取狀態 — 事件內容來自 DB 寫入結果。</p>
<h2 id="第三層事件發布03">第三層：事件發布（03）</h2>
<p>訂單寫入後，<code>order.created</code> 事件需要傳遞到下游：通知服務寄信、庫存服務更新、搜尋索引同步、分析管道記錄。這些下游不在 checkout request 內完成，要用非同步傳遞。</p>
<p><strong>責任邊界</strong>：</p>
<ul>
<li>事件發布與 DB 寫入的一致性用 <a href="/blog/backend/03-message-queue/outbox-pattern/" data-link-title="3.3 outbox pattern 與發佈一致性" data-link-desc="把 transaction 與 event publish 分離">outbox pattern</a>：outbox record 在 DB transaction 內寫入，poller 或 CDC 負責把 record 發到 broker</li>
<li>Broker 保證 <a href="/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">at-least-once delivery</a>，consumer 需要做 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 處理</li>
<li>Event contract（schema、idempotency key、replay window）見 <a href="/blog/backend/03-message-queue/event-contract-replay-boundary/" data-link-title="3.7 Event Contract 與 Replay Boundary" data-link-desc="說明 event schema、idempotency key、replay window 與補償如何先於 broker 選型。">3.7 event contract replay boundary</a></li>
</ul>
<p><strong>失敗判讀</strong>：</p>
<table>
  <thead>
      <tr>
          <th>失敗訊號</th>
          <th>判讀</th>
          <th>下一步</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Outbox poller 延遲</td>
          <td>事件延遲但不遺失，DB 已 commit</td>
          <td>監控 outbox table 的 pending row count，回 <a href="/blog/backend/03-message-queue/outbox-pattern/" data-link-title="3.3 outbox pattern 與發佈一致性" data-link-desc="把 transaction 與 event publish 分離">3.3 outbox pattern</a></td>
      </tr>
      <tr>
          <td>Consumer lag 上升</td>
          <td>下游處理速度跟不上，事件在 broker 堆積</td>
          <td>回 <a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer design</a> 檢查 consumer 數量與 backpressure</td>
      </tr>
      <tr>
          <td>DLQ 堆積</td>
          <td>毒訊息或下游持續失敗，已超過 retry 預算</td>
          <td>回 <a href="/blog/backend/03-message-queue/queue-consumer-retry-replay-handoff/" data-link-title="3.8 Queue Consumer Retry 與 Replay Handoff（實作示範）" data-link-desc="以 order_created consumer 示範 queue 路徑如何交付 idempotency evidence、DLQ handling、replay runbook 與 incident decision log。">3.8 retry replay handoff</a> 啟動 DLQ drain runbook</td>
      </tr>
      <tr>
          <td>重複事件造成下游重複副作用</td>
          <td>Consumer idempotency 沒擋住</td>
          <td>回 <a href="/blog/backend/03-message-queue/processing-recovery-semantics/" data-link-title="3.6 Processing Semantics 與 Recovery Semantics" data-link-desc="說明投遞成功、處理成功與恢復成功為何是三個不同判斷。">3.6 processing recovery semantics</a> 確認去重機制</td>
      </tr>
  </tbody>
</table>
<p><strong>交接給下一層的資訊</strong>：事件已發到 broker，每一步（publish、ack、consume、DLQ）都需要觀測訊號。</p>
<h2 id="第四層觀測訊號04">第四層：觀測訊號（04）</h2>
<p>以上三層的每一步都需要被記錄成可查詢的訊號。Checkout 路徑的觀測責任是讓事故判讀者能用同一組 trace ID 串起完整鏈路。</p>
<p><strong>責任邊界</strong>：</p>
<ul>
<li><a href="/blog/backend/04-observability/tracing-context/" data-link-title="4.3 tracing 與 context link" data-link-desc="整理 trace id、span 與跨服務 context propagation">Trace context</a> 從 client 一路 propagate 到 consumer，跨 sync（HTTP）與 async（queue）邊界</li>
<li><a href="/blog/backend/04-observability/log-schema/" data-link-title="4.1 log schema 與搜尋規劃" data-link-desc="整理 log 欄位、索引與搜尋策略">Log schema</a> 使用統一欄位：<code>order_id</code>、<code>trace_id</code>、<code>tenant_id</code>、<code>region</code></li>
<li><a href="/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">Metrics</a> 覆蓋三組 SLI：checkout latency（p50/p95/p99）、checkout error rate、event publish lag</li>
<li><a href="/blog/backend/04-observability/dashboard-alert/" data-link-title="4.4 dashboard 與 alert 設計" data-link-desc="讓 dashboard 與 alert 對應 runbook 與容量趨勢">Dashboard</a> 把上述三組 SLI 放在同一個 checkout 服務面板</li>
<li><a href="/blog/backend/04-observability/checkout-api-evidence-package/" data-link-title="4.22 Checkout API Evidence Package 實作示範" data-link-desc="用 checkout 路徑示範 evidence package 如何交接給 release gate 與 incident decision。">Evidence package</a> 把查詢、時間窗、資料品質與 owner 打包成可交接證據</li>
</ul>
<p><strong>失敗判讀</strong>：</p>
<table>
  <thead>
      <tr>
          <th>失敗訊號</th>
          <th>判讀</th>
          <th>下一步</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Trace 在 DB commit 後斷鏈</td>
          <td>Context propagation 沒跨到 async 邊界</td>
          <td>回 <a href="/blog/backend/04-observability/tracing-context/" data-link-title="4.3 tracing 與 context link" data-link-desc="整理 trace id、span 與跨服務 context propagation">4.3 tracing context</a> 補 queue span link</td>
      </tr>
      <tr>
          <td>Checkout metric 正常但客訴增加</td>
          <td>觀測盲區或 sampling 偏差</td>
          <td>回 <a href="/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">4.17 telemetry data quality</a> 標示 known gap</td>
      </tr>
      <tr>
          <td>Alert 太吵但真正事件沒被抓到</td>
          <td>告警粒度與閾值設計問題</td>
          <td>回 <a href="/blog/backend/04-observability/dashboard-alert/" data-link-title="4.4 dashboard 與 alert 設計" data-link-desc="讓 dashboard 與 alert 對應 runbook 與容量趨勢">4.4 dashboard alert</a> 調整 symptom-based alert</td>
      </tr>
      <tr>
          <td>訊號延遲導致事故判讀困難</td>
          <td>Pipeline ingest delay 或 metric scrape interval 太長</td>
          <td>回 <a href="/blog/backend/04-observability/telemetry-pipeline/" data-link-title="4.11 Telemetry Pipeline 架構" data-link-desc="把 log / metric / trace 的 agent → collector → ingest → storage → query 分層治理">4.11 telemetry pipeline</a> 檢查 pipeline 健康</td>
      </tr>
  </tbody>
</table>
<h2 id="四層交接總覽">四層交接總覽</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">┌─────────────┐    commit     ┌──────────────┐
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">│  01 DB      │──────────────→│  02 Cache    │
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">│  order-db   │    ok         │  invalidate  │
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">│  write      │               │  product key │
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">└──────┬──────┘               └──────────────┘
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">       │ outbox
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">       │ record
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">       ▼
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">┌─────────────┐
</span></span><span class="line"><span class="ln">10</span><span class="cl">│  03 Event   │
</span></span><span class="line"><span class="ln">11</span><span class="cl">│  publish    │
</span></span><span class="line"><span class="ln">12</span><span class="cl">│  order.     │
</span></span><span class="line"><span class="ln">13</span><span class="cl">│  created    │
</span></span><span class="line"><span class="ln">14</span><span class="cl">└─────────────┘
</span></span><span class="line"><span class="ln">15</span><span class="cl">       │
</span></span><span class="line"><span class="ln">16</span><span class="cl">       │ all layers emit
</span></span><span class="line"><span class="ln">17</span><span class="cl">       ▼
</span></span><span class="line"><span class="ln">18</span><span class="cl">┌──────────────────────────┐
</span></span><span class="line"><span class="ln">19</span><span class="cl">│  04 Observability        │
</span></span><span class="line"><span class="ln">20</span><span class="cl">│  span + log + metric     │
</span></span><span class="line"><span class="ln">21</span><span class="cl">│  per layer               │
</span></span><span class="line"><span class="ln">22</span><span class="cl">└──────────────────────────┘</span></span></code></pre></div><p>每一層都有明確的失敗判讀與交接資訊。四層合在一起的判讀順序是：先看 04 的 trace 確認斷點在哪一層，再進那一層的失敗訊號表。</p>
<h2 id="跨層失敗場景">跨層失敗場景</h2>
<p>單層失敗表只處理各自的責任。跨層失敗需要同時看多組訊號：</p>
<h3 id="db-commit-成功但快取沒失效且事件沒發出">DB commit 成功，但快取沒失效且事件沒發出</h3>
<p>原因通常是 outbox poller 和 cache invalidation 在同一個 request 內串行、前者失敗後沒做到後者。判讀順序：</p>
<ol>
<li>04 的 trace 看 checkout span 是否有 error tag</li>
<li>01 的 outbox table 看 pending row 是否堆積</li>
<li>02 的 cache key 是否仍是舊值（TTL 保底正常時可接受）</li>
</ol>
<p>修正方向：invalidation 和 outbox 解耦 — invalidation 在 DB commit 後同步執行（失敗可 retry），outbox 非同步由 poller 負責。兩者不應互相阻塞。</p>
<h3 id="event-consumer-重複處理造成庫存扣兩次">Event consumer 重複處理造成庫存扣兩次</h3>
<p>原因是 consumer 的 idempotency 沒做好，broker redelivery 導致重複副作用。判讀順序：</p>
<ol>
<li>04 的 consumer span 看 redelivery count</li>
<li>03 的 DLQ 看是否有 poison message</li>
<li>01 的 inventory table 看同一 order_id 是否有多筆扣減</li>
</ol>
<p>修正方向：回 <a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4 consumer design</a> 補 idempotency key 驗證，用 order_id 當去重鍵。</p>
<h3 id="checkout-latency-上升但-db-和-cache-都正常">Checkout latency 上升但 DB 和 cache 都正常</h3>
<p>原因可能是 outbox poller 或 event publish 在 request path 內同步等待（設計錯誤）。判讀順序：</p>
<ol>
<li>04 的 checkout span 看 child span 時間分布</li>
<li>確認 event publish 是否在 request 返回前完成（不該）</li>
<li>如果是，回到 03 確認 outbox pattern 是否正確實作（寫 outbox record 應在 DB transaction 內、publish 應由 poller 異步執行）</li>
</ol>
<h2 id="各模組回讀路由">各模組回讀路由</h2>
<table>
  <thead>
      <tr>
          <th>層</th>
          <th>主要回讀章節</th>
          <th>回讀時機</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>01 DB</td>
          <td><a href="/blog/backend/01-database/high-concurrency-access/" data-link-title="1.1 高併發下的 SQL 讀寫邊界" data-link-desc="說明高併發服務如何共用資料庫 client、控制 transaction、管理 connection pool、避免資料庫成為瓶頸">1.1</a>、<a href="/blog/backend/01-database/transaction-boundary/" data-link-title="1.3 Transaction 與一致性邊界" data-link-desc="交易邊界、isolation level、retry 策略、distributed transaction（2PC、Saga）與跨 region 強一致取捨">1.3</a>、<a href="/blog/backend/01-database/database-migration-playbook/" data-link-title="1.6 資料庫轉換實作：雙寫、回填、切流與回滾" data-link-desc="同 DB 內 schema 演進與資料變更的可分段驗證流程、跟 1.12 cross-DB migration 分工">1.6</a>、<a href="/blog/backend/01-database/schema-migration-rollout-evidence/" data-link-title="1.7 Schema Migration Rollout 證據（Schema Migration Rollout Evidence）實作示範" data-link-desc="以訂單付款狀態欄位演進示範 schema migration 如何產出 evidence、release gate 與 incident decision log。">1.7</a></td>
          <td>transaction 或 schema 問題</td>
      </tr>
      <tr>
          <td>02 Cache</td>
          <td><a href="/blog/backend/02-cache-redis/high-concurrency-access/" data-link-title="2.1 高併發下的 Redis 讀寫邊界" data-link-desc="說明高併發服務如何共用 Redis client、控制 pipeline 與避免 cache stampede">2.1</a>、<a href="/blog/backend/02-cache-redis/cache-aside/" data-link-title="2.2 cache aside 與失效策略" data-link-desc="整理 read-through 思路、cache miss 與 invalidation">2.2</a>、<a href="/blog/backend/02-cache-redis/cache-copy-freshness-boundary/" data-link-title="2.7 Cache Copy Boundary 與 Freshness" data-link-desc="說明快取何時只是可重建副本，何時會影響交易、權限或配額正確性。">2.7</a>、<a href="/blog/backend/02-cache-redis/cache-migration-stampede-rollback/" data-link-title="2.9 Cache Migration 與 Stampede Rollback（實作示範）" data-link-desc="以商品詳情與價格快取示範 cache migration 如何交付 evidence package、release gate 與 incident decision log。">2.9</a></td>
          <td>invalidation 或 stampede 問題</td>
      </tr>
      <tr>
          <td>03 Event</td>
          <td><a href="/blog/backend/03-message-queue/outbox-pattern/" data-link-title="3.3 outbox pattern 與發佈一致性" data-link-desc="把 transaction 與 event publish 分離">3.3</a>、<a href="/blog/backend/03-message-queue/consumer-design/" data-link-title="3.4 consumer 設計與去重" data-link-desc="整理 consumer、checkpoint 與 replay safety">3.4</a>、<a href="/blog/backend/03-message-queue/processing-recovery-semantics/" data-link-title="3.6 Processing Semantics 與 Recovery Semantics" data-link-desc="說明投遞成功、處理成功與恢復成功為何是三個不同判斷。">3.6</a>、<a href="/blog/backend/03-message-queue/event-contract-replay-boundary/" data-link-title="3.7 Event Contract 與 Replay Boundary" data-link-desc="說明 event schema、idempotency key、replay window 與補償如何先於 broker 選型。">3.7</a></td>
          <td>delivery、idempotency 或 replay 問題</td>
      </tr>
      <tr>
          <td>04 Observability</td>
          <td><a href="/blog/backend/04-observability/tracing-context/" data-link-title="4.3 tracing 與 context link" data-link-desc="整理 trace id、span 與跨服務 context propagation">4.3</a>、<a href="/blog/backend/04-observability/dashboard-alert/" data-link-title="4.4 dashboard 與 alert 設計" data-link-desc="讓 dashboard 與 alert 對應 runbook 與容量趨勢">4.4</a>、<a href="/blog/backend/04-observability/telemetry-data-quality/" data-link-title="4.17 Telemetry Data Quality" data-link-desc="把 missing signal、schema drift、sampling bias 與 timestamp skew 變成資料品質問題">4.17</a>、<a href="/blog/backend/04-observability/checkout-api-evidence-package/" data-link-title="4.22 Checkout API Evidence Package 實作示範" data-link-desc="用 checkout 路徑示範 evidence package 如何交接給 release gate 與 incident decision。">4.22</a></td>
          <td>訊號斷鏈、盲區或 evidence 問題</td>
      </tr>
      <tr>
          <td>操作閉環</td>
          <td><a href="/blog/backend/00-service-selection/operations-control-vertical-slice/" data-link-title="0.13 操作控制 vertical slice 實作入口" data-link-desc="用一個服務串起觀測證據、可靠性驗證、事故決策與回寫閉環">0.13</a></td>
          <td>從訊號進入驗證、事故與回寫流程</td>
      </tr>
  </tbody>
</table>
<h2 id="使用方式">使用方式</h2>
<p>本篇是索引型讀物。讀者第一次讀時順著四層走一遍，建立跨模組的交接心智模型。之後遇到具體問題時，用失敗訊號表定位到對應模組的章節。</p>
<p>已經有某一層經驗的讀者可以從那一層開始讀，看該層與相鄰層的交接欄位是否對齊。資料庫工程師從第一層開始看事件發布的交接；觀測工程師從第四層反推前三層需要哪些欄位。</p>
<p>本篇不處理 payment adapter、inventory lock、notification 等更複雜的分支。這些分支的模式相同 — 確認責任邊界、交接欄位與失敗判讀 — 讀者可以自行延伸。</p>
]]></content:encoded></item><item><title>0.19 雲端服務對照地圖（AWS / GCP / Azure）</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/cloud-vendor-capability-mapping/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/cloud-vendor-capability-mapping/</guid><description>&lt;p>面對「我該選 AWS 還是 GCP？」這類問題、第一步是把後端能力分類對應到三家雲廠商的具體服務名稱、技術細節放後面。本章提供這份對照地圖、同時警告一件事：AWS、GCP、Azure 在大部分能力上都有對應產品，但「對應」不等於「等價」— 同樣是 managed SQL、AWS RDS、GCP Cloud SQL、Azure SQL 在備份頻率、replica 行為、failover 時間、跨區複製成本上都有差異。對照表是入口、不是決策本身。&lt;/p>
&lt;h2 id="為什麼需要這張對照地圖">為什麼需要這張對照地圖&lt;/h2>
&lt;p>兩種使用情境會需要這張表。第一是初次選型時，讀者已經選定主要雲廠商，要對照各能力分類找出 vendor 名稱。第二是跨雲遷移評估，讀者要對照源端跟目標端的能力 gap。沒有這張表，每次都要重新查文件、容易漏掉某個能力。&lt;/p>
&lt;p>但這張表不能取代深入評估。每個 vendor 都有不在表格內的差異，例如配額、區域可用性、跨服務整合、計價模型。表格是路由起點，後續判讀要進到該 vendor 的 deep article。&lt;/p>
&lt;h2 id="能力--雲廠商對照表">能力 × 雲廠商對照表&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>能力分類&lt;/th>
 &lt;th>AWS&lt;/th>
 &lt;th>GCP&lt;/th>
 &lt;th>Azure&lt;/th>
 &lt;th>對照判讀重點&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>關聯式 DB（OLTP）&lt;/td>
 &lt;td>RDS / Aurora&lt;/td>
 &lt;td>Cloud SQL / AlloyDB&lt;/td>
 &lt;td>Azure SQL / Azure Database for Postgres&lt;/td>
 &lt;td>failover 時間、跨區 replica、IOPS 計價&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>全球分散式 DB&lt;/td>
 &lt;td>Aurora DSQL / DynamoDB Global Tables&lt;/td>
 &lt;td>Spanner&lt;/td>
 &lt;td>Cosmos DB&lt;/td>
 &lt;td>一致性模型、寫入延遲、計價單位&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>KV / Document DB&lt;/td>
 &lt;td>DynamoDB&lt;/td>
 &lt;td>Firestore / Bigtable&lt;/td>
 &lt;td>Cosmos DB&lt;/td>
 &lt;td>partition key 設計、capacity mode、跨區一致性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>快取&lt;/td>
 &lt;td>ElastiCache（Redis / Memcached）&lt;/td>
 &lt;td>Memorystore&lt;/td>
 &lt;td>Azure Cache for Redis&lt;/td>
 &lt;td>跨區複製、persistence、容量上限&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>訊息佇列&lt;/td>
 &lt;td>SQS / SNS / Kinesis&lt;/td>
 &lt;td>Pub/Sub&lt;/td>
 &lt;td>Service Bus / Event Hubs&lt;/td>
 &lt;td>delivery guarantee、ordering、retention 期&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>事件流（Kafka）&lt;/td>
 &lt;td>MSK / Kinesis&lt;/td>
 &lt;td>Pub/Sub&lt;/td>
 &lt;td>Event Hubs (Kafka compatibility)&lt;/td>
 &lt;td>Kafka 相容性、partition 數量、跨區複製&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>物件儲存&lt;/td>
 &lt;td>S3&lt;/td>
 &lt;td>Cloud Storage&lt;/td>
 &lt;td>Blob Storage&lt;/td>
 &lt;td>一致性模型、跨區複製、lifecycle policy&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>容器執行平台&lt;/td>
 &lt;td>ECS / EKS / Fargate&lt;/td>
 &lt;td>GKE / Cloud Run&lt;/td>
 &lt;td>AKS / Container Apps&lt;/td>
 &lt;td>managed 程度、cold start、計價單位&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Serverless 函式&lt;/td>
 &lt;td>Lambda&lt;/td>
 &lt;td>Cloud Functions / Cloud Run&lt;/td>
 &lt;td>Azure Functions&lt;/td>
 &lt;td>最大執行時間、cold start、整合方式&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Load Balancer&lt;/td>
 &lt;td>ELB（ALB / NLB / CLB）&lt;/td>
 &lt;td>Cloud Load Balancing&lt;/td>
 &lt;td>Azure Load Balancer / App Gateway&lt;/td>
 &lt;td>L4 vs L7、跨區 LB、TLS termination&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>API Gateway&lt;/td>
 &lt;td>API Gateway&lt;/td>
 &lt;td>API Gateway / Apigee&lt;/td>
 &lt;td>API Management&lt;/td>
 &lt;td>rate limit、auth 整合、計價&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>CDN / 邊緣&lt;/td>
 &lt;td>CloudFront&lt;/td>
 &lt;td>Cloud CDN / Media CDN&lt;/td>
 &lt;td>Azure Front Door / CDN&lt;/td>
 &lt;td>edge POP 數、purge API、cache key 彈性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>監控&lt;/td>
 &lt;td>CloudWatch&lt;/td>
 &lt;td>Cloud Monitoring&lt;/td>
 &lt;td>Azure Monitor&lt;/td>
 &lt;td>metric retention、dashboard 表達力、整合範圍&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Log 聚合&lt;/td>
 &lt;td>CloudWatch Logs&lt;/td>
 &lt;td>Cloud Logging&lt;/td>
 &lt;td>Log Analytics&lt;/td>
 &lt;td>ingestion 成本、query 語言、retention&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Tracing&lt;/td>
 &lt;td>X-Ray&lt;/td>
 &lt;td>Cloud Trace&lt;/td>
 &lt;td>Application Insights&lt;/td>
 &lt;td>sampling 策略、跨服務 trace、整合 SDK&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Secret Management&lt;/td>
 &lt;td>Secrets Manager / SSM Parameter&lt;/td>
 &lt;td>Secret Manager&lt;/td>
 &lt;td>Key Vault&lt;/td>
 &lt;td>旋轉支援、整合 IAM、稽核 log&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Identity / IAM&lt;/td>
 &lt;td>IAM&lt;/td>
 &lt;td>IAM&lt;/td>
 &lt;td>Entra ID（前 AAD） + Azure RBAC&lt;/td>
 &lt;td>跨服務 policy、token lifetime、federation&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>CI/CD&lt;/td>
 &lt;td>CodePipeline / CodeBuild&lt;/td>
 &lt;td>Cloud Build / Cloud Deploy&lt;/td>
 &lt;td>Azure Pipelines&lt;/td>
 &lt;td>整合 Git 平台、執行環境彈性、計價單位&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表以全球 hyperscaler 三巨頭為主、不是市場全貌。&lt;strong>Oracle Cloud (OCI)&lt;/strong> 在 enterprise / Java workload 跟金融受監管環境有顯著市佔；&lt;strong>Alibaba Cloud&lt;/strong> 在亞太 / 跨境電商是主流；&lt;strong>IBM Cloud&lt;/strong> 在金融 / 受監管環境仍存在；&lt;strong>Hetzner / DigitalOcean / Vultr&lt;/strong> 在 cost-leader 區段提供完全不同的計價模型；&lt;strong>Sovereign cloud&lt;/strong>（GDPR Schrems II 後在歐洲、JEDI / JWCC 在美國政府）是另一條獨立軸、跟資料主權合規綁定、比較對象不在這張表內。對照判讀邏輯（「對應 ≠ 等價」）可以同樣套用、但具體 vendor 名稱與差異維度要按目標廠商各自查證。&lt;/p></description><content:encoded><![CDATA[<p>面對「我該選 AWS 還是 GCP？」這類問題、第一步是把後端能力分類對應到三家雲廠商的具體服務名稱、技術細節放後面。本章提供這份對照地圖、同時警告一件事：AWS、GCP、Azure 在大部分能力上都有對應產品，但「對應」不等於「等價」— 同樣是 managed SQL、AWS RDS、GCP Cloud SQL、Azure SQL 在備份頻率、replica 行為、failover 時間、跨區複製成本上都有差異。對照表是入口、不是決策本身。</p>
<h2 id="為什麼需要這張對照地圖">為什麼需要這張對照地圖</h2>
<p>兩種使用情境會需要這張表。第一是初次選型時，讀者已經選定主要雲廠商，要對照各能力分類找出 vendor 名稱。第二是跨雲遷移評估，讀者要對照源端跟目標端的能力 gap。沒有這張表，每次都要重新查文件、容易漏掉某個能力。</p>
<p>但這張表不能取代深入評估。每個 vendor 都有不在表格內的差異，例如配額、區域可用性、跨服務整合、計價模型。表格是路由起點，後續判讀要進到該 vendor 的 deep article。</p>
<h2 id="能力--雲廠商對照表">能力 × 雲廠商對照表</h2>
<table>
  <thead>
      <tr>
          <th>能力分類</th>
          <th>AWS</th>
          <th>GCP</th>
          <th>Azure</th>
          <th>對照判讀重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>關聯式 DB（OLTP）</td>
          <td>RDS / Aurora</td>
          <td>Cloud SQL / AlloyDB</td>
          <td>Azure SQL / Azure Database for Postgres</td>
          <td>failover 時間、跨區 replica、IOPS 計價</td>
      </tr>
      <tr>
          <td>全球分散式 DB</td>
          <td>Aurora DSQL / DynamoDB Global Tables</td>
          <td>Spanner</td>
          <td>Cosmos DB</td>
          <td>一致性模型、寫入延遲、計價單位</td>
      </tr>
      <tr>
          <td>KV / Document DB</td>
          <td>DynamoDB</td>
          <td>Firestore / Bigtable</td>
          <td>Cosmos DB</td>
          <td>partition key 設計、capacity mode、跨區一致性</td>
      </tr>
      <tr>
          <td>快取</td>
          <td>ElastiCache（Redis / Memcached）</td>
          <td>Memorystore</td>
          <td>Azure Cache for Redis</td>
          <td>跨區複製、persistence、容量上限</td>
      </tr>
      <tr>
          <td>訊息佇列</td>
          <td>SQS / SNS / Kinesis</td>
          <td>Pub/Sub</td>
          <td>Service Bus / Event Hubs</td>
          <td>delivery guarantee、ordering、retention 期</td>
      </tr>
      <tr>
          <td>事件流（Kafka）</td>
          <td>MSK / Kinesis</td>
          <td>Pub/Sub</td>
          <td>Event Hubs (Kafka compatibility)</td>
          <td>Kafka 相容性、partition 數量、跨區複製</td>
      </tr>
      <tr>
          <td>物件儲存</td>
          <td>S3</td>
          <td>Cloud Storage</td>
          <td>Blob Storage</td>
          <td>一致性模型、跨區複製、lifecycle policy</td>
      </tr>
      <tr>
          <td>容器執行平台</td>
          <td>ECS / EKS / Fargate</td>
          <td>GKE / Cloud Run</td>
          <td>AKS / Container Apps</td>
          <td>managed 程度、cold start、計價單位</td>
      </tr>
      <tr>
          <td>Serverless 函式</td>
          <td>Lambda</td>
          <td>Cloud Functions / Cloud Run</td>
          <td>Azure Functions</td>
          <td>最大執行時間、cold start、整合方式</td>
      </tr>
      <tr>
          <td>Load Balancer</td>
          <td>ELB（ALB / NLB / CLB）</td>
          <td>Cloud Load Balancing</td>
          <td>Azure Load Balancer / App Gateway</td>
          <td>L4 vs L7、跨區 LB、TLS termination</td>
      </tr>
      <tr>
          <td>API Gateway</td>
          <td>API Gateway</td>
          <td>API Gateway / Apigee</td>
          <td>API Management</td>
          <td>rate limit、auth 整合、計價</td>
      </tr>
      <tr>
          <td>CDN / 邊緣</td>
          <td>CloudFront</td>
          <td>Cloud CDN / Media CDN</td>
          <td>Azure Front Door / CDN</td>
          <td>edge POP 數、purge API、cache key 彈性</td>
      </tr>
      <tr>
          <td>監控</td>
          <td>CloudWatch</td>
          <td>Cloud Monitoring</td>
          <td>Azure Monitor</td>
          <td>metric retention、dashboard 表達力、整合範圍</td>
      </tr>
      <tr>
          <td>Log 聚合</td>
          <td>CloudWatch Logs</td>
          <td>Cloud Logging</td>
          <td>Log Analytics</td>
          <td>ingestion 成本、query 語言、retention</td>
      </tr>
      <tr>
          <td>Tracing</td>
          <td>X-Ray</td>
          <td>Cloud Trace</td>
          <td>Application Insights</td>
          <td>sampling 策略、跨服務 trace、整合 SDK</td>
      </tr>
      <tr>
          <td>Secret Management</td>
          <td>Secrets Manager / SSM Parameter</td>
          <td>Secret Manager</td>
          <td>Key Vault</td>
          <td>旋轉支援、整合 IAM、稽核 log</td>
      </tr>
      <tr>
          <td>Identity / IAM</td>
          <td>IAM</td>
          <td>IAM</td>
          <td>Entra ID（前 AAD） + Azure RBAC</td>
          <td>跨服務 policy、token lifetime、federation</td>
      </tr>
      <tr>
          <td>CI/CD</td>
          <td>CodePipeline / CodeBuild</td>
          <td>Cloud Build / Cloud Deploy</td>
          <td>Azure Pipelines</td>
          <td>整合 Git 平台、執行環境彈性、計價單位</td>
      </tr>
  </tbody>
</table>
<p>這張表以全球 hyperscaler 三巨頭為主、不是市場全貌。<strong>Oracle Cloud (OCI)</strong> 在 enterprise / Java workload 跟金融受監管環境有顯著市佔；<strong>Alibaba Cloud</strong> 在亞太 / 跨境電商是主流；<strong>IBM Cloud</strong> 在金融 / 受監管環境仍存在；<strong>Hetzner / DigitalOcean / Vultr</strong> 在 cost-leader 區段提供完全不同的計價模型；<strong>Sovereign cloud</strong>（GDPR Schrems II 後在歐洲、JEDI / JWCC 在美國政府）是另一條獨立軸、跟資料主權合規綁定、比較對象不在這張表內。對照判讀邏輯（「對應 ≠ 等價」）可以同樣套用、但具體 vendor 名稱與差異維度要按目標廠商各自查證。</p>
<h2 id="三家雲共同缺的能力分類">三家雲共同缺的能力分類</h2>
<p>對照表覆蓋的能力都有 vendor 直接對應，但有兩類能力三家雲廠商都沒有提供等價的原生服務，要靠第三方工具補完。把這兩類獨立成段，避免在對照表中用「（無原生）」填空造成模板化。</p>
<p><strong>壓測 / 流量重放</strong>：三家雲都沒有像 RDS 對 PostgreSQL 那樣的「managed 壓測服務」。團隊要從 k6、JMeter、Gatling、Locust、Vegeta、AWS Distributed Load Testing（這是 reference architecture 而非 managed service）這類第三方工具選擇。選型考量在於：是否支援該團隊熟悉的腳本語言（k6 用 JS / Gatling 用 Scala / Locust 用 Python）、能否分散執行、能否在 CI 整合、能否重放 production traffic（GoReplay、AWS VPC Traffic Mirroring）。各工具的選型細節見 <a href="/blog/backend/09-performance-capacity/load-test-tooling/" data-link-title="9.3 壓測工具選型" data-link-desc="k6 / JMeter / Gatling / Locust / Vegeta / Production Replay 的工程選型">9.3 壓測工具選型</a>。</p>
<p><strong>事故管理 / on-call 通知</strong>：三家雲都沒有原生的 incident management 平台。CloudWatch / Cloud Monitoring / Azure Monitor 只到 alert 層、不負責 escalation、on-call rotation、incident timeline 與 retrospective。這層責任目前由 PagerDuty、Opsgenie、Splunk On-Call（前 VictorOps）、Grafana OnCall 等第三方平台承擔。三家雲提供的 alert 可以 webhook 到這些平台，但 incident workflow 本身不在 cloud vendor scope 內。事故管理流程見 <a href="/blog/backend/08-incident-response/" data-link-title="模組八：事故處理與復盤" data-link-desc="用 IR 領域詞彙建問題節點、以服務級案例庫累積事故脈絡，先建概念與案例庫再進實作交接">08 事故處理模組</a>。</p>
<p>辨識這兩類「跨雲共缺」能力的價值在於：跨雲遷移時這兩層不會增加 vendor lock-in，可以保留現有第三方工具直接接到新雲；反之，cloud-native incident management 或 cloud-native 壓測這類規劃要在採購前確認是否真實存在，避免被命名類似的工具誤導。</p>
<h2 id="對應--等價的具體差異範例">「對應 ≠ 等價」的具體差異範例</h2>
<p>對照表只給名稱對應，實際選型要看差異細節。下面四個常見的差異維度示範如何把名稱對應翻成選型判讀。</p>
<h3 id="失效切換時間差異rds-vs-cloud-sql-vs-azure-sql">失效切換時間差異（RDS vs Cloud SQL vs Azure SQL）</h3>
<p>同樣是 managed PostgreSQL，三家 vendor 文件給的 failover 時間參考值差距明顯。下列數字以各雲廠商公開文件為基準、實測長尾可能拖到更長：</p>
<ul>
<li>AWS RDS Multi-AZ：vendor 文件寫「typically 60–120 seconds」、P99 實測可達數分鐘</li>
<li>AWS Aurora：vendor 文件寫「typically less than 30 seconds」、實測 30–90 秒常見</li>
<li>GCP Cloud SQL HA：vendor 文件寫「1–2 minutes」</li>
<li>Azure SQL Business Critical：vendor 文件寫「around 30 seconds」、實測 30–60 秒</li>
</ul>
<p>選擇關鍵不是「哪個快」、而是「業務能容忍多少 downtime」。30 秒對 banking、ticketing 是不能接受的；對內部後台是無感的。失效切換時間直接影響 SLO 設定跟業務連續性 — 數字以 vendor 公開文件為參考、實際決策時要用該 vendor 自己的 SLA 條款跟 incident report 驗證。</p>
<h3 id="一致性模型差異dynamodb-vs-firestore-vs-cosmos-db">一致性模型差異（DynamoDB vs Firestore vs Cosmos DB）</h3>
<p>三家的 NoSQL 在一致性語意上分歧：</p>
<ul>
<li>DynamoDB：預設 eventual consistent read、可選 strongly consistent read（成本 2 倍）</li>
<li>Firestore：strongly consistent read 是預設、跨 region 用 multi-region 配置</li>
<li>Cosmos DB：五種一致性等級可選（strong / bounded staleness / session / consistent prefix / eventual）</li>
</ul>
<p>如果應用程式假設「寫完馬上能讀到」（read-after-write），在 DynamoDB 預設模式下會撞牆。在 Cosmos DB 選 session consistency 可以保證單一 client 內 read-after-write、跨 client 仍是 eventual。這類差異要在選型階段對齊，不是事後改 code。</p>
<h3 id="計價模型差異lambda-vs-cloud-functions-vs-azure-functions">計價模型差異（Lambda vs Cloud Functions vs Azure Functions）</h3>
<p>三家的 <a href="/blog/backend/knowledge-cards/serverless/" data-link-title="Serverless" data-link-desc="說明按請求 / 按用量計費、由平台管理執行環境與擴縮的運算交付模型、與其冷啟動與計價邊界">serverless</a> 在計價單位有差異：</p>
<ul>
<li>Lambda：請求數 + 執行時間 (GB-秒)</li>
<li>Cloud Functions：請求數 + 執行時間 + 網路流量</li>
<li>Azure Functions：執行次數 + 執行時間 + 記憶體（Consumption Plan）或固定費用（Premium / Dedicated Plan）</li>
</ul>
<p>對於低流量服務、三家差異不大；對於高頻率短時間函式、計價差異可能放大數倍（具體倍數視 memory size / 執行時間 / 流量分布、用 vendor calculator 算）。選型時要用實際 workload 估算、不能看單位價格表面數字。</p>
<h3 id="跨服務整合差異消息佇列-vs-觸發器">跨服務整合差異（消息佇列 vs 觸發器）</h3>
<p>AWS SQS + Lambda 整合非常成熟、有 native trigger；GCP Pub/Sub + Cloud Functions 同樣 native；Azure Service Bus + Functions 也有 trigger，但細節（dead-letter 處理、retry 策略、batch size）跟前兩家有差異。</p>
<p>跨服務的整合成熟度通常會在事故時放大差異。同樣的事件處理流程，在 AWS 上 90% 用 native 路徑、在另一家可能需要 30% 自己寫 glue code。</p>
<h2 id="跨雲遷移的判讀重點">跨雲遷移的判讀重點</h2>
<p>把這張對照表反過來讀，就是跨雲遷移的 gap 分析起點。但實際遷移要看四類風險：</p>
<table>
  <thead>
      <tr>
          <th>風險類型</th>
          <th>判讀重點</th>
          <th>對應緩解</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>語意差異</td>
          <td>兩家「對應」服務的一致性 / 失效 / 順序語意是否一致</td>
          <td>在抽象層（repository、queue adapter）封裝差異</td>
      </tr>
      <tr>
          <td>配額差異</td>
          <td>限制（每秒請求數、partition 上限、batch size）是否相當</td>
          <td>對照新平台配額重新設計批次大小</td>
      </tr>
      <tr>
          <td>計價差異</td>
          <td>計價單位不同，舊有 cost model 在新平台失準</td>
          <td>用新平台計價重做 cost engineering</td>
      </tr>
      <tr>
          <td>生態差異</td>
          <td>周邊工具（監控、log、IAM）整合不對等</td>
          <td>預估遷移成本要含「重建 observability / IAM」</td>
      </tr>
      <tr>
          <td>Data gravity / egress lock-in</td>
          <td>PB 級資料的 egress fee 跟一致性轉移時程</td>
          <td>決定資料「同步轉移 / 漸進複製 / 保留在原雲、運算跨雲」</td>
      </tr>
  </tbody>
</table>
<p>第五類風險常被低估：以 AWS S3 為例、egress 約 $0.09/GB、PB 級資料即 $90k 帶寬費；GCP / Azure 同等級。跨雲遷移最大單筆成本經常是 data gravity、需要先決策資料拓樸再算其他三類風險。</p>
<p>跨雲遷移不是把服務名稱換掉就完成。每一個對應都要做 deep audit，這是 <a href="/blog/backend/01-database/large-scale-db-migration/" data-link-title="1.12 大規模 DB 遷移實戰" data-link-desc="跨 DB 遷移的 dual-write、[shadow read](/backend/knowledge-cards/shadow-read/)、cutover、rollback 流程 — 從實戰案例提煉的工程做法">01 大規模 DB 遷移實戰</a> 等模組的責任。</p>
<h2 id="混合雲與多雲的情境">混合雲與多雲的情境</h2>
<p>常見的混合或多雲組合：</p>
<ul>
<li><strong>資料留 AWS、ML 跑 GCP</strong>：因為 BigQuery、Vertex AI 在資料分析優勢</li>
<li><strong>主要 Azure、ML 跑 AWS</strong>：因為 SageMaker 跟 Bedrock 提供的選項</li>
<li><strong>DR 在另一家雲</strong>：主要在 AWS、DR 站在 Azure 避免單一雲廠商故障</li>
</ul>
<p>混合 / 多雲要解的核心問題是跨雲流量成本（egress）跟身分聯邦（cross-cloud IAM）。這兩個成本通常被低估，要在規劃階段就做進 cost model。</p>
<h2 id="對照表使用的判讀順序">對照表使用的判讀順序</h2>
<p>讀這張表時，避免以下兩種誤用：</p>
<p>第一是「看完表格就決定 vendor」。表格只給名稱對應，沒給選型理由。先確認自己的能力需求（容量、一致性、failover 時間、計價型態），再用表格找候選 vendor，再進該 vendor 的 deep article 驗證細節。</p>
<p>第二是「把『對應』當作可互換」。已經提到的失效時間、一致性語意、計價模型差異會直接影響業務。在做技術選型時不能假設「換家雲就行」，要驗證每一條差異。</p>
<p>正確的使用順序：能力需求 → 對照表找候選 → vendor deep article 驗證 → cost / failure / consistency 驗算 → 決策。</p>
<h2 id="判讀訊號">判讀訊號</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>判讀重點</th>
          <th>對應動作</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>同樣 workload 在新雲上 cost 翻倍</td>
          <td>計價模型差異未被估到</td>
          <td>重做 cost engineering、用實際 traffic 估算</td>
      </tr>
      <tr>
          <td>遷移後 latency 升高</td>
          <td>區域、跨服務整合或一致性模式不同</td>
          <td>確認 region 選擇、跨服務整合方式</td>
      </tr>
      <tr>
          <td>跨雲 egress 成本失控</td>
          <td>流量設計沒考慮 inter-cloud transfer</td>
          <td>重新設計流量拓樸、考慮 cache 或聚合</td>
      </tr>
      <tr>
          <td>跨雲 IAM 設定爆炸</td>
          <td>身分聯邦設計不足、每個服務各管各的</td>
          <td>引入統一身分平台或 federation</td>
      </tr>
      <tr>
          <td>新雲服務功能對應不上</td>
          <td>「對應 ≠ 等價」的 gap 出現</td>
          <td>抽象層封裝差異、或評估是否值得換</td>
      </tr>
  </tbody>
</table>
<h2 id="常見誤區">常見誤區</h2>
<p>把 vendor 對照表當「採購清單」，看完直接照表選。選型必須回到需求，不是看哪家有對應名稱就選。</p>
<p>把雲廠商當「commodity 商品」，假設換家就好。三家的整合生態、配額限制、計價單位都有差異、遷移成本經常被嚴重低估（特別是 data gravity / IAM / 監控重建這三類隱性成本）。</p>
<p>把單一雲廠商當「永遠不會變」。雲廠商會調整定價、棄用服務、改 API。設計時要有抽象邊界，避免直接綁定 vendor SDK 到業務邏輯，方便未來換家或多雲。</p>
<h2 id="定位邊界">定位邊界</h2>
<p>本章預設「自建於雲端基礎設施」已成立；讀者若在對照表看到 Firestore 而想問「乾脆整個用 Firebase？」、那是 BaaS / 託管平台層的交付形態判斷、見 <a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型</a>。</p>
<p>本章專注「能力分類到 vendor 名稱的翻譯與對應差異」。當問題進入具體 vendor 配置（例如 RDS 怎麼設 backup）、跨 vendor 遷移流程（例如從 MySQL 遷到 Aurora），分別交給各模組的 <code>vendors/</code> 目錄跟 migration playbook。當問題進入需求分類（這個業務需要強一致還是最終一致？）回到 <a href="/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0 後端需求分類地圖</a>。</p>
<h2 id="案例回寫">案例回寫</h2>
<p>雲端服務選型可用以下案例回寫：</p>
<ul>
<li><a href="/blog/backend/00-service-selection/enterprise-selection-case-atlas/" data-link-title="0.14 企業選型案例圖譜" data-link-desc="蒐集不同類型與不同規模企業的技術選型案例，作為後端選型判讀的跨情境補充。">0.14 企業選型案例圖譜</a> — 0.14 收錄不同產業、不同規模階段企業的雲端選型決策；對照本章「跨雲遷移的判讀重點」段：合規、計價、IAM 整合是三家雲決策的主要分歧軸。</li>
<li><a href="/blog/backend/09-performance-capacity/cases/zomato-tidb-to-dynamodb-migration/" data-link-title="9.C20 Zomato：從 TiDB 遷移到 DynamoDB、吞吐 4 倍、延遲降 90%、成本減 50%" data-link-desc="Zomato 帳單系統從 TiDB 遷移到 DynamoDB、吞吐 2K→8K RPM、延遲降 90%、成本減 50%">9.C20 Zomato：TiDB 遷到 DynamoDB</a> — Zomato 把 SQL 介面（TiDB）換成 KV 介面（DynamoDB）、用一致性語意差異換取 4 倍吞吐 + 50% 成本；對照本章「對應 ≠ 等價」段中的一致性模型差異子段。</li>
<li><a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix：Aurora consolidation</a> — 案例是 AWS 內 DB 種類整併（多 RDB → Aurora），可對照本章「對應 ≠ 等價」段中的計價模型與整合成熟度差異。雖然不涉及跨雲，但在同一家雲廠商內整併服務、跟跨雲整併共用同一條決策邏輯：權衡 vendor lock-in 代價 vs 運維碎片化代價。</li>
<li><a href="/blog/backend/05-deployment-platform/cases/tradeshift-self-managed-k8s-to-eks/" data-link-title="5.C1 Tradeshift：self-managed Kubernetes 遷移到 EKS" data-link-desc="零停機平台遷移的分段策略案例。">5.C1 Tradeshift：self-managed K8s → EKS</a> — Tradeshift 從自管 K8s control plane 遷到 EKS managed control plane、運維責任邊界從「整套 cluster」收斂到「workload + worker node」。對照本章「容器執行平台」對照行：managed 程度是同一能力分類下的主要分歧軸。</li>
</ul>
<p>這些案例回答的是不同問題、不是同一個問題的不同切面。對照表本身只回答「叫什麼名字」；Zomato / Tradeshift 補「換掉名字後實際差多少」（介面 / 計價 / 一致性差異）；Netflix Aurora 補「同一雲內怎麼收斂」；0.14 補「真實企業在什麼壓力下選什麼」。讀者按手邊的問題進入對應案例、不需要也不適合串成同一條 narrative。</p>
<h2 id="跨模組路由">跨模組路由</h2>
<ol>
<li>與 <a href="/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1 後端服務能力地圖</a> 的交接：先確認能力分類，再用本章找 vendor 對應。</li>
<li>與 <a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6 成本、風險與選型取捨</a> 的交接：cost model 是 vendor 選型的關鍵維度。</li>
<li>與各模組的 <code>vendors/</code> 目錄的交接：對照表只給名稱、deep article 給配置與運維。</li>
<li>與 <a href="/blog/backend/01-database/large-scale-db-migration/" data-link-title="1.12 大規模 DB 遷移實戰" data-link-desc="跨 DB 遷移的 dual-write、[shadow read](/backend/knowledge-cards/shadow-read/)、cutover、rollback 流程 — 從實戰案例提煉的工程做法">01 大規模 DB 遷移實戰</a> 的交接：跨 vendor 遷移的具體流程。</li>
</ol>
<h2 id="下一步路由">下一步路由</h2>
<p>對照表是查 vendor 名稱的第一層、進入細節要走 deep article：</p>
<ul>
<li>實際企業選型案例 → <a href="/blog/backend/00-service-selection/enterprise-selection-case-atlas/" data-link-title="0.14 企業選型案例圖譜" data-link-desc="蒐集不同類型與不同規模企業的技術選型案例，作為後端選型判讀的跨情境補充。">0.14 企業選型案例圖譜</a></li>
<li>資料庫 vendor 細節對比 → <a href="/blog/backend/01-database/vendors/" data-link-title="資料庫 Vendor 清單" data-link-desc="規劃 SQL、managed SQL、document、KV 與 distributed SQL 的服務頁撰寫順序與教學大綱">01 模組 vendors/</a></li>
<li>部署平台 vendor 細節對比 → <a href="/blog/backend/05-deployment-platform/vendors/" data-link-title="部署平台 Vendor 清單" data-link-desc="規劃 workload runtime、orchestration、traffic、IaC 與 discovery 的服務頁撰寫順序與判準">05 模組 vendors/</a></li>
</ul>
<p>本章不在規模成長路線上、是 sibling 工具型入口。要進規模成長路線、從 <a href="/blog/backend/10-system-evolution/service-decomposition-boundaries/" data-link-title="10.1 服務拆分與邊界判讀" data-link-desc="整理 monolith vs microservice 取捨、服務邊界判讀訊號、拆分時機與回退路徑">10.1 服務拆分</a> 或 <a href="/blog/backend/09-performance-capacity/scaling-axes/" data-link-title="9.13 擴展軸與 Stateless 前提" data-link-desc="整理垂直 / 水平擴展取捨、stateless vs stateful 前提、auto scaling 操作模型與兩種擴展的 hidden cost">9.13 擴展軸</a> 開始。</p>
]]></content:encoded></item><item><title>0.21 交付形態選型：從全託管到自建的光譜與邊界</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/delivery-mode-selection/</link><pubDate>Thu, 11 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/delivery-mode-selection/</guid><description>&lt;p>交付形態選型的核心原則是先判斷「這個服務值得自建嗎」、再進入自建世界的服務選型。提供線上服務的途徑是一個光譜：全託管平台（Wix、Shopify、Google Sites）、辦公生態自動化（Google Apps Script）、BaaS（Firebase、Supabase）、半託管 CMS（WordPress）、到自建程式 — 本模組其餘章節討論的資料庫、快取、queue、部署選型、全部屬於光譜最右端的自建世界。落在光譜其他位置的服務、那些章節的問題暫時與它無關；判斷自己落在哪、以及什麼訊號出現時該往右移、是比「選哪個資料庫」更早的決策。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、讀者能夠：&lt;/p>
&lt;ol>
&lt;li>用差異化位置與業務量判斷服務該落在交付形態光譜的哪一段&lt;/li>
&lt;li>看懂全託管平台、辦公生態自動化、BaaS、半託管 CMS 與自建各自的能力邊界與遷出代價&lt;/li>
&lt;li>在選擇託管形態的同時、保留日後遷往自建的可遷出路徑&lt;/li>
&lt;li>把「該升級自建了」的判斷從感覺轉成可觀察的 tripwire&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="觀察自建的合理性來自差異化位置">【觀察】自建的合理性來自差異化位置&lt;/h2>
&lt;p>自建的合理性來自一個前提：&lt;strong>這個產品的差異化在軟體本身&lt;/strong>。差異化在商品、內容、社群或服務品質的生意、軟體只是通路 — 通路用現成的、把工程資源留給差異化所在的位置、是成本上更誠實的選擇。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>可觀察訊號&lt;/th>
 &lt;th>指向&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>需求能用「型錄 + 結帳」「表單 + 通知」「文章 + 頁面」描述完&lt;/td>
 &lt;td>託管平台的標準域、先不自建&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>流程是把幾個現成服務串起來（表單進試算表、定時寄報表）&lt;/td>
 &lt;td>辦公生態自動化（Apps Script 類）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>產品是行動 app 或 SPA、後端需求是認證 + 資料同步 + 推播&lt;/td>
 &lt;td>BaaS（Firebase 類）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>內容為主、但要客製版型、SEO、外掛功能&lt;/td>
 &lt;td>半託管 CMS（WordPress 類）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>業務流程落在某個垂直行業 SaaS 的標準域（預約、課表、POS、訂位）&lt;/td>
 &lt;td>垂直 SaaS — 行業專用的託管形態、先進候選&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>產品本身就是軟體（SaaS 工具、API 服務、平台）&lt;/td>
 &lt;td>自建 — 本模組其餘章節的世界&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>核心流程在任何現成平台都要大量 workaround 才能表達&lt;/td>
 &lt;td>自建、或重新檢視流程是否過度客製&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>服務只有自己 / 家人用、跑在自有主機或私有網路、無對外使用者&lt;/td>
 &lt;td>個人自架工具 — 自建但走極縮減流程&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>第一列的判讀方式值得展開：把產品的核心流程用一句話描述、再問「這句話是不是某個託管平台的官方首頁文案」。「賣手作飾品、信用卡結帳、出貨通知」就是 Shopify 的首頁；「活動報名、自動寄確認信、報名滿額關閉」就是表單工具加自動化的範圍。描述不出落在任何平台標準域的流程 — 例如「客戶上傳檔案後跑客製演算法、依結果動態計價」— 才是自建訊號。&lt;/p>
&lt;p>「產品本身就是軟體」這一列要先過一個澄清：&lt;strong>這個軟體是要賣的產品、還是經營業務的工具&lt;/strong>。「給健身教練用的課表系統」有兩種身分 — 開發者要賣給眾多教練的產品（市場上的垂直 SaaS 是競爭對手、交付形態走自建）、或教練管理自己學員的工具（同一批垂直 SaaS — 課表、預約、POS — 正是該優先評估的託管形態）。同一句需求描述、兩種身分的結論相反、先拆身分再進訊號表。&lt;/p>
&lt;h2 id="判讀交付形態光譜">【判讀】交付形態光譜&lt;/h2>
&lt;p>光譜從左到右、控制力遞增、維運責任同步遞增。每一段先看它解什麼、再看邊界訊號與遷出代價。&lt;/p>
&lt;h3 id="全託管平台wixshopifysquarespacegoogle-sites">全託管平台：Wix、Shopify、Squarespace、Google Sites&lt;/h3>
&lt;p>平台承擔整條技術棧：主機、憑證、防護、金流、版面。使用者操作的對象是「網站內容」、不是「程式碼」。電商走 Shopify、形象站與簡介站走 Wix / Google Sites、訂閱內容走 Substack 類 — 各平台的標準域內、上線時間以天計、且本系列 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8 資安與資料保護需求&lt;/a> 裡多數伺服器側的功課由平台承擔。&lt;/p>
&lt;p>邊界訊號：客製需求開始對抗平台 — 結帳流程要插入平台不支援的步驟、資料要跟外部系統雙向同步、頁面效能撞到平台的模板天花板。在平台內 workaround 的程式碼（Shopify 的 liquid hack、Wix 的 Velo 腳本）累積越多、等於在用最差的開發環境自建。&lt;/p>
&lt;p>遷出代價：資料匯出通常有官方管道（商品、訂單 CSV）、但 URL 結構、SEO 累積、會員密碼（雜湊不可攜、遷移等於全體重設密碼）、訂閱金流的扣款授權（綁在平台的金流帳戶上）都要重建。&lt;/p>
&lt;h3 id="辦公生態自動化google-apps-script--sites--forms--sheets">辦公生態自動化：Google Apps Script + Sites / Forms / Sheets&lt;/h3>
&lt;p>這一段解的是「流程自動化」、不是「產品」。表單收件進試算表、定時整理寄報表、收到 email 觸發動作 — Apps Script 把 Google Workspace 的元件串成工作流、零主機、零部署、權限直接掛在 Google 帳號上。同段位的還有 no-code 資料庫工具（Airtable、Notion 當輕後台）— 串現成元件、零部署的角色相同。內部工具與小規模對外流程（報名、登記、排班）在這一段的成本接近零。&lt;/p>
&lt;p>邊界訊號：第一個出現的通常是配額牆 — 某天報名表單停止收件、log 裡躺著超額錯誤、而且已經靜默丟了一個下午的提交。再來是併發：兩個人同時送出、Sheets 用最後寫入蓋掉前一筆。最後是工程紀律的渴望、腳本長到想要版本控制與測試時、它已經是一個沒有工程基礎設施的程式專案。&lt;/p>
&lt;p>遷出代價：低 — 資料在 Sheets / Drive 裡天然可匯出、流程邏輯通常短到可以重寫。這一段的風險是「忘記遷」、不是「遷不動」：業務量上來後配額錯誤靜默發生、報名表單少收一批人才發現。&lt;/p>
&lt;h3 id="baasfirebasesupabase">BaaS：Firebase、Supabase&lt;/h3>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/baas/" data-link-title="BaaS（Backend as a Service）" data-link-desc="說明把認證、資料庫、檔案儲存、推播打包成現成模組、由前端 SDK 直連的後端交付形態">BaaS&lt;/a> 把後端拆成現成模組：認證、資料庫、檔案儲存、推播、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/serverless/" data-link-title="Serverless" data-link-desc="說明按請求 / 按用量計費、由平台管理執行環境與擴縮的運算交付模型、與其冷啟動與計價邊界">serverless&lt;/a> function。前端（app / SPA）自己寫、後端用平台的 SDK 直連 — 本系列 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2 狀態與資料儲存選型&lt;/a> 討論的多數問題、在這一段被平台的預設答案取代。行動 app MVP 與快速驗證期的產品、BaaS 把「後端工程師」這個角色延後了。&lt;/p>
&lt;p>BaaS 的邊界牆通常分三面依序出現。第一面是報表 — 老闆要一張跨集合的月報、Firestore 查不出來、工程師開始把資料複製第二份、複製管線本身變成要維護的系統。第二面是帳單：讀寫計費隨流量線性成長、某個月的發票讓人重新打開計算機比對自建。第三面最安靜：client 直連資料庫的模型把授權邏輯全部塞進 security rules、規則檔長到沒人敢改時、&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8&lt;/a> 的整個控制面已經壓在一個難以測試的規則語言（DSL）裡。&lt;/p></description><content:encoded><![CDATA[<p>交付形態選型的核心原則是先判斷「這個服務值得自建嗎」、再進入自建世界的服務選型。提供線上服務的途徑是一個光譜：全託管平台（Wix、Shopify、Google Sites）、辦公生態自動化（Google Apps Script）、BaaS（Firebase、Supabase）、半託管 CMS（WordPress）、到自建程式 — 本模組其餘章節討論的資料庫、快取、queue、部署選型、全部屬於光譜最右端的自建世界。落在光譜其他位置的服務、那些章節的問題暫時與它無關；判斷自己落在哪、以及什麼訊號出現時該往右移、是比「選哪個資料庫」更早的決策。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、讀者能夠：</p>
<ol>
<li>用差異化位置與業務量判斷服務該落在交付形態光譜的哪一段</li>
<li>看懂全託管平台、辦公生態自動化、BaaS、半託管 CMS 與自建各自的能力邊界與遷出代價</li>
<li>在選擇託管形態的同時、保留日後遷往自建的可遷出路徑</li>
<li>把「該升級自建了」的判斷從感覺轉成可觀察的 tripwire</li>
</ol>
<hr>
<h2 id="觀察自建的合理性來自差異化位置">【觀察】自建的合理性來自差異化位置</h2>
<p>自建的合理性來自一個前提：<strong>這個產品的差異化在軟體本身</strong>。差異化在商品、內容、社群或服務品質的生意、軟體只是通路 — 通路用現成的、把工程資源留給差異化所在的位置、是成本上更誠實的選擇。</p>
<table>
  <thead>
      <tr>
          <th>可觀察訊號</th>
          <th>指向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>需求能用「型錄 + 結帳」「表單 + 通知」「文章 + 頁面」描述完</td>
          <td>託管平台的標準域、先不自建</td>
      </tr>
      <tr>
          <td>流程是把幾個現成服務串起來（表單進試算表、定時寄報表）</td>
          <td>辦公生態自動化（Apps Script 類）</td>
      </tr>
      <tr>
          <td>產品是行動 app 或 SPA、後端需求是認證 + 資料同步 + 推播</td>
          <td>BaaS（Firebase 類）</td>
      </tr>
      <tr>
          <td>內容為主、但要客製版型、SEO、外掛功能</td>
          <td>半託管 CMS（WordPress 類）</td>
      </tr>
      <tr>
          <td>業務流程落在某個垂直行業 SaaS 的標準域（預約、課表、POS、訂位）</td>
          <td>垂直 SaaS — 行業專用的託管形態、先進候選</td>
      </tr>
      <tr>
          <td>產品本身就是軟體（SaaS 工具、API 服務、平台）</td>
          <td>自建 — 本模組其餘章節的世界</td>
      </tr>
      <tr>
          <td>核心流程在任何現成平台都要大量 workaround 才能表達</td>
          <td>自建、或重新檢視流程是否過度客製</td>
      </tr>
      <tr>
          <td>服務只有自己 / 家人用、跑在自有主機或私有網路、無對外使用者</td>
          <td>個人自架工具 — 自建但走極縮減流程</td>
      </tr>
  </tbody>
</table>
<p>第一列的判讀方式值得展開：把產品的核心流程用一句話描述、再問「這句話是不是某個託管平台的官方首頁文案」。「賣手作飾品、信用卡結帳、出貨通知」就是 Shopify 的首頁；「活動報名、自動寄確認信、報名滿額關閉」就是表單工具加自動化的範圍。描述不出落在任何平台標準域的流程 — 例如「客戶上傳檔案後跑客製演算法、依結果動態計價」— 才是自建訊號。</p>
<p>「產品本身就是軟體」這一列要先過一個澄清：<strong>這個軟體是要賣的產品、還是經營業務的工具</strong>。「給健身教練用的課表系統」有兩種身分 — 開發者要賣給眾多教練的產品（市場上的垂直 SaaS 是競爭對手、交付形態走自建）、或教練管理自己學員的工具（同一批垂直 SaaS — 課表、預約、POS — 正是該優先評估的託管形態）。同一句需求描述、兩種身分的結論相反、先拆身分再進訊號表。</p>
<h2 id="判讀交付形態光譜">【判讀】交付形態光譜</h2>
<p>光譜從左到右、控制力遞增、維運責任同步遞增。每一段先看它解什麼、再看邊界訊號與遷出代價。</p>
<h3 id="全託管平台wixshopifysquarespacegoogle-sites">全託管平台：Wix、Shopify、Squarespace、Google Sites</h3>
<p>平台承擔整條技術棧：主機、憑證、防護、金流、版面。使用者操作的對象是「網站內容」、不是「程式碼」。電商走 Shopify、形象站與簡介站走 Wix / Google Sites、訂閱內容走 Substack 類 — 各平台的標準域內、上線時間以天計、且本系列 <a href="/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8 資安與資料保護需求</a> 裡多數伺服器側的功課由平台承擔。</p>
<p>邊界訊號：客製需求開始對抗平台 — 結帳流程要插入平台不支援的步驟、資料要跟外部系統雙向同步、頁面效能撞到平台的模板天花板。在平台內 workaround 的程式碼（Shopify 的 liquid hack、Wix 的 Velo 腳本）累積越多、等於在用最差的開發環境自建。</p>
<p>遷出代價：資料匯出通常有官方管道（商品、訂單 CSV）、但 URL 結構、SEO 累積、會員密碼（雜湊不可攜、遷移等於全體重設密碼）、訂閱金流的扣款授權（綁在平台的金流帳戶上）都要重建。</p>
<h3 id="辦公生態自動化google-apps-script--sites--forms--sheets">辦公生態自動化：Google Apps Script + Sites / Forms / Sheets</h3>
<p>這一段解的是「流程自動化」、不是「產品」。表單收件進試算表、定時整理寄報表、收到 email 觸發動作 — Apps Script 把 Google Workspace 的元件串成工作流、零主機、零部署、權限直接掛在 Google 帳號上。同段位的還有 no-code 資料庫工具（Airtable、Notion 當輕後台）— 串現成元件、零部署的角色相同。內部工具與小規模對外流程（報名、登記、排班）在這一段的成本接近零。</p>
<p>邊界訊號：第一個出現的通常是配額牆 — 某天報名表單停止收件、log 裡躺著超額錯誤、而且已經靜默丟了一個下午的提交。再來是併發：兩個人同時送出、Sheets 用最後寫入蓋掉前一筆。最後是工程紀律的渴望、腳本長到想要版本控制與測試時、它已經是一個沒有工程基礎設施的程式專案。</p>
<p>遷出代價：低 — 資料在 Sheets / Drive 裡天然可匯出、流程邏輯通常短到可以重寫。這一段的風險是「忘記遷」、不是「遷不動」：業務量上來後配額錯誤靜默發生、報名表單少收一批人才發現。</p>
<h3 id="baasfirebasesupabase">BaaS：Firebase、Supabase</h3>
<p><a href="/blog/backend/knowledge-cards/baas/" data-link-title="BaaS（Backend as a Service）" data-link-desc="說明把認證、資料庫、檔案儲存、推播打包成現成模組、由前端 SDK 直連的後端交付形態">BaaS</a> 把後端拆成現成模組：認證、資料庫、檔案儲存、推播、<a href="/blog/backend/knowledge-cards/serverless/" data-link-title="Serverless" data-link-desc="說明按請求 / 按用量計費、由平台管理執行環境與擴縮的運算交付模型、與其冷啟動與計價邊界">serverless</a> function。前端（app / SPA）自己寫、後端用平台的 SDK 直連 — 本系列 <a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2 狀態與資料儲存選型</a> 討論的多數問題、在這一段被平台的預設答案取代。行動 app MVP 與快速驗證期的產品、BaaS 把「後端工程師」這個角色延後了。</p>
<p>BaaS 的邊界牆通常分三面依序出現。第一面是報表 — 老闆要一張跨集合的月報、Firestore 查不出來、工程師開始把資料複製第二份、複製管線本身變成要維護的系統。第二面是帳單：讀寫計費隨流量線性成長、某個月的發票讓人重新打開計算機比對自建。第三面最安靜：client 直連資料庫的模型把授權邏輯全部塞進 security rules、規則檔長到沒人敢改時、<a href="/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8</a> 的整個控制面已經壓在一個難以測試的規則語言（DSL）裡。</p>
<p>遷出的代價集中在資料層：資料本身可匯出、但資料模型沿平台特性設計（為遷就查詢限制、同一份資料複製存放多處的反正規化結構、加上平台專屬的即時同步語意）、遷到關聯式資料庫等於重做資料層。認證體系可攜性視平台而定（Firebase Auth 可匯出密碼雜湊、是少數友善案例）。</p>
<h3 id="半託管-cmswordpress-與同類">半託管 CMS：WordPress 與同類</h3>
<p>WordPress 代表「半手動自定義」這一段：核心由開源專案提供、功能靠外掛拼裝、版型可以改到面目全非、主機可以託管也可以自架。內容為主、客製需求中等的站（媒體、部落格、預約、小型電商加 WooCommerce）長期住在這一段。控制力比全託管平台高一級：資料庫是自己的 MySQL、檔案是自己的目錄、想改什麼理論上都改得動。</p>
<p>邊界訊號：每次外掛更新前先全站備份、更新完手動點一輪主要頁面 — 這個儀式固定下來時、外掛堆疊已經超出任何人的全盤理解。效能問題跟著來：頁面變慢、但慢在哪一層查詢沒人說得清。資安面則是時間問題：WordPress 外掛漏洞是攻擊者的固定狩獵場、patch 責任在自己身上、沒人 patch 的站是 <a href="/blog/backend/00-service-selection/red-team-cross-service-weaknesses/" data-link-title="0.11 攻擊者視角（紅隊）：跨服務弱點判讀總表" data-link-desc="用攻擊面、可觀察訊號與失敗代價，建立 backend 選型前的弱點盤點框架">0.11 攻擊者視角</a> 裡最便宜的目標。</p>
<p>遷出代價：真正遷不動的是外掛私有表裡的業務邏輯 — 會員等級、預約規則、客製欄位散在各外掛自己的資料表、遷移時要逐個考古；內容本身（文章、媒體）反而是最成熟的匯出路徑。</p>
<h3 id="垂直-saas行業專用的託管形態">垂直 SaaS：行業專用的託管形態</h3>
<p>垂直 SaaS（預約系統、課表排班、POS、訂位平台）是全託管平台的行業特化分支。平台已經把該行業的標準流程做成產品、使用者設定開通而非寫程式碼。業務流程落在平台標準域內時、效率跟全託管平台相同；差異在於當需求偏離行業標準域（例如預約系統要加客製的動態定價邏輯）、平台的 API 與 webhook 是延伸天花板 — 超出就是自建訊號。遷出代價集中在客戶資料與業務規則的可攜性：客戶名單、歷史交易紀錄的匯出格式、以及在平台 UI 裡長出來的行業特定規則（排班邏輯、會員等級、優惠券組合）能否帶走。</p>
<h3 id="個人自架工具常駐本機無對外服務">個人自架工具：常駐本機、無對外服務</h3>
<p>這一段跟前面所有形態的本質差異在於：沒有對外使用者。遠端操控自己的主機、家庭自動化、個人備份同步這類工具、使用者就是所有者（單人或家人）。它在光譜上是自建的一個特例 — 自建成立、但本模組其餘章節的多數問題（租戶、使用者資料庫、對外服務）不適用。常駐在自有主機（launchd / systemd）或私有網路上、本模組裡真正展開的只剩三條：入口怎麼安全進來（部署平台）、誰能存取（資安）、密鑰怎麼保管（secret）;資料庫、快取、queue、多租戶隔離多半 N/A。</p>
<p>認證也離開 web-auth 光譜。沒有帳號系統、沒有 SSO、主體就是持有裝置的所有者：一層裝置原生生物辨識（Face ID / 指紋）認「人」、一層 app 與主機共享的密鑰認「連線」。入口形態常是 outbound tunnel（cloudflared / Tailscale）而非公網 IP — 本機主動外連、路由器零開 port。詳見 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 身分與授權邊界</a> 的單人裝置認證段與 <a href="/blog/backend/05-deployment-platform/outbound-tunnel-entry/" data-link-title="5.10 Outbound Tunnel 入口與生命週期" data-link-desc="整理 cloudflared / Tailscale 等反向隧道的入口形態、生命週期合約與故障模式">5.10 Outbound Tunnel 入口</a>。</p>
<p>這個模型的邊界在使用者數。使用者從「自己」變成「自己 + 幾個朋友」時、第一個多出來的使用者就打破整個模型 — 共享密鑰無法分辨是誰、生物辨識綁在單一裝置、沒有帳號就無法個別撤銷。這時回到完整自建訪談、把認證升級成帳號系統。</p>
<p>遷出方向也跟其他形態相反 — 方向是「長成服務」、離開平台只是副產物。工具沒有累積對外使用者資料、遷移成本低;真正要重做的是認證與授權層（從單人共享密鑰換成多使用者帳號系統）、以及入口（從個人 tunnel 換成能承載多人的公開入口）。</p>
<h3 id="自建本模組其餘章節的世界">自建：本模組其餘章節的世界</h3>
<p>差異化在軟體本身、或所有託管形態的邊界都已撞到、就進入自建。自建的真正成本由本模組其餘章節展開：<a href="/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0 需求分類</a> 開始、<a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6 成本、風險與選型取捨</a> 把人力與維運成本攤開。自建換到的是：資料模型自己定、流程任意客製、成本曲線在規模化後由自己控制、以及所有控制面（資安、觀測、備援）可以做到合規要求的深度。</p>
<h2 id="判讀混合形態是常態不是過渡期的妥協">【判讀】混合形態是常態、不是過渡期的妥協</h2>
<p>光譜上的位置不必全站一致。常見的健康組合：行銷頁與內容放託管平台（Wix / WordPress）、核心產品自建、兩者用子網域分流；電商主站走 Shopify、客製的批發報價系統自建接 Shopify API；內部流程跑 Apps Script、對外產品自建。判讀單位是「每條業務流程」、不是「整間公司」— 把不是差異化的流程硬塞進自建 codebase、跟把差異化流程硬塞進託管平台、是同一個錯誤的兩個方向。拆分軸除了逐流程、還有逐層：headless 形態（託管平台當後端引擎、自建前端體驗層）是同一條流程內的層級混合、判讀方式相同 — 每一層各自問「差異化在這層嗎」。</p>
<p>光譜上還有兩個停靠點值得知道：靜態網站生成器（Hugo / Next.js export）搭配 hosting（Netlify / Vercel）介於全託管與半託管之間，適合文件站與行銷頁；Edge Functions（Cloudflare Workers / Vercel Edge）介於 BaaS 與自建之間，寫程式但不管基礎設施，適合輕量 API 與邊緣邏輯。兩者的邊界訊號與遷出代價跟相鄰形態類似，需求超出時回到各自相鄰段落的判讀。</p>
<h2 id="權衡託管形態的成本與資安帳">【權衡】託管形態的成本與資安帳</h2>
<p>託管形態把伺服器帳單換成平台帳單、把維運人力換成平台依賴。權衡時五個方向都要看：</p>
<ol>
<li><strong>資安限制</strong>：平台扛掉 patch、憑證、DDoS 防護 — 這對沒有資安人力的團隊是淨收益。代價是資料主權與稽核深度受限：資料落在平台的儲存裡、<a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a> 細度由平台決定、有資料落地或合規要求（金融、醫療、政府標案）的業務、託管形態可能直接出局。</li>
<li><strong>流量與穩定性</strong>：平台的彈性通常優於小團隊自建（Shopify 扛 Black Friday 是它的本業）、但天花板不可協商 — API rate limit、配額、模板效能、撞到就是撞到。</li>
<li><strong>平台費用</strong>：月費 + 抽成（電商平台的交易抽成在量大後是實質稅率）。自建與託管的成本曲線會交叉、交叉點要算：平台月費 + 抽成 vs 自建的工程薪資 + 雲端帳單、在目前與三倍業務量下各是多少。</li>
<li><strong>人力與操作</strong>：託管形態讓非工程角色能直接維護（改文案、上商品、調流程）、這個能力在小團隊值很多錢；自建後每個改動都過工程隊列。</li>
<li><strong>機會成本</strong>：選託管、省下的工程時間投到差異化；選自建、買到的控制力要有明確用途。「以後可能要客製」是最常見的偽自建理由 — 客製需求出現時再遷、總成本通常低於提前自建養一套用不滿的基礎設施。</li>
</ol>
<h2 id="檢查可遷出保險選託管的同時保留往右走的路">【檢查】可遷出保險：選託管的同時保留往右走的路</h2>
<p>託管形態的真正風險是 <a href="/blog/backend/knowledge-cards/vendor-lock-in/" data-link-title="Vendor Lock-In" data-link-desc="說明採用供應商產品後，其 API 與格式滲入程式碼造成的退出成本">vendor lock-in</a> 的具體形：遷不出去。保險在進場時最便宜。選擇任何託管形態的同時、確認下列事項：</p>
<table>
  <thead>
      <tr>
          <th>保險項</th>
          <th>做法</th>
          <th>缺了會發生什麼</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>自有網域</td>
          <td>網域註冊在自己名下、DNS 自己控制、不用平台贈送的子網域</td>
          <td>遷移等於換址、SEO 與既有連結歸零</td>
      </tr>
      <tr>
          <td>資料定期匯出</td>
          <td>排程匯出商品 / 訂單 / 會員資料、確認格式可被重新匯入</td>
          <td>遷移當天才發現匯出殘缺、或平台限制匯出頻率</td>
      </tr>
      <tr>
          <td>客戶聯絡管道自有</td>
          <td>email 名單同步到自有系統、不只活在平台的行銷模組裡</td>
          <td>客戶關係綁死在平台、遷移等於重新獲客</td>
      </tr>
      <tr>
          <td>金流可攜性</td>
          <td>評估金流商是否平台綁定；訂閱制確認扣款授權能否轉移</td>
          <td>訂閱客戶遷移時全體重新授權、流失率直接體現在營收</td>
      </tr>
      <tr>
          <td>密碼不可攜的預案</td>
          <td>接受會員密碼雜湊多半遷不走、預先設計重設密碼的遷移體驗</td>
          <td>遷移日全體會員被迫重設、無預案時體驗等於資安事故</td>
      </tr>
      <tr>
          <td>業務邏輯文件化</td>
          <td>在平台設定裡長出來的規則（折扣邏輯、會員等級）寫成文件</td>
          <td>規則只存在平台 UI 裡、遷移時靠回憶重建</td>
      </tr>
  </tbody>
</table>
<p>每項保險在遷出日如何兌現 — 保險與理賠流程的對應 — 見 <a href="/blog/backend/10-system-evolution/managed-platform-exit/" data-link-title="10.3 託管形態遷出：資產線盤點與並行期執行" data-link-desc="0.21 升級自建 tripwire 觸發後的執行劇本 — 把遷出拆成資料、身分、流量、整合各自的可攜性與斷點、設計舊平台與新系統的並行期與回切窗口、用部分遷出作為中繼形態">10.3 託管形態遷出</a> 的資產線盤點。</p>
<h2 id="檢查升級自建的-tripwire">【檢查】升級自建的 tripwire</h2>
<p>「日後可能需要自建」要轉成可觀察訊號、寫進選型記錄、而不是留在感覺裡：</p>
<table>
  <thead>
      <tr>
          <th>Tripwire 訊號</th>
          <th>判讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>平台內 workaround 程式碼持續成長（liquid hack、Velo、外掛魔改）</td>
          <td>已經在用最差的環境自建、把工程投入轉到正式自建更划算</td>
      </tr>
      <tr>
          <td>平台年費用超過半個工程師全載年薪（含招聘與管理成本）</td>
          <td>成本曲線交叉、用自己團隊的數字錨定後重算自建總帳；三倍業務量下再算一次</td>
      </tr>
      <tr>
          <td>核心流程的客製需求連續被平台能力擋下</td>
          <td>差異化開始長在軟體上、自建的前提成立了</td>
      </tr>
      <tr>
          <td>API rate limit / 配額錯誤開始影響業務</td>
          <td>天花板撞到、額度調整權在平台手上</td>
      </tr>
      <tr>
          <td>合規或客戶要求資料落地、稽核細度、滲透測試</td>
          <td>控制面深度超出託管形態能給的範圍</td>
      </tr>
      <tr>
          <td>平台政策變更（費率、功能下架）直接衝擊營收</td>
          <td>平台風險具體化、依賴單一平台的代價浮現</td>
      </tr>
      <tr>
          <td>平台被收購、停止維護或公告 EOL</td>
          <td>帶死線的續存風險 — 問題從「該不該遷」變成「遷移窗口多長」、立即啟動評估</td>
      </tr>
  </tbody>
</table>
<p>tripwire 是重評承諾、不是遷移保證 — 觸發後每拖一季、資料量與整合深度都在墊高遷移成本。任一 tripwire 觸發時、回到本模組從 <a href="/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0 需求分類</a> 走完整的自建選型；評估成立後的執行劇本 — 資產線盤點、並行期、回切窗口 — 見 <a href="/blog/backend/10-system-evolution/managed-platform-exit/" data-link-title="10.3 託管形態遷出：資產線盤點與並行期執行" data-link-desc="0.21 升級自建 tripwire 觸發後的執行劇本 — 把遷出拆成資料、身分、流量、整合各自的可攜性與斷點、設計舊平台與新系統的並行期與回切窗口、用部分遷出作為中繼形態">10.3 託管形態遷出</a>。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>判斷落在自建：從 <a href="/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0 後端需求分類地圖</a> 開始走本模組的選型順序。</li>
<li>判斷落在自建、但周邊能力仍想逐塊外包（認證、搜尋、金流、表單、後台）：見 <a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22 能力級買 vs 建</a>。</li>
<li>判斷落在個人自架工具（單人自用、無對外服務）：跳過資料庫 / 快取 / queue 章節、只看 <a href="/blog/backend/07-security-data-protection/identity-access-boundary/" data-link-title="7.2 身分與授權邊界" data-link-desc="以問題驅動方式整理身分、授權、會話與供應商身分鏈">7.2 單人裝置認證</a> 與 <a href="/blog/backend/05-deployment-platform/outbound-tunnel-entry/" data-link-title="5.10 Outbound Tunnel 入口與生命週期" data-link-desc="整理 cloudflared / Tailscale 等反向隧道的入口形態、生命週期合約與故障模式">5.10 Outbound Tunnel 入口</a>;多人化時再回完整自建選型。</li>
<li>判斷落在託管形態：完成上方可遷出保險清單、把 tripwire 寫進選型記錄、定期回看。</li>
<li>成本曲線的算法：見 <a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6 成本、風險與選型取捨</a>。</li>
<li>託管形態下仍需要的資安底線（帳號安全、權限、資料匯出管控）：見 <a href="/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8 資安與資料保護需求</a>。</li>
<li>從託管遷往自建的執行劇本：見 <a href="/blog/backend/10-system-evolution/managed-platform-exit/" data-link-title="10.3 託管形態遷出：資產線盤點與並行期執行" data-link-desc="0.21 升級自建 tripwire 觸發後的執行劇本 — 把遷出拆成資料、身分、流量、整合各自的可攜性與斷點、設計舊平台與新系統的並行期與回切窗口、用部分遷出作為中繼形態">10.3 託管形態遷出</a>；模組總覽見 <a href="/blog/backend/10-system-evolution/" data-link-title="模組十：系統演進與遷移" data-link-desc="處理服務拆分、跨服務重構、大型遷移與雲端切換的執行紀律 — 設計階段的選型判斷見模組零、執行階段的高風險變更收斂在本模組">模組十：系統演進與遷移</a>。</li>
</ul>
]]></content:encoded></item><item><title>0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/</link><pubDate>Sun, 14 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/</guid><description>&lt;p>能力級買 vs 建的核心原則是：交付形態 gate 決定整個系統要不要自建之後、每一塊非核心能力仍各自是一次獨立的買 vs 建決策。&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型&lt;/a> 把「整包該不該自建」篩過一輪、留下決定自建核心的團隊；但自建核心不等於每塊能力都要自己寫 — 認證、搜尋、金流、Email、表單蒐集、檔案儲存、後台操作介面這些非差異化能力、預設先問「能不能買現成的」。決策單位是能力、不是系統；真實系統是逐能力混搭、核心自建、周邊外包。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>讀完本章後、讀者能夠：&lt;/p>
&lt;ol>
&lt;li>把「買 vs 建」的判斷單位從整個系統下降到單一能力&lt;/li>
&lt;li>辨識三種外包深度（managed 基礎設施、feature SaaS、BaaS bundle）與 no-code 到 dev-tool 的服務光譜&lt;/li>
&lt;li>用 commodity、合規、長尾成本與團隊規模判斷一塊能力該買還是該建&lt;/li>
&lt;li>算清外包的隱性帳：整合接縫、鎖定、遷出代價、以及權重如何隨情境浮動&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="判讀先確認該不該讀這章">【判讀】先確認該不該讀這章&lt;/h2>
&lt;p>本章預設讀者已經過了 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21&lt;/a> 的 whole-system gate、決定自建核心。在那之前有一種讀者該先被擋下來：&lt;strong>非工程師、目的是解自己的生活痛點或做第一個 MVP 的人&lt;/strong>。對這種讀者、0.21 已經把答案給完了 — 用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/baas/" data-link-title="BaaS（Backend as a Service）" data-link-desc="說明把認證、資料庫、檔案儲存、推播打包成現成模組、由前端 SDK 直連的後端交付形態">BaaS&lt;/a>（Supabase、Firebase）就是對的起點、本章的逐能力拆解反而是過度工程。免費額度對個人專案通常夠用、BaaS 連後端與資料庫的串接、效能調教、資源調配一起省掉、把這些當成「之後真的撞牆再說」的問題、是這個尺度最誠實的選擇。&lt;/p>
&lt;p>常見的誤判是把選型問題問錯層。「我該選什麼資料庫」這個提問、對非工程師多半真正的答案在 0.21（這個尺度根本不必自己管資料庫）、不在本章。下表把提問者的身分對應到該回的章節：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>提問者情境&lt;/th>
 &lt;th>真正該回的章節&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>非工程師、解個人痛點、第一個 MVP&lt;/td>
 &lt;td>0.21 — 用 BaaS、本章不必細讀&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>已決定自建核心、要逐塊判斷哪些能力外包&lt;/td>
 &lt;td>本章&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>已長期自建、某塊外包能力撐不住要搬回自建&lt;/td>
 &lt;td>本章 §「什麼訊號指向『自建或搬離』」+ &lt;a href="https://tarrragon.github.io/blog/backend/10-system-evolution/managed-platform-exit/" data-link-title="10.3 託管形態遷出：資產線盤點與並行期執行" data-link-desc="0.21 升級自建 tripwire 觸發後的執行劇本 — 把遷出拆成資料、身分、流量、整合各自的可攜性與斷點、設計舊平台與新系統的並行期與回切窗口、用部分遷出作為中繼形態">10.3 託管遷出&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>第一列展開說明：判斷自己是不是這種讀者、看「撞牆之後誰來修」。個人專案撞到 Supabase 免費額度上限時、升級付費方案或匯出資料換平台都是幾小時的事、不需要先把架構拆乾淨。把工程資源花在「現在還沒發生的擴展問題」上、是把 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6 成本、風險與選型取捨&lt;/a> 講的機會成本花在錯的地方。確定自己是要自建核心、且周邊有多塊能力要逐一決定買或建、再往下讀。&lt;/p>
&lt;h2 id="判讀三種外包深度與-no-code-到-dev-tool-光譜">【判讀】三種外包深度與 no-code 到 dev-tool 光譜&lt;/h2>
&lt;p>外包一塊能力有深度之分、不是非黑即白的二元動作（見 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/capability-outsourcing-depth/" data-link-title="Capability Outsourcing Depth（外包深度）" data-link-desc="說明外包一塊後端能力有三種深度（managed 基礎設施、feature SaaS、BaaS bundle）、深度決定保留多少控制權與遷出代價">Capability Outsourcing Depth&lt;/a> 卡片）。同樣是「不自己寫」、把維運交出去跟把整塊能力連業務邏輯一起交出去、控制權與遷出代價差一個量級。下面這三層講的是把能力交給雲端託管側時、交出多少 — 自架 OSS 或買 on-prem 授權、只租控制平面的自管形態是另一條平行軸（鎖定點在運維 know-how 與授權、不在 vendor API）、不收在這三層裡。下表把三種深度分開、每種附代表服務與遷出代價：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>外包深度&lt;/th>
 &lt;th>你外包什麼、還擁有什麼&lt;/th>
 &lt;th>dev-tool 代表&lt;/th>
 &lt;th>no-code / low-code 代表&lt;/th>
 &lt;th>遷出代價&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>managed 基礎設施&lt;/td>
 &lt;td>外包維運、仍擁有 schema、query 與架構&lt;/td>
 &lt;td>Aurora、ElastiCache、Neon&lt;/td>
 &lt;td>—&lt;/td>
 &lt;td>低–中&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>feature SaaS（能力即服務）&lt;/td>
 &lt;td>外包整塊能力與內部業務邏輯、只消費 API&lt;/td>
 &lt;td>Auth0、Algolia、Stripe、SendGrid&lt;/td>
 &lt;td>Ragic、SurveyCake、Airtable、Typeform&lt;/td>
 &lt;td>中–高&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>跨能力 BaaS bundle&lt;/td>
 &lt;td>一個 vendor 一次給多塊能力&lt;/td>
 &lt;td>—&lt;/td>
 &lt;td>Supabase、Firebase、Amplify&lt;/td>
 &lt;td>高&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>managed 基礎設施是最淺的外包：vendor 接手備份、修補、failover、擴容、跨區複製、但 schema、query、index、資料模型還是你的。遷出時資料是標準格式、架構是自己畫的、換一家 managed PostgreSQL 主要是搬資料與改連線字串。撞牆時你改得動的邊界很寬 — 慢查詢自己優化、index 自己加、只有底層硬體與維運動作在 vendor 手上。不過「邊界很寬」有前提：受限的 serverless 或內嵌型 managed（沒給 superuser、裝不了 extension 的那種）邊界其實更窄、選之前要確認需要的控制權它給不給。&lt;/p>
&lt;p>feature SaaS 把整塊能力連同它的內部業務邏輯一起交出去、你消費的是一組 API 而不是一台機器。買 Auth0 不只是省下跑一台認證伺服器、是把「密碼雜湊策略、MFA、SSO、social login、session 管理」整套交給 vendor、你只接它的 SDK。代價是你改得動的邊界縮到 vendor 開放的擴展點為止 — 它沒給的客製、你做不到、繞過去就是在 vendor 之外再搭一層。遷出代價中到高、因為資料模型與業務規則都沿 vendor 的特性長出來。&lt;/p>
&lt;p>選 feature SaaS 真正在賭的、是它的擴展點夠不夠你長出差異化。commodity 能力的多數需求跟同業一樣、買現成就解決；會區分產品的是少數、而那少數得疊在 vendor 之上自己長 — 但要先確認那塊差異化存不存在：有些 commodity（收個款、寄封信）差異化趨近零、整塊就是純買、這條擴展點判準根本不啟動。判準只在「確實有一塊差異化要疊上去」時才是選型核心。能不能疊、看 vendor 把控制權開到哪 — 開 API 讓你改它的排序、規則、把自己的資料接進它的邏輯、差異化長得出來；只開一面設定面板、核心邏輯動不了、一撞到差異化需求就得繞到 vendor 外另建一塊補。所以選的時候除了問「它做不做這塊能力」、更關鍵的是「它讓不讓我在上面長出獨有的那部分」 — 這一題決定它能陪產品走多遠。&lt;/p></description><content:encoded><![CDATA[<p>能力級買 vs 建的核心原則是：交付形態 gate 決定整個系統要不要自建之後、每一塊非核心能力仍各自是一次獨立的買 vs 建決策。<a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型</a> 把「整包該不該自建」篩過一輪、留下決定自建核心的團隊；但自建核心不等於每塊能力都要自己寫 — 認證、搜尋、金流、Email、表單蒐集、檔案儲存、後台操作介面這些非差異化能力、預設先問「能不能買現成的」。決策單位是能力、不是系統；真實系統是逐能力混搭、核心自建、周邊外包。</p>
<h2 id="本章目標">本章目標</h2>
<p>讀完本章後、讀者能夠：</p>
<ol>
<li>把「買 vs 建」的判斷單位從整個系統下降到單一能力</li>
<li>辨識三種外包深度（managed 基礎設施、feature SaaS、BaaS bundle）與 no-code 到 dev-tool 的服務光譜</li>
<li>用 commodity、合規、長尾成本與團隊規模判斷一塊能力該買還是該建</li>
<li>算清外包的隱性帳：整合接縫、鎖定、遷出代價、以及權重如何隨情境浮動</li>
</ol>
<hr>
<h2 id="判讀先確認該不該讀這章">【判讀】先確認該不該讀這章</h2>
<p>本章預設讀者已經過了 <a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21</a> 的 whole-system gate、決定自建核心。在那之前有一種讀者該先被擋下來：<strong>非工程師、目的是解自己的生活痛點或做第一個 MVP 的人</strong>。對這種讀者、0.21 已經把答案給完了 — 用 <a href="/blog/backend/knowledge-cards/baas/" data-link-title="BaaS（Backend as a Service）" data-link-desc="說明把認證、資料庫、檔案儲存、推播打包成現成模組、由前端 SDK 直連的後端交付形態">BaaS</a>（Supabase、Firebase）就是對的起點、本章的逐能力拆解反而是過度工程。免費額度對個人專案通常夠用、BaaS 連後端與資料庫的串接、效能調教、資源調配一起省掉、把這些當成「之後真的撞牆再說」的問題、是這個尺度最誠實的選擇。</p>
<p>常見的誤判是把選型問題問錯層。「我該選什麼資料庫」這個提問、對非工程師多半真正的答案在 0.21（這個尺度根本不必自己管資料庫）、不在本章。下表把提問者的身分對應到該回的章節：</p>
<table>
  <thead>
      <tr>
          <th>提問者情境</th>
          <th>真正該回的章節</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>非工程師、解個人痛點、第一個 MVP</td>
          <td>0.21 — 用 BaaS、本章不必細讀</td>
      </tr>
      <tr>
          <td>已決定自建核心、要逐塊判斷哪些能力外包</td>
          <td>本章</td>
      </tr>
      <tr>
          <td>已長期自建、某塊外包能力撐不住要搬回自建</td>
          <td>本章 §「什麼訊號指向『自建或搬離』」+ <a href="/blog/backend/10-system-evolution/managed-platform-exit/" data-link-title="10.3 託管形態遷出：資產線盤點與並行期執行" data-link-desc="0.21 升級自建 tripwire 觸發後的執行劇本 — 把遷出拆成資料、身分、流量、整合各自的可攜性與斷點、設計舊平台與新系統的並行期與回切窗口、用部分遷出作為中繼形態">10.3 託管遷出</a></td>
      </tr>
  </tbody>
</table>
<p>第一列展開說明：判斷自己是不是這種讀者、看「撞牆之後誰來修」。個人專案撞到 Supabase 免費額度上限時、升級付費方案或匯出資料換平台都是幾小時的事、不需要先把架構拆乾淨。把工程資源花在「現在還沒發生的擴展問題」上、是把 <a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6 成本、風險與選型取捨</a> 講的機會成本花在錯的地方。確定自己是要自建核心、且周邊有多塊能力要逐一決定買或建、再往下讀。</p>
<h2 id="判讀三種外包深度與-no-code-到-dev-tool-光譜">【判讀】三種外包深度與 no-code 到 dev-tool 光譜</h2>
<p>外包一塊能力有深度之分、不是非黑即白的二元動作（見 <a href="/blog/backend/knowledge-cards/capability-outsourcing-depth/" data-link-title="Capability Outsourcing Depth（外包深度）" data-link-desc="說明外包一塊後端能力有三種深度（managed 基礎設施、feature SaaS、BaaS bundle）、深度決定保留多少控制權與遷出代價">Capability Outsourcing Depth</a> 卡片）。同樣是「不自己寫」、把維運交出去跟把整塊能力連業務邏輯一起交出去、控制權與遷出代價差一個量級。下面這三層講的是把能力交給雲端託管側時、交出多少 — 自架 OSS 或買 on-prem 授權、只租控制平面的自管形態是另一條平行軸（鎖定點在運維 know-how 與授權、不在 vendor API）、不收在這三層裡。下表把三種深度分開、每種附代表服務與遷出代價：</p>
<table>
  <thead>
      <tr>
          <th>外包深度</th>
          <th>你外包什麼、還擁有什麼</th>
          <th>dev-tool 代表</th>
          <th>no-code / low-code 代表</th>
          <th>遷出代價</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>managed 基礎設施</td>
          <td>外包維運、仍擁有 schema、query 與架構</td>
          <td>Aurora、ElastiCache、Neon</td>
          <td>—</td>
          <td>低–中</td>
      </tr>
      <tr>
          <td>feature SaaS（能力即服務）</td>
          <td>外包整塊能力與內部業務邏輯、只消費 API</td>
          <td>Auth0、Algolia、Stripe、SendGrid</td>
          <td>Ragic、SurveyCake、Airtable、Typeform</td>
          <td>中–高</td>
      </tr>
      <tr>
          <td>跨能力 BaaS bundle</td>
          <td>一個 vendor 一次給多塊能力</td>
          <td>—</td>
          <td>Supabase、Firebase、Amplify</td>
          <td>高</td>
      </tr>
  </tbody>
</table>
<p>managed 基礎設施是最淺的外包：vendor 接手備份、修補、failover、擴容、跨區複製、但 schema、query、index、資料模型還是你的。遷出時資料是標準格式、架構是自己畫的、換一家 managed PostgreSQL 主要是搬資料與改連線字串。撞牆時你改得動的邊界很寬 — 慢查詢自己優化、index 自己加、只有底層硬體與維運動作在 vendor 手上。不過「邊界很寬」有前提：受限的 serverless 或內嵌型 managed（沒給 superuser、裝不了 extension 的那種）邊界其實更窄、選之前要確認需要的控制權它給不給。</p>
<p>feature SaaS 把整塊能力連同它的內部業務邏輯一起交出去、你消費的是一組 API 而不是一台機器。買 Auth0 不只是省下跑一台認證伺服器、是把「密碼雜湊策略、MFA、SSO、social login、session 管理」整套交給 vendor、你只接它的 SDK。代價是你改得動的邊界縮到 vendor 開放的擴展點為止 — 它沒給的客製、你做不到、繞過去就是在 vendor 之外再搭一層。遷出代價中到高、因為資料模型與業務規則都沿 vendor 的特性長出來。</p>
<p>選 feature SaaS 真正在賭的、是它的擴展點夠不夠你長出差異化。commodity 能力的多數需求跟同業一樣、買現成就解決；會區分產品的是少數、而那少數得疊在 vendor 之上自己長 — 但要先確認那塊差異化存不存在：有些 commodity（收個款、寄封信）差異化趨近零、整塊就是純買、這條擴展點判準根本不啟動。判準只在「確實有一塊差異化要疊上去」時才是選型核心。能不能疊、看 vendor 把控制權開到哪 — 開 API 讓你改它的排序、規則、把自己的資料接進它的邏輯、差異化長得出來；只開一面設定面板、核心邏輯動不了、一撞到差異化需求就得繞到 vendor 外另建一塊補。所以選的時候除了問「它做不做這塊能力」、更關鍵的是「它讓不讓我在上面長出獨有的那部分」 — 這一題決定它能陪產品走多遠。</p>
<p>跨能力 BaaS bundle 是一個 vendor 同時提供多塊能力、用整合當賣點。它的遷出代價最高、來自多塊能力被同一套整合綁在一起、不在任何單一能力 —— 例如同一組登入身分同時管資料庫、檔案與即時訂閱的權限、搬走其中一塊就要拆開這層共用整合（見下方 bundle 專段）。</p>
<p>這三種深度橫切一條 no-code 到 dev-tool 的光譜、而光譜的兩端服務不同的人。feature SaaS 這一層特別明顯：Auth0、Algolia 是 dev-tool、要寫 code 接 API、客製空間大、但需要工程整合能力；Ragic、SurveyCake、Airtable、Typeform 是 no-code、連 schema 都不必碰、填表就能用、客製天花板通常較低、但起步門檻也低到非工程師能獨立操作。選哪一端不只看「需要哪塊能力」、更看「誰來維護它」。一個沒有工程隊的小團隊、把會員資料放 Ragic、滿意度調查放 SurveyCake、是把維護權留在能自己改的人手上；同樣的能力換成 Auth0 + 自建問卷服務、每次調整都回到工程隊列、對這種團隊反而更貴。</p>
<h2 id="觀察什麼訊號指向買這塊能力">【觀察】什麼訊號指向「買這塊能力」</h2>
<p>一塊能力該優先評估外包、訊號集中在「自建不產生競爭優勢、卻要承擔沒有上限的長尾成本」。下表列可觀察訊號與它指向的判斷：</p>
<table>
  <thead>
      <tr>
          <th>可觀察訊號</th>
          <th>指向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>這塊能力同業要的都一樣、做得再好也不構成差異化</td>
          <td>commodity 能力、預設先買</td>
      </tr>
      <tr>
          <td>合規負擔重且標準化（金流的 PCI、認證的 SSO / SOC2）</td>
          <td>把合規面交給專做這件事的 vendor</td>
      </tr>
      <tr>
          <td>自建後維護成本沒有上限（投遞率、反詐欺、登入方式矩陣）</td>
          <td>長尾成本型能力、買掉長尾</td>
      </tr>
      <tr>
          <td>團隊缺這個領域的專才、或時間壓力不允許自建</td>
          <td>用 SaaS 換時間、把人力留給核心</td>
      </tr>
  </tbody>
</table>
<p>commodity 這一列是最常見的買訊號。認證、Email 投遞、金流處理、問卷蒐集、物件儲存 / 檔案 / CDN、後台操作介面（internal tooling）都落在這裡 — 每個產品要的功能幾乎一樣、自己寫一套不會讓產品更有競爭力。後台介面值得特別點出：很多團隊把「完整後台可操作」當成自建理由、但 admin panel 本身是 commodity、Supabase Studio、Retool、Appsmith 這類工具讓你連著資料庫就生出可操作的後台、把工程時間留給真正客製的業務流程。</p>
<p>自己架一台 SMTP 寄 email 看起來簡單、真正的成本藏在 deliverability — SPF、DKIM、DMARC、IP 信譽、退信處理、進垃圾桶的排查、是一條沒有終點的維護線、而 SendGrid 這類服務把這條線變成它的本業。這就是長尾成本最容易被低估的地方：金流的反詐欺、認證的 MFA 與 social login 矩陣同理 — 第一版很快、長期維護吃掉的人力沒有上限。</p>
<h2 id="觀察什麼訊號指向自建或搬離">【觀察】什麼訊號指向「自建或搬離」</h2>
<p>外包不是預設終點、有四種訊號會把一塊能力從「買」翻回「建」。這一段是對照、判斷時跟上一段的買訊號一起看、不是讓否定句主導決策：</p>
<table>
  <thead>
      <tr>
          <th>可觀察訊號</th>
          <th>指向</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>這塊能力正是產品的差異化核心</td>
          <td>自建、控制權要握在自己手上</td>
      </tr>
      <tr>
          <td>客製需求持續撞到 SaaS 的擴展點上限</td>
          <td>外包換來的天花板開始擋路、評估自建</td>
      </tr>
      <tr>
          <td>計費隨規模線性成長、自建的 TCO 出現交叉點</td>
          <td>成本曲線翻轉、重算自建總帳</td>
      </tr>
      <tr>
          <td>資料主權或合規要求 SaaS 無法滿足</td>
          <td>控制面深度超出外包能給的範圍</td>
      </tr>
  </tbody>
</table>
<p>會把一塊能力翻回自建的訊號裡、差異化核心是最硬的一條。一塊能力如果就是產品賣點 — 推薦引擎之於內容平台、媒合演算法之於媒合服務 — 把它外包等於把競爭力外包、再貴也該自建。但「差異化核心」是最容易拿來自我說服的標籤 — 下手自建前先用買訊號表的 commodity 判準反向驗一次：同業是不是也都這樣做、做得再好客戶會不會無感？會、它其實是偽核心、「再貴也建」不適用。其餘三列是「原本買得對、條件變了該重評」：客製撞牆、成本交叉、合規不滿足、都是把選型結論拿出來重算的 tripwire、而不是一次定生死。觸發後的搬離執行 — 並行期、回切窗口、資產盤點 — 見 <a href="/blog/backend/10-system-evolution/managed-platform-exit/" data-link-title="10.3 託管形態遷出：資產線盤點與並行期執行" data-link-desc="0.21 升級自建 tripwire 觸發後的執行劇本 — 把遷出拆成資料、身分、流量、整合各自的可攜性與斷點、設計舊平台與新系統的並行期與回切窗口、用部分遷出作為中繼形態">10.3 託管形態遷出</a>。</p>
<h2 id="判讀四個真實例子">【判讀】四個真實例子</h2>
<p>例子的責任是建判斷錨點。下面四個刻意走四種不同方向 — 黏合型、買到部分搬離、永遠買、建到改買 — 避免把「逐能力外包」講成單向的故事。</p>
<p>一個親子活動 app 的形狀最能展示「決策單位是能力」。需求包含親子活動預約、室內空間遊玩預約、親職文章分享、會員資料、滿意度調查、線上諮詢。拆開來看：會員資料與空間預約接 Ragic、滿意度調查接 SurveyCake、文章只是連結跳轉、真正需要自建的差異化只有「線上諮詢內容匯整成固定格式檔」這一塊。這個 app 的本質是整合層 — 把幾個 no-code SaaS 黏起來、自己寫的部分極小。資料庫選 Supabase 還是 Neon 在這裡幾乎是次要問題、真正的工程量在「會員資料同時存在 Ragic 跟 app、要不要同步、諮詢內容怎麼流到固定格式檔」這些接縫上。逐能力看、它的決策是「五塊買、一塊建」、不是「選一個資料庫」。</p>
<p>一個成長期的 SaaS 走的是相反路徑的前半段。它早期用 Supabase 全包上線 — Postgres、Auth、Storage、Realtime 一次到位、團隊不必碰後端。業務量上來後、資料層的 query 複雜度與成本超過 Supabase 託管 Postgres 的舒適區、團隊把資料層搬到自管 PostgreSQL、但認證留在 Supabase Auth。這是逐能力遷出的典型 — 只把撞牆的那一塊（資料層）搬走、沒撞牆的（認證）留在原地、整包搬離反而是錯誤思路。</p>
<p>一個自建電商展示「永遠買」的判斷。核心交易流程、商品、訂單、庫存全部自建、因為那是差異化所在。金流則永遠接 Stripe — PCI 合規、反詐欺、各國支付方式是 Stripe 的本業、自建金流要承擔的合規與長尾成本沒有任何回報、因為「能收錢」不構成競爭優勢。這個「永遠買」是對絕大多數團隊的預設、不是無條件鐵律 — 例外要先攔在前面：做受監管清算、金融牌照或資金存管業務的團隊、接 vendor 不會把這些合規責任接走、得回到自己業態的前提判斷、別照抄「金流永遠買」。要分清這裡「買」涵蓋的是哪一層：收單（把一筆卡片交易實際跑完、完成扣款）、卡片資料、PCI 合規、各國支付方式這層、對絕大多數團隊從第一天到規模化都是買、收單就是終點。會翻回自建的是更上層的支付編排（orchestration）。當一家公司同時接多個 PSP（payment service provider，實際完成扣款的金流商、如 Stripe、Adyen）、就需要一層編排決定每筆交易走哪家、哪家失敗換哪家重試、月底跟各家對帳。這層協調的複雜度跨多業務線後超過任何單一 vendor 能給、超大規模下才會把它拿回自己手上；但拿回的是收單之上的協調邏輯、底層的 PCI 與卡片處理仍然外包。對本章設定的讀者、金流買到收單這層就是答案、編排層的自建是規模到了才會出現的 tripwire —— 而多數產品永遠到不了那個規模、orchestration 對它們是不會觸發的分支、不是必經路徑；少數例外是高度監管或特殊清算需求的團隊、小規模就可能直接 direct acquiring（跳過 PSP 直接對接收單行）。</p>
<p>站內搜尋走的是反方向 —— 建到改買。一個內容站初期用自建 Elasticsearch、隨內容成長、維運這套搜尋（叢集調校、相關性排序、同義詞、中文斷詞）吃掉的人力越來越多、而搜尋品質始終追不上專做這件事的服務。團隊把搜尋換成 Algolia — 一塊原本自建的能力、因為長尾運維成本翻轉、改成外包。方向跟前三個都不同、但判準一致：這塊能力的維護成本有沒有回報。</p>
<h2 id="判讀跨能力-bundle-的特殊判讀">【判讀】跨能力 bundle 的特殊判讀</h2>
<p>跨能力 BaaS bundle 難放進以能力分章的結構、因為它一次交付多塊能力。Supabase 同時是 Postgres、Auth、Storage、Realtime 與 Edge Functions、橫跨本系列的 <a href="/blog/backend/01-database/" data-link-title="模組一：資料庫與持久化" data-link-desc="整理 SQL、transaction、migration 與 repository adapter 的後端實務">01 資料庫</a>、<a href="/blog/backend/02-cache-redis/" data-link-title="模組二：快取與 Redis" data-link-desc="整理快取策略、Redis 資料型別與分散式狀態輔助能力">02 快取</a>、<a href="/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">03 訊息佇列</a>、<a href="/blog/backend/05-deployment-platform/" data-link-title="模組五：部署平台與網路入口" data-link-desc="整理 Kubernetes、systemd、load balancer、container 與服務生命週期合約">05 部署</a> 與 <a href="/blog/backend/07-security-data-protection/" data-link-title="模組七：資安與資料保護" data-link-desc="以問題驅動方式擴充資安知識網：先定義服務環節問題，再以案例作為觸發式參考">07 資安</a>。以能力分章的教材、放不下「一個 vendor 給五塊能力」這種形狀、所以 Supabase 在資料庫章節只能當 managed PostgreSQL 比較表裡的一行 — 本章是它在選型層的上層錨點。</p>
<p>bundle 的價值與鎖定同源、都來自整合。同一套認證身分貫穿資料庫的 row-level security、Storage 的存取控制與 Realtime 的訂閱權限、是 bundle 最大的賣點 — 一次設定、多塊能力一致生效、省掉自己接縫的工作。但這份整合反過來就是遷出阻力：搬走任何一塊、都要把它跟其他幾塊的整合關係拆開重接。bundle 的高遷出代價不在資料量、在這些被同一套整合綁住的能力之間。</p>
<p>判讀 bundle 的單位仍然是逐能力。Supabase 不是一個必須整包接受或整包拒絕的決定 — 你可以只用它的 Postgres 當 managed 基礎設施、認證自建或接 Auth0；也可以反過來、資料庫自管、只用 Supabase Auth。問「我需要哪幾塊」「這幾塊的整合值不值得換取遷出代價」、比問「要不要用 Supabase」更準。</p>
<p>這也澄清一個常被混為一談的並列：Supabase 跟 Neon 不在同一個外包深度。Neon 是 managed 基礎設施、純 serverless PostgreSQL、給你一個會自動擴縮的資料庫、其餘能力自理；Supabase 是 BaaS bundle、資料庫只是它的一塊。只需要一個資料庫、兩者都行、Neon 更輕、遷出代價更低；需要認證、儲存、即時同步一起到位、才是 Supabase 的賣點。把它們當同級選項比較、會錯估各自真正交付的範圍。</p>
<h2 id="權衡六方向成本與權重隨情境浮動">【權衡】六方向成本與權重隨情境浮動</h2>
<p>外包一塊能力的成本帳有六個方向、但這六個方向不是等權的 — 權重隨讀者與規模浮動、用同一張等權表套所有情境會把真正主導的軸攤平。先定權重、再看方向。</p>
<p>MVP 與個人專案主導的是三個方向：免費額度天花板、整合接縫工作量、長大後的鎖定。金流 / PCI 合規與流量穩定性對一個親子活動預約 MVP 近乎無關 — 沒有信用卡資料、沒有尖峰流量 — 但「合規」不能整類劃掉：這個 app 蒐集兒少個資、在多數司法管轄區（COPPA、GDPR-K、台灣個資法）反而是高敏感類別、同意機制與資料存放地點要照規矩走。把金流合規與流量這兩個方向跟其他四個並重討論、只會稀釋真正要看的「免費額度夠不夠、SaaS 黏起來累不累、以後搬不搬得動」。企業與規模化則相反、主導的是合規、流量穩定與計費的線性成長、免費額度天花板根本不在視野裡。</p>
<p>六個方向：</p>
<ol>
<li><strong>資安與合規</strong>：外包認證把身分攻擊面交給 vendor、對沒有資安人力的團隊是淨收益；代價是 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a> 細度、資料存放地點（落在哪個國家 / 區域）與稽核深度受 vendor 限制、有合規要求的業務可能直接出局。</li>
<li><strong>流量與穩定性</strong>：SaaS 的 rate limit 與 SLA 變成你的天花板、不可協商；vendor 故障時你跟著故障 — 買一塊能力等於接受一個外部單點依賴。這個依賴的極端是 vendor 自己 sunset、倒閉或被併後關停 — 跟「你想走的鎖定」相反、是 vendor 先走、後果不可逆、選有長期生存力的 vendor 是這條的隱性成本。</li>
<li><strong>伺服器與雲端成本</strong>：計費形狀（per-MAU、per-request、per-seat、免費額度上限）決定成本曲線。個人專案看免費額度夠不夠、規模化看線性成長何時跟自建的固定成本加人力出現交叉點。</li>
<li><strong>人力與操作</strong>：外包省下維運、換來 vendor 管理 — SDK 升級、API 變更追蹤、定價政策變動的因應、都是新的操作成本、只是從機房移到供應商關係。</li>
<li><strong>機會成本</strong>：買對、省下的工程時間投到差異化；買錯、付出遷出代價加 <a href="/blog/backend/knowledge-cards/vendor-lock-in/" data-link-title="Vendor Lock-In" data-link-desc="說明採用供應商產品後，其 API 與格式滲入程式碼造成的退出成本">vendor lock-in</a>。「以後可能要客製」是最常見的偽自建理由、客製需求真的出現再遷、總成本通常低於提前自建。</li>
<li><strong>整合接縫成本</strong>：每多買一塊 feature SaaS、就多一道接縫 — 資料跨 SaaS 重複（會員同時在 Ragic 跟 app）、跨來源一致性、整合維護。買越多塊、系統的真正複雜度從「每塊能力內部」移到「能力之間的縫」。這是外包換來的隱性帳、跟「省下維運」是同一個決策的反面、評估買 vs 建時要跟省下的成本一起算。</li>
</ol>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>還沒過 whole-system gate：先讀 <a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型</a>、判斷整個系統該不該自建。</li>
<li>成本曲線交叉點的算法：見 <a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6 成本、風險與選型取捨</a>。</li>
<li>逐能力的 managed 選項：資料庫見 <a href="/blog/backend/01-database/vendors/postgresql/managed-pg-comparison/" data-link-title="Managed PostgreSQL Comparison" data-link-desc="RDS PostgreSQL、Aurora PostgreSQL、Cloud SQL、Azure Database for PostgreSQL、Neon、Supabase、Crunchy Bridge 的責任邊界比較">Managed PostgreSQL 比較</a>、認證見 <a href="/blog/backend/07-security-data-protection/vendors/" data-link-title="資安與資料保護 Vendor 清單" data-link-desc="規劃身份、秘密、金鑰、入口防護、供應鏈與偵測工具的服務頁撰寫順序與教學大綱">07 資安 vendor 清單</a>、佇列見 <a href="/blog/backend/03-message-queue/vendors/aws-sqs/" data-link-title="AWS SQS" data-link-desc="AWS managed queue、簡單可靠、無 ordering（standard）">AWS SQS</a>。</li>
<li>外包能力撐不住要搬回自建：執行劇本見 <a href="/blog/backend/10-system-evolution/managed-platform-exit/" data-link-title="10.3 託管形態遷出：資產線盤點與並行期執行" data-link-desc="0.21 升級自建 tripwire 觸發後的執行劇本 — 把遷出拆成資料、身分、流量、整合各自的可攜性與斷點、設計舊平台與新系統的並行期與回切窗口、用部分遷出作為中繼形態">10.3 託管形態遷出</a>。</li>
<li>BaaS 的概念背景：見 <a href="/blog/backend/knowledge-cards/baas/" data-link-title="BaaS（Backend as a Service）" data-link-desc="說明把認證、資料庫、檔案儲存、推播打包成現成模組、由前端 SDK 直連的後端交付形態">BaaS 知識卡片</a>。</li>
</ul>
]]></content:encoded></item><item><title>模組零案例正文</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/cases/</link><pubDate>Thu, 07 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/cases/</guid><description>&lt;p>這個資料夾的核心責任是把案例圖譜中的產業壓力轉成可回寫正文。圖譜負責索引，正文負責判讀訊號、風險邊界與下一步路由。&lt;/p>
&lt;h2 id="章節列表">章節列表&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>章節&lt;/th>
 &lt;th>主題&lt;/th>
 &lt;th>核心責任&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cases/fintech-compliance-and-selection-pressure/" data-link-title="FinTech：合規壓力下的後端選型" data-link-desc="在審計、留存與交易正確性要求下，如何平衡成本、風險與交付速度。">0.C1&lt;/a>&lt;/td>
 &lt;td>FinTech 合規壓力&lt;/td>
 &lt;td>把合規、留存、審計對選型的影響變成可判讀條件&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cases/gaming-peak-traffic-and-isolation/" data-link-title="Gaming：高峰流量與隔離邊界選型" data-link-desc="大型活動流量下，如何在低延遲與穩定性之間做可持續取捨。">0.C2&lt;/a>&lt;/td>
 &lt;td>Gaming 高峰流量&lt;/td>
 &lt;td>把低延遲與高峰容量風險轉成分層決策&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cases/healthcare-data-sovereignty-and-recovery/" data-link-title="Healthcare：資料主權與回復順序選型" data-link-desc="醫療場景下，如何把資料主權、存取邊界與災難回復放進同一套決策。">0.C3&lt;/a>&lt;/td>
 &lt;td>Healthcare 資料主權&lt;/td>
 &lt;td>把資料主權與回復順序放進同一個選型模型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cases/post-scale-migration-language-tool-architecture/" data-link-title="營運後技術轉換：語言、工具與架構何時該換" data-link-desc="服務營運一段時間後，如何判讀何時該轉語言、工具或架構，並用案例說明轉換動機。">0.C4&lt;/a>&lt;/td>
 &lt;td>營運後技術轉換&lt;/td>
 &lt;td>營運成熟後何時要轉語言、工具或架構，以及轉換成本邏輯&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table></description><content:encoded><![CDATA[<p>這個資料夾的核心責任是把案例圖譜中的產業壓力轉成可回寫正文。圖譜負責索引，正文負責判讀訊號、風險邊界與下一步路由。</p>
<h2 id="章節列表">章節列表</h2>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>主題</th>
          <th>核心責任</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/00-service-selection/cases/fintech-compliance-and-selection-pressure/" data-link-title="FinTech：合規壓力下的後端選型" data-link-desc="在審計、留存與交易正確性要求下，如何平衡成本、風險與交付速度。">0.C1</a></td>
          <td>FinTech 合規壓力</td>
          <td>把合規、留存、審計對選型的影響變成可判讀條件</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/cases/gaming-peak-traffic-and-isolation/" data-link-title="Gaming：高峰流量與隔離邊界選型" data-link-desc="大型活動流量下，如何在低延遲與穩定性之間做可持續取捨。">0.C2</a></td>
          <td>Gaming 高峰流量</td>
          <td>把低延遲與高峰容量風險轉成分層決策</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/cases/healthcare-data-sovereignty-and-recovery/" data-link-title="Healthcare：資料主權與回復順序選型" data-link-desc="醫療場景下，如何把資料主權、存取邊界與災難回復放進同一套決策。">0.C3</a></td>
          <td>Healthcare 資料主權</td>
          <td>把資料主權與回復順序放進同一個選型模型</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/cases/post-scale-migration-language-tool-architecture/" data-link-title="營運後技術轉換：語言、工具與架構何時該換" data-link-desc="服務營運一段時間後，如何判讀何時該轉語言、工具或架構，並用案例說明轉換動機。">0.C4</a></td>
          <td>營運後技術轉換</td>
          <td>營運成熟後何時要轉語言、工具或架構，以及轉換成本邏輯</td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item><item><title>0.0 後端需求分類地圖</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/backend-demand-taxonomy/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/backend-demand-taxonomy/</guid><description>&lt;p>後端需求分類的核心原則是先辨識「工程問題的形狀」。同一個產品功能可能同時包含狀態保存、讀取壓力、非同步處理、即時推送、診斷、部署與可靠性驗證；選型前要先把問題拆開，才有辦法討論服務能力。本章預設「自建」已經成立 — 更早一層的交付形態判斷（託管平台 / BaaS / 自建）見 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型&lt;/a>。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>把後端需求拆成可討論的工程類型&lt;/li>
&lt;li>用產品情境辨識狀態、讀取、非同步、即時、診斷與交付需求&lt;/li>
&lt;li>找出需求討論中的常見陷阱&lt;/li>
&lt;li>把需求類型連到後續選型章節&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="觀察產品功能通常混合多種後端需求">【觀察】產品功能通常混合多種後端需求&lt;/h2>
&lt;p>需求分類的第一個判斷是「這個功能其實包含哪些後端責任」。例如一個電商結帳流程看起來是單一功能，但它可能同時需要保存訂單、查商品與庫存、呼叫付款、寄通知、更新報表、記錄操作訊號與支援發版回滾。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>需求類型&lt;/th>
 &lt;th>核心問題&lt;/th>
 &lt;th>常見情境&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>狀態保存&lt;/td>
 &lt;td>系統承認哪份資料是正式狀態&lt;/td>
 &lt;td>訂單、會員、付款、權限&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>讀取壓力&lt;/td>
 &lt;td>同一份資料被大量重複讀取&lt;/td>
 &lt;td>商品頁、權限摘要、首頁推薦&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>非同步工作&lt;/td>
 &lt;td>request 結束後仍要可靠處理&lt;/td>
 &lt;td>寄信、轉檔、同步外部系統&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>即時互動&lt;/td>
 &lt;td>client 需要持續接收狀態變化&lt;/td>
 &lt;td>聊天、通知、進度更新、presence&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>操作診斷&lt;/td>
 &lt;td>出事時要知道原因與影響範圍&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&lt;/a>、metric、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>服務交付&lt;/td>
 &lt;td>服務要穩定發版、擴容與接流量&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/container/" data-link-title="Container" data-link-desc="說明容器如何包裝服務、隔離依賴與影響部署方式">container&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/load-balancer/" data-link-title="Load Balancer" data-link-desc="說明流量如何分散、排空與導向健康節點">load balancer&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>可靠性驗證&lt;/td>
 &lt;td>事故前要驗證容量與失敗情境&lt;/td>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ci-pipeline/" data-link-title="CI Pipeline" data-link-desc="說明持續整合流程如何在合併前驗證品質與相容性">CI pipeline&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">load test&lt;/a>、fuzz、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/chaos-test/" data-link-title="Chaos Test" data-link-desc="說明透過受控故障注入驗證系統在異常條件下的恢復能力">chaos test&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表是需求索引。每個類型後面都會對應到不同的能力地圖，但實際功能常會同時命中多列。&lt;/p>
&lt;h2 id="判讀狀態保存需求要先找正式狀態">【判讀】狀態保存需求要先找正式狀態&lt;/h2>
&lt;p>狀態保存需求的核心訊號是「資料會被後續流程承認」。當使用者、營運人員、付款系統或稽核流程都需要相信某份資料，這份資料就需要明確的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth&lt;/a>。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>訂單建立後，付款、出貨、客服與退款都依賴同一筆訂單狀態。&lt;/li>
&lt;li>會員升級方案後，API 權限、帳單與使用量限制都要讀到同一個 plan。&lt;/li>
&lt;li>文章發布後，公開頁面、搜尋索引與後台審核都要知道目前版本。&lt;/li>
&lt;/ul>
&lt;p>這類需求的陷阱是把「看起來能存資料」的地方都當成正式狀態。快取、搜尋索引、log 與事件流可能保存資料副本，但它們承擔的責任不同。正式狀態要回答誰能寫入、哪些欄位要一致、失敗後如何恢復。&lt;/p>
&lt;p>下一步可讀：&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">狀態與資料儲存選型&lt;/a>。&lt;/p>
&lt;h2 id="判讀讀取壓力需求要先找重複讀取路徑">【判讀】讀取壓力需求要先找重複讀取路徑&lt;/h2>
&lt;p>讀取壓力需求的核心訊號是「同一類資料被大量重複讀取」。這種壓力通常先出現在熱門頁面、權限檢查、設定查詢、推薦摘要或即時狀態查詢。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>活動商品頁在短時間內被大量瀏覽，但商品描述變更頻率低。&lt;/li>
&lt;li>每個 API request 都要讀取使用者權限與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/feature-flag/" data-link-title="Feature Flag" data-link-desc="說明如何用可動態開關控制功能曝光與風險">Feature Flag&lt;/a>。&lt;/li>
&lt;li>即時通知服務需要頻繁查詢 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic&lt;/a> 的在線訂閱者。&lt;/li>
&lt;/ul>
&lt;p>這類需求的陷阱是把所有慢查詢都當成快取問題。若查詢慢是因為資料模型、索引、N+1 request、外部 API &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout&lt;/a> 或資料量爆炸，快取只能暫時吸收症狀。讀取壓力要先確認是否有明確 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth&lt;/a>、資料能否重建、失效後是否能接受短暫不一致。&lt;/p>
&lt;p>下一步可讀：&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">後端服務能力地圖&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">狀態與資料儲存選型&lt;/a>。&lt;/p>
&lt;h2 id="判讀非同步需求要先找-request-邊界">【判讀】非同步需求要先找 request 邊界&lt;/h2>
&lt;p>非同步需求的核心訊號是「使用者不需要等到所有後續工作完成」。一個 request 可以先完成主要承諾，後續工作由背景流程、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a>、stream 或 outbox 接續處理。&lt;/p>
&lt;p>接近真實網路服務的例子包括：&lt;/p>
&lt;ul>
&lt;li>付款成功頁先回應使用者，email、推播與報表更新在後面完成。&lt;/li>
&lt;li>使用者上傳影片後先看到處理中狀態，轉檔與縮圖由背景 worker 執行。&lt;/li>
&lt;li>外部 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook&lt;/a> 進來後先驗證與保存，再由後續流程重試與分派。&lt;/li>
&lt;/ul>
&lt;p>這類需求的陷阱是把「放到背景」視為可靠性保證。背景工作離開 request 後，系統還要回答是否可遺失、是否重試、是否允許重複、是否需要順序、process 重啟後工作是否仍存在。&lt;/p>
&lt;p>下一步可讀：&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">非同步與事件傳遞選型&lt;/a>。&lt;/p>
&lt;h2 id="判讀即時互動需求要先找狀態補償方式">【判讀】即時互動需求要先找狀態補償方式&lt;/h2>
&lt;p>即時互動需求的核心訊號是「client 持續在線，並期待快速看到變化」。聊天、通知、進度更新、多人協作、presence 與 dashboard 都屬於這類需求。&lt;/p></description><content:encoded><![CDATA[<p>後端需求分類的核心原則是先辨識「工程問題的形狀」。同一個產品功能可能同時包含狀態保存、讀取壓力、非同步處理、即時推送、診斷、部署與可靠性驗證；選型前要先把問題拆開，才有辦法討論服務能力。本章預設「自建」已經成立 — 更早一層的交付形態判斷（託管平台 / BaaS / 自建）見 <a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型</a>。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>把後端需求拆成可討論的工程類型</li>
<li>用產品情境辨識狀態、讀取、非同步、即時、診斷與交付需求</li>
<li>找出需求討論中的常見陷阱</li>
<li>把需求類型連到後續選型章節</li>
</ol>
<hr>
<h2 id="觀察產品功能通常混合多種後端需求">【觀察】產品功能通常混合多種後端需求</h2>
<p>需求分類的第一個判斷是「這個功能其實包含哪些後端責任」。例如一個電商結帳流程看起來是單一功能，但它可能同時需要保存訂單、查商品與庫存、呼叫付款、寄通知、更新報表、記錄操作訊號與支援發版回滾。</p>
<table>
  <thead>
      <tr>
          <th>需求類型</th>
          <th>核心問題</th>
          <th>常見情境</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>狀態保存</td>
          <td>系統承認哪份資料是正式狀態</td>
          <td>訂單、會員、付款、權限</td>
      </tr>
      <tr>
          <td>讀取壓力</td>
          <td>同一份資料被大量重複讀取</td>
          <td>商品頁、權限摘要、首頁推薦</td>
      </tr>
      <tr>
          <td>非同步工作</td>
          <td>request 結束後仍要可靠處理</td>
          <td>寄信、轉檔、同步外部系統</td>
      </tr>
      <tr>
          <td>即時互動</td>
          <td>client 需要持續接收狀態變化</td>
          <td>聊天、通知、進度更新、presence</td>
      </tr>
      <tr>
          <td>操作診斷</td>
          <td>出事時要知道原因與影響範圍</td>
          <td><a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a>、metric、<a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a>、<a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a></td>
      </tr>
      <tr>
          <td>服務交付</td>
          <td>服務要穩定發版、擴容與接流量</td>
          <td><a href="/blog/backend/knowledge-cards/container/" data-link-title="Container" data-link-desc="說明容器如何包裝服務、隔離依賴與影響部署方式">container</a>、<a href="/blog/backend/knowledge-cards/load-balancer/" data-link-title="Load Balancer" data-link-desc="說明流量如何分散、排空與導向健康節點">load balancer</a>、<a href="/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness</a></td>
      </tr>
      <tr>
          <td>可靠性驗證</td>
          <td>事故前要驗證容量與失敗情境</td>
          <td><a href="/blog/backend/knowledge-cards/ci-pipeline/" data-link-title="CI Pipeline" data-link-desc="說明持續整合流程如何在合併前驗證品質與相容性">CI pipeline</a>、<a href="/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">load test</a>、fuzz、<a href="/blog/backend/knowledge-cards/chaos-test/" data-link-title="Chaos Test" data-link-desc="說明透過受控故障注入驗證系統在異常條件下的恢復能力">chaos test</a></td>
      </tr>
  </tbody>
</table>
<p>這張表是需求索引。每個類型後面都會對應到不同的能力地圖，但實際功能常會同時命中多列。</p>
<h2 id="判讀狀態保存需求要先找正式狀態">【判讀】狀態保存需求要先找正式狀態</h2>
<p>狀態保存需求的核心訊號是「資料會被後續流程承認」。當使用者、營運人員、付款系統或稽核流程都需要相信某份資料，這份資料就需要明確的 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a>。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>訂單建立後，付款、出貨、客服與退款都依賴同一筆訂單狀態。</li>
<li>會員升級方案後，API 權限、帳單與使用量限制都要讀到同一個 plan。</li>
<li>文章發布後，公開頁面、搜尋索引與後台審核都要知道目前版本。</li>
</ul>
<p>這類需求的陷阱是把「看起來能存資料」的地方都當成正式狀態。快取、搜尋索引、log 與事件流可能保存資料副本，但它們承擔的責任不同。正式狀態要回答誰能寫入、哪些欄位要一致、失敗後如何恢復。</p>
<p>下一步可讀：<a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">狀態與資料儲存選型</a>。</p>
<h2 id="判讀讀取壓力需求要先找重複讀取路徑">【判讀】讀取壓力需求要先找重複讀取路徑</h2>
<p>讀取壓力需求的核心訊號是「同一類資料被大量重複讀取」。這種壓力通常先出現在熱門頁面、權限檢查、設定查詢、推薦摘要或即時狀態查詢。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>活動商品頁在短時間內被大量瀏覽，但商品描述變更頻率低。</li>
<li>每個 API request 都要讀取使用者權限與 <a href="/blog/backend/knowledge-cards/feature-flag/" data-link-title="Feature Flag" data-link-desc="說明如何用可動態開關控制功能曝光與風險">Feature Flag</a>。</li>
<li>即時通知服務需要頻繁查詢 <a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic</a> 的在線訂閱者。</li>
</ul>
<p>這類需求的陷阱是把所有慢查詢都當成快取問題。若查詢慢是因為資料模型、索引、N+1 request、外部 API <a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout</a> 或資料量爆炸，快取只能暫時吸收症狀。讀取壓力要先確認是否有明確 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a>、資料能否重建、失效後是否能接受短暫不一致。</p>
<p>下一步可讀：<a href="/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">後端服務能力地圖</a> 與 <a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">狀態與資料儲存選型</a>。</p>
<h2 id="判讀非同步需求要先找-request-邊界">【判讀】非同步需求要先找 request 邊界</h2>
<p>非同步需求的核心訊號是「使用者不需要等到所有後續工作完成」。一個 request 可以先完成主要承諾，後續工作由背景流程、<a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a>、stream 或 outbox 接續處理。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>付款成功頁先回應使用者，email、推播與報表更新在後面完成。</li>
<li>使用者上傳影片後先看到處理中狀態，轉檔與縮圖由背景 worker 執行。</li>
<li>外部 <a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook</a> 進來後先驗證與保存，再由後續流程重試與分派。</li>
</ul>
<p>這類需求的陷阱是把「放到背景」視為可靠性保證。背景工作離開 request 後，系統還要回答是否可遺失、是否重試、是否允許重複、是否需要順序、process 重啟後工作是否仍存在。</p>
<p>下一步可讀：<a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">非同步與事件傳遞選型</a>。</p>
<h2 id="判讀即時互動需求要先找狀態補償方式">【判讀】即時互動需求要先找狀態補償方式</h2>
<p>即時互動需求的核心訊號是「client 持續在線，並期待快速看到變化」。聊天、通知、進度更新、多人協作、presence 與 dashboard 都屬於這類需求。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>客服聊天室需要把新訊息推給在線客服與使用者。</li>
<li>任務處理頁需要即時顯示轉檔進度。</li>
<li>共同編輯工具需要讓其他使用者看到狀態變化。</li>
</ul>
<p>這類需求的陷阱是把即時通道當成唯一可靠資料來源。<a href="/blog/backend/knowledge-cards/websocket/" data-link-title="WebSocket" data-link-desc="說明 WebSocket 如何提供長連線雙向即時通訊">WebSocket</a>、<a href="/blog/backend/knowledge-cards/sse/" data-link-title="Server-Sent Events (SSE)" data-link-desc="說明 SSE 如何透過 HTTP 長連線向 client 單向推送事件">Server-Sent Events (SSE)</a> 或 <a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">pub/sub</a> 適合降低延遲，但 client 斷線、server 重啟、網路切換都會造成缺口。即時需求要先決定離線後如何 <a href="/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">offline catch-up</a>、哪些訊息可丟、哪些訊息需要正式保存。</p>
<p>下一步可讀：<a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">非同步與事件傳遞選型</a> 與 <a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">操作平台選型</a>。</p>
<h2 id="判讀操作診斷需求要先找決策問題">【判讀】操作診斷需求要先找決策問題</h2>
<p>操作診斷需求的核心訊號是「團隊需要用訊號做決策」。log、metric、trace、dashboard 與 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 的用途不同；它們都應服務某個排障、容量、告警或產品營運問題。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>API 延遲上升時，要判斷瓶頸在資料庫、外部 API、queue 還是某個版本。</li>
<li>queue lag 增加時，要判斷 <a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer</a> 變快、<a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a> 變慢，還是下游失敗。</li>
<li>某地區 <a href="/blog/backend/knowledge-cards/websocket/" data-link-title="WebSocket" data-link-desc="說明 WebSocket 如何提供長連線雙向即時通訊">WebSocket</a> disconnect 增加時，要知道是 client 版本、網路入口還是部署節點問題。</li>
</ul>
<p>這類需求的陷阱是先買平台，再補欄位語意。沒有穩定欄位、<a href="/blog/backend/knowledge-cards/trace-context/" data-link-title="Trace Context" data-link-desc="說明跨服務 request 如何用 trace context 串起路徑與耗時">trace context</a>、錯誤分類與 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a>，觀測平台只能保存大量難以操作的訊號。</p>
<p>下一步可讀：<a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">操作平台選型</a>。</p>
<h2 id="判讀交付與可靠性需求要先找變更風險">【判讀】交付與可靠性需求要先找變更風險</h2>
<p>交付與可靠性需求的核心訊號是「系統變更本身帶來風險」。當服務需要頻繁發版、水平擴容、處理尖峰、承受下游失敗或保證回歸品質，部署平台與可靠性驗證就會變成需求的一部分。</p>
<p>接近真實網路服務的例子包括：</p>
<ul>
<li>發版時新版本尚未 ready 就接到流量，造成部分 request 失敗。</li>
<li>活動流量前沒有容量證據，只能靠臨時加機器。</li>
<li>重要 parser 一次更新後影響大量 <a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook</a>，缺少 fuzz 或回歸案例。</li>
</ul>
<p>這類需求的陷阱是把可靠性視為上線後的補救工作。交付與可靠性要在設計時就定義 readiness、shutdown、rollback、<a href="/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">load test</a>、資料 <a href="/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration</a> 與事故演練的檢查點。</p>
<p>下一步可讀：<a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">操作平台選型</a>。</p>
<p><strong>規模成長路線下一站 → <a href="/blog/backend/10-system-evolution/service-decomposition-boundaries/" data-link-title="10.1 服務拆分與邊界判讀" data-link-desc="整理 monolith vs microservice 取捨、服務邊界判讀訊號、拆分時機與回退路徑">10.1 服務拆分與邊界判讀</a></strong>：需求分類完之後、第一個判讀通常是「該不該把服務拆開」。若讀者剛從影片進來想學「能跑 → 能撐」演進、回到 <a href="/blog/backend/#%e5%be%9e%e5%bd%b1%e7%89%87%e8%a7%80%e7%9c%be%e7%9a%84%e8%a9%9e%e5%bd%99%e9%80%b2%e5%85%a5" data-link-title="Backend 服務實務指南" data-link-desc="用跨語言教學路線整理資料庫、快取、訊息佇列、觀測、部署、可靠性、資安、事故與容量等後端服務能力">_index 規模成長路線</a> 看完整路徑。</p>
<h2 id="小結">小結</h2>
<p>後端需求分類要先拆問題，再談服務。狀態保存、讀取壓力、非同步工作、即時互動、操作診斷、服務交付與可靠性驗證各自有不同判斷訊號。需求形狀清楚後，後續才進入資料庫、快取、queue、觀測平台與部署平台的能力比較。</p>
]]></content:encoded></item><item><title>模組零：後端服務選型</title><link>https://tarrragon.github.io/blog/backend/00-service-selection/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/00-service-selection/</guid><description>&lt;p>後端服務選型的核心目標是把「需求類型」轉成「服務能力」。資料庫、快取、訊息佇列、觀測平台與部署平台都能提升系統能力，但它們解決的是不同問題；選型時要先辨識需求、流量、資料量、失敗代價與成本模型，再進入具體產品比較。&lt;/p>
&lt;p>進入需求分類之前、先確認一個更早的判斷：&lt;strong>這個服務值得自建嗎&lt;/strong>。差異化在商品、內容或服務品質、需求落在 Wix / Shopify、Google Apps Script、Firebase、WordPress 這類現成平台標準域的業務、託管形態可能是成本上更誠實的起點；判讀方式與可遷出保險見 &lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型&lt;/a>、日後升級自建 tripwire 觸發的遷出執行見 &lt;a href="https://tarrragon.github.io/blog/backend/10-system-evolution/managed-platform-exit/" data-link-title="10.3 託管形態遷出：資產線盤點與並行期執行" data-link-desc="0.21 升級自建 tripwire 觸發後的執行劇本 — 把遷出拆成資料、身分、流量、整合各自的可攜性與斷點、設計舊平台與新系統的並行期與回切窗口、用部分遷出作為中繼形態">10.3 託管形態遷出&lt;/a>。本模組其餘章節預設自建已成立。&lt;/p>
&lt;p>本模組先建立跨分類的選型語言。後續進入 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a>、Redis、message &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a>、observability 或 deployment 資料夾時，每個資料夾開頭都應延續同一個形式：先說明這類服務解決什麼問題，再比較同質服務的差異，最後才進入實作細節。&lt;/p>
&lt;p>閱讀本模組前，建議先把 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/" data-link-title="Knowledge Cards" data-link-desc="用原子化卡片整理後端服務選型前需要理解的 domain knowhow">前置知識卡片&lt;/a> 當成共同詞彙索引。選型文章會使用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">dead-letter queue&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">降級&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">停機&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness&lt;/a> 等概念；這些概念的完整 domain knowhow 放在卡片中，章節本文則專注於需求判讀與服務能力取捨。&lt;/p>
&lt;h2 id="章節列表">章節列表&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>章節&lt;/th>
 &lt;th>主題&lt;/th>
 &lt;th>關鍵收穫&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0&lt;/a>&lt;/td>
 &lt;td>後端需求分類地圖&lt;/td>
 &lt;td>先把需求分成狀態、讀取、非同步、即時、診斷、交付與可靠性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1&lt;/a>&lt;/td>
 &lt;td>後端服務能力地圖&lt;/td>
 &lt;td>用需求類型判斷該先看資料庫、快取、queue、觀測或部署平台&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2&lt;/a>&lt;/td>
 &lt;td>狀態與資料儲存選型&lt;/td>
 &lt;td>區分 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth&lt;/a>、快取、搜尋索引、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">event log&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage&lt;/a>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3&lt;/a>&lt;/td>
 &lt;td>非同步與事件傳遞選型&lt;/td>
 &lt;td>區分背景工作、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue&lt;/a>、stream、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">pub/sub&lt;/a> 與 outbox&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4&lt;/a>&lt;/td>
 &lt;td>操作平台選型&lt;/td>
 &lt;td>區分 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&lt;/a>、metric、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert&lt;/a>、deployment 與 reliability&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5&lt;/a>&lt;/td>
 &lt;td>流量與資料量評估&lt;/td>
 &lt;td>用 QPS、burst、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-key/" data-link-title="Hot Key" data-link-desc="說明單一 key 承受大量讀寫時如何形成容量瓶頸">hot key&lt;/a>、資料成長與保留期限評估需求規模&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6&lt;/a>&lt;/td>
 &lt;td>成本、風險與選型取捨&lt;/td>
 &lt;td>用人力成本、雲端成本、操作成本與失敗代價判斷投入順序&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7&lt;/a>&lt;/td>
 &lt;td>錯誤定位、觀測訊號與備援切換設計&lt;/td>
 &lt;td>從錯誤分類、定位線索、降級與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">failover&lt;/a> 設計服務可維護性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8&lt;/a>&lt;/td>
 &lt;td>資安與資料保護需求&lt;/td>
 &lt;td>從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/knowledge-graph-message-flow/" data-link-title="0.9 知識網：訊息與事件決策路徑" data-link-desc="把 broker、queue、ack、retry、DLQ、replay 與 idempotency 串成可操作的非同步決策語言">0.9&lt;/a>&lt;/td>
 &lt;td>知識網：訊息與事件決策路徑&lt;/td>
 &lt;td>用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a>、queue、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">ack&lt;/a>、retry、DLQ、replay 串出非同步決策脈絡&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/knowledge-graph-operations-security/" data-link-title="0.10 知識網：容量、觀測與資安決策路徑" data-link-desc="把容量、可觀測、備援、權限、憑證與稽核術語串成統一的服務治理語言">0.10&lt;/a>&lt;/td>
 &lt;td>知識網：容量、觀測與資安決策路徑&lt;/td>
 &lt;td>用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO&lt;/a>/&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO&lt;/a>、權限與憑證串出操作脈絡&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/red-team-cross-service-weaknesses/" data-link-title="0.11 攻擊者視角（紅隊）：跨服務弱點判讀總表" data-link-desc="用攻擊面、可觀察訊號與失敗代價，建立 backend 選型前的弱點盤點框架">0.11&lt;/a>&lt;/td>
 &lt;td>攻擊者視角（紅隊）：跨服務弱點判讀總表&lt;/td>
 &lt;td>用攻擊面、可觀察訊號與失敗代價建立跨分類的弱點判讀順序&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/operations-control-service-selection/" data-link-title="0.12 觀測、可靠性與事故服務選型" data-link-desc="從訊號、驗證與響應三層能力判斷操作控制服務的選型順序">0.12&lt;/a>&lt;/td>
 &lt;td>觀測、可靠性與事故服務選型&lt;/td>
 &lt;td>用訊號、驗證、響應與閉環四層能力判斷操作控制服務該如何選型&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/operations-control-vertical-slice/" data-link-title="0.13 操作控制 vertical slice 實作入口" data-link-desc="用一個服務串起觀測證據、可靠性驗證、事故決策與回寫閉環">0.13&lt;/a>&lt;/td>
 &lt;td>操作控制 vertical slice 實作入口&lt;/td>
 &lt;td>用一個服務串起 evidence package、verification handoff、decision log 與 write-back&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/enterprise-selection-case-atlas/" data-link-title="0.14 企業選型案例圖譜" data-link-desc="蒐集不同類型與不同規模企業的技術選型案例，作為後端選型判讀的跨情境補充。">0.14&lt;/a>&lt;/td>
 &lt;td>企業選型案例圖譜&lt;/td>
 &lt;td>以企業型態與規模階段分組案例，建立跨產業、跨規模的選型壓力對照&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cross-module-checkout-episode/" data-link-title="0.15 跨模組 Checkout Episode：從資料寫入到觀測證據" data-link-desc="以 checkout 為切片，走完 DB write → cache invalidation → event publish → observability evidence 四層串聯，標示各模組的交接欄位與失敗判讀">0.15&lt;/a>&lt;/td>
 &lt;td>跨模組 Checkout Episode&lt;/td>
 &lt;td>用一條 checkout 路徑走完 DB write → cache invalidation → event publish → observability evidence 四層串聯&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/cloud-vendor-capability-mapping/" data-link-title="0.19 雲端服務對照地圖（AWS / GCP / Azure）" data-link-desc="把後端能力分類對照到 AWS / GCP / Azure 的具體服務名稱、保留跨雲遷移與選型差異的判讀重點">0.19&lt;/a>&lt;/td>
 &lt;td>雲端服務對照地圖（AWS / GCP / Azure）&lt;/td>
 &lt;td>後端能力分類對照三家雲廠商、failover / 一致性 / 計價差異、跨雲遷移判讀&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21&lt;/a>&lt;/td>
 &lt;td>交付形態選型：託管平台、BaaS 與自建&lt;/td>
 &lt;td>在自建選型之前先判斷該用 Wix / Shopify、Apps Script、Firebase、WordPress 還是自建、並保留可遷出路徑與升級 tripwire&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22&lt;/a>&lt;/td>
 &lt;td>能力級買 vs 建：feature-as-a-service&lt;/td>
 &lt;td>自建核心成立後、逐能力判斷外包還是自建：三種外包深度、no-code 到 dev-tool 光譜、買 vs 建判準與整合接縫成本&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>服務拆分判讀（原 0.18）與執行 Runbook（原 0.20）已移到 &lt;a href="https://tarrragon.github.io/blog/backend/10-system-evolution/" data-link-title="模組十：系統演進與遷移" data-link-desc="處理服務拆分、跨服務重構、大型遷移與雲端切換的執行紀律 — 設計階段的選型判斷見模組零、執行階段的高風險變更收斂在本模組">模組十：系統演進與遷移&lt;/a> — 設計階段的選型判讀留本模組、執行階段的高風險變更收斂到模組十。&lt;/p></description><content:encoded><![CDATA[<p>後端服務選型的核心目標是把「需求類型」轉成「服務能力」。資料庫、快取、訊息佇列、觀測平台與部署平台都能提升系統能力，但它們解決的是不同問題；選型時要先辨識需求、流量、資料量、失敗代價與成本模型，再進入具體產品比較。</p>
<p>進入需求分類之前、先確認一個更早的判斷：<strong>這個服務值得自建嗎</strong>。差異化在商品、內容或服務品質、需求落在 Wix / Shopify、Google Apps Script、Firebase、WordPress 這類現成平台標準域的業務、託管形態可能是成本上更誠實的起點；判讀方式與可遷出保險見 <a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型</a>、日後升級自建 tripwire 觸發的遷出執行見 <a href="/blog/backend/10-system-evolution/managed-platform-exit/" data-link-title="10.3 託管形態遷出：資產線盤點與並行期執行" data-link-desc="0.21 升級自建 tripwire 觸發後的執行劇本 — 把遷出拆成資料、身分、流量、整合各自的可攜性與斷點、設計舊平台與新系統的並行期與回切窗口、用部分遷出作為中繼形態">10.3 託管形態遷出</a>。本模組其餘章節預設自建已成立。</p>
<p>本模組先建立跨分類的選型語言。後續進入 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a>、Redis、message <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a>、observability 或 deployment 資料夾時，每個資料夾開頭都應延續同一個形式：先說明這類服務解決什麼問題，再比較同質服務的差異，最後才進入實作細節。</p>
<p>閱讀本模組前，建議先把 <a href="/blog/backend/knowledge-cards/" data-link-title="Knowledge Cards" data-link-desc="用原子化卡片整理後端服務選型前需要理解的 domain knowhow">前置知識卡片</a> 當成共同詞彙索引。選型文章會使用 <a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag</a>、<a href="/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">dead-letter queue</a>、<a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay</a>、<a href="/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">降級</a>、<a href="/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">停機</a>、<a href="/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness</a> 等概念；這些概念的完整 domain knowhow 放在卡片中，章節本文則專注於需求判讀與服務能力取捨。</p>
<h2 id="章節列表">章節列表</h2>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>主題</th>
          <th>關鍵收穫</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0</a></td>
          <td>後端需求分類地圖</td>
          <td>先把需求分成狀態、讀取、非同步、即時、診斷、交付與可靠性</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1</a></td>
          <td>後端服務能力地圖</td>
          <td>用需求類型判斷該先看資料庫、快取、queue、觀測或部署平台</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a></td>
          <td>狀態與資料儲存選型</td>
          <td>區分 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a>、快取、搜尋索引、<a href="/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">event log</a> 與 <a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage</a></td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3</a></td>
          <td>非同步與事件傳遞選型</td>
          <td>區分背景工作、<a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue</a>、stream、<a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">pub/sub</a> 與 outbox</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4</a></td>
          <td>操作平台選型</td>
          <td>區分 <a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a>、metric、<a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a>、<a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a>、<a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>、deployment 與 reliability</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a></td>
          <td>流量與資料量評估</td>
          <td>用 QPS、burst、<a href="/blog/backend/knowledge-cards/hot-key/" data-link-title="Hot Key" data-link-desc="說明單一 key 承受大量讀寫時如何形成容量瓶頸">hot key</a>、資料成長與保留期限評估需求規模</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
          <td>成本、風險與選型取捨</td>
          <td>用人力成本、雲端成本、操作成本與失敗代價判斷投入順序</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a></td>
          <td>錯誤定位、觀測訊號與備援切換設計</td>
          <td>從錯誤分類、定位線索、降級與 <a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">failover</a> 設計服務可維護性</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8</a></td>
          <td>資安與資料保護需求</td>
          <td>從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/knowledge-graph-message-flow/" data-link-title="0.9 知識網：訊息與事件決策路徑" data-link-desc="把 broker、queue、ack、retry、DLQ、replay 與 idempotency 串成可操作的非同步決策語言">0.9</a></td>
          <td>知識網：訊息與事件決策路徑</td>
          <td>用 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a>、queue、<a href="/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">ack</a>、retry、DLQ、replay 串出非同步決策脈絡</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/knowledge-graph-operations-security/" data-link-title="0.10 知識網：容量、觀測與資安決策路徑" data-link-desc="把容量、可觀測、備援、權限、憑證與稽核術語串成統一的服務治理語言">0.10</a></td>
          <td>知識網：容量、觀測與資安決策路徑</td>
          <td>用 <a href="/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure</a>、<a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout</a>、<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a>、<a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO</a>/<a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a>、權限與憑證串出操作脈絡</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/red-team-cross-service-weaknesses/" data-link-title="0.11 攻擊者視角（紅隊）：跨服務弱點判讀總表" data-link-desc="用攻擊面、可觀察訊號與失敗代價，建立 backend 選型前的弱點盤點框架">0.11</a></td>
          <td>攻擊者視角（紅隊）：跨服務弱點判讀總表</td>
          <td>用攻擊面、可觀察訊號與失敗代價建立跨分類的弱點判讀順序</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/operations-control-service-selection/" data-link-title="0.12 觀測、可靠性與事故服務選型" data-link-desc="從訊號、驗證與響應三層能力判斷操作控制服務的選型順序">0.12</a></td>
          <td>觀測、可靠性與事故服務選型</td>
          <td>用訊號、驗證、響應與閉環四層能力判斷操作控制服務該如何選型</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/operations-control-vertical-slice/" data-link-title="0.13 操作控制 vertical slice 實作入口" data-link-desc="用一個服務串起觀測證據、可靠性驗證、事故決策與回寫閉環">0.13</a></td>
          <td>操作控制 vertical slice 實作入口</td>
          <td>用一個服務串起 evidence package、verification handoff、decision log 與 write-back</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/enterprise-selection-case-atlas/" data-link-title="0.14 企業選型案例圖譜" data-link-desc="蒐集不同類型與不同規模企業的技術選型案例，作為後端選型判讀的跨情境補充。">0.14</a></td>
          <td>企業選型案例圖譜</td>
          <td>以企業型態與規模階段分組案例，建立跨產業、跨規模的選型壓力對照</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/cross-module-checkout-episode/" data-link-title="0.15 跨模組 Checkout Episode：從資料寫入到觀測證據" data-link-desc="以 checkout 為切片，走完 DB write → cache invalidation → event publish → observability evidence 四層串聯，標示各模組的交接欄位與失敗判讀">0.15</a></td>
          <td>跨模組 Checkout Episode</td>
          <td>用一條 checkout 路徑走完 DB write → cache invalidation → event publish → observability evidence 四層串聯</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/cloud-vendor-capability-mapping/" data-link-title="0.19 雲端服務對照地圖（AWS / GCP / Azure）" data-link-desc="把後端能力分類對照到 AWS / GCP / Azure 的具體服務名稱、保留跨雲遷移與選型差異的判讀重點">0.19</a></td>
          <td>雲端服務對照地圖（AWS / GCP / Azure）</td>
          <td>後端能力分類對照三家雲廠商、failover / 一致性 / 計價差異、跨雲遷移判讀</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21</a></td>
          <td>交付形態選型：託管平台、BaaS 與自建</td>
          <td>在自建選型之前先判斷該用 Wix / Shopify、Apps Script、Firebase、WordPress 還是自建、並保留可遷出路徑與升級 tripwire</td>
      </tr>
      <tr>
          <td><a href="/blog/backend/00-service-selection/capability-buy-vs-build/" data-link-title="0.22 能力級買 vs 建：feature-as-a-service 與 BaaS bundle 選型" data-link-desc="在交付形態決定整個系統要不要自建之後、逐能力判斷該外包還是自建：辨識 managed 基礎設施、feature SaaS 與 BaaS bundle 三種外包深度、no-code 到 dev-tool 的服務光譜、買 vs 建判準與權重浮動、整合接縫與遷出代價">0.22</a></td>
          <td>能力級買 vs 建：feature-as-a-service</td>
          <td>自建核心成立後、逐能力判斷外包還是自建：三種外包深度、no-code 到 dev-tool 光譜、買 vs 建判準與整合接縫成本</td>
      </tr>
  </tbody>
</table>
<p>服務拆分判讀（原 0.18）與執行 Runbook（原 0.20）已移到 <a href="/blog/backend/10-system-evolution/" data-link-title="模組十：系統演進與遷移" data-link-desc="處理服務拆分、跨服務重構、大型遷移與雲端切換的執行紀律 — 設計階段的選型判斷見模組零、執行階段的高風險變更收斂在本模組">模組十：系統演進與遷移</a> — 設計階段的選型判讀留本模組、執行階段的高風險變更收斂到模組十。</p>
<h2 id="需求討論順序">需求討論順序</h2>
<p>這個討論順序預設自建已成立；交付形態的判讀見本頁開頭的分流與 <a href="/blog/backend/00-service-selection/delivery-mode-selection/" data-link-title="0.21 交付形態選型：從全託管到自建的光譜與邊界" data-link-desc="在進入資料庫、快取與部署選型之前、先判斷服務該用託管平台（Wix / Shopify / Google Sites）、辦公生態自動化（Apps Script）、BaaS（Firebase）、半託管 CMS（WordPress）還是自建、並為日後遷往自建保留可遷出路徑">0.21 交付形態選型</a>。</p>
<p>後端選型討論的核心順序是先問「問題長什麼樣」，再問「哪種能力能解決」。討論一開始就跳到產品名稱，容易把資料庫、快取、queue、觀測平台或部署平台當成固定答案；比較穩定的做法是先確認下列事項。</p>
<ol>
<li>需求類型：這是狀態保存、讀取加速、非同步處理、即時推送、診斷、交付，還是可靠性驗證問題？</li>
<li>流量形狀：流量是穩定、尖峰、長尾、單一 hot key，還是週期性批次？</li>
<li><a href="/blog/backend/knowledge-cards/data-lifecycle/" data-link-title="Data Lifecycle" data-link-desc="說明資料從建立、使用、保留到刪除的責任邊界">資料生命週期</a>：資料是否長期存在、能否重建、是否需要 audit、保留多久？</li>
<li>失敗代價：延遲、重複、遺失、短暫不一致、<a href="/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">停機</a>，各自會造成什麼產品後果？</li>
<li>成本模型：目前瓶頸來自雲端費用、人力維護、事故風險、開發速度，還是操作複雜度？</li>
<li>定位與備援：錯誤發生時能否分類、追蹤、<a href="/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">降級</a>、切換與恢復？</li>
<li>安全邊界：誰能存取哪些資料、資料如何遮罩、傳輸如何保護、操作如何稽核？</li>
</ol>
<p>這些問題回答清楚後，服務分類才會自然出現。正式狀態通常走向資料庫；重複讀取通常走向快取；request 外的可靠工作通常走向 queue 或 outbox；看不見系統行為通常走向 observability；部署與擴容不穩通常走向 platform；失敗前驗證不足通常走向 reliability pipeline。</p>
<h2 id="選型文章的共同格式">選型文章的共同格式</h2>
<p>每篇選型文章都使用同一個閱讀路徑：</p>
<ol>
<li><strong>核心原則</strong>：先說明這類服務解決哪一種工程問題。</li>
<li><strong>可觀察訊號</strong>：列出怎麼從產品需求、流量型態或事故症狀辨識問題。</li>
<li><strong>現實例子</strong>：用接近真實網路服務的例子建立判斷錨點。</li>
<li><strong>候選服務類型</strong>：列出同質服務或相近能力的差異。</li>
<li><strong>成本權衡</strong>：討論資安限制、流量穩定性、伺服器成本、人力成本與機會成本。</li>
<li><strong>下一步路由</strong>：指向對應 backend 模組，實作細節放在後續章節。</li>
</ol>
<p>本模組新增的需求分析章節會更早一層：它們負責討論「該問哪些問題」。服務分類章節則負責討論「問題落到哪種後端能力」。</p>
<h2 id="服務實體的固定討論段落">服務實體的固定討論段落</h2>
<p>服務實體章節的核心要求是每個選型都要回答「值得引入的理由」與「引入後的代價」。討論 PostgreSQL、Redis、RabbitMQ、Kafka、Prometheus、Kubernetes、<a href="/blog/backend/knowledge-cards/waf/" data-link-title="WAF" data-link-desc="說明 Web Application Firewall 如何在入口層過濾常見攻擊與濫用">WAF</a>、<a href="/blog/backend/knowledge-cards/iam/" data-link-title="IAM" data-link-desc="說明 identity and access management 如何集中管理身分、角色與權限">IAM</a>、<a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> 或任何具體服務時，都必須保留成本權衡段落。</p>
<p>這個段落要同時看五個方向：</p>
<ol>
<li><strong>資安限制</strong>：權限分級、資料遮罩、傳輸保護、密鑰管理、稽核與伺服器防護會增加哪些設計與操作要求。</li>
<li><strong>流量與穩定性</strong>：尖峰、hot key、長連線、大量資料、重試風暴或下游失敗會讓服務承擔哪些容量壓力。</li>
<li><strong>伺服器與雲端成本</strong>：儲存、運算、網路傳輸、保留期限、備援、跨區與觀測資料會如何增加成本。</li>
<li><strong>人力與操作成本</strong>：維護、升級、監控、備份、演練、<a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a>、文件與事故處理需要誰負責。</li>
<li><strong>機會成本</strong>：選擇完整平台會延後哪些產品工作；選擇簡單方案會留下哪些風險；哪些條件會讓團隊需要重新評估。</li>
</ol>
<h2 id="和語言教材的關係">和語言教材的關係</h2>
<p>語言教材負責教「如何隔離外部能力」。Backend 選型模組負責教「什麼能力值得被隔離」。例如 Go 章節會說明 repository port、publisher port、cache interface 與 observability boundary；本模組則說明何時需要資料庫、Redis、broker、OpenTelemetry 或部署平台能力。</p>
<h2 id="企業選型案例補充">企業選型案例補充</h2>
<p>模組零的案例補充重點是「企業如何說明選型取捨」。閱讀時先抓它在解什麼需求壓力，再對照本模組的需求分類與成本取捨章節。</p>
<table>
  <thead>
      <tr>
          <th>企業案例</th>
          <th>主要選型問題</th>
          <th>優先回讀章節</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="https://www.notion.com/blog/sharding-postgres-at-notion">Herding elephants: Lessons learned from sharding Postgres at Notion</a></td>
          <td>單體資料庫何時需要走向分片</td>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a>、<a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a></td>
      </tr>
      <tr>
          <td><a href="https://shopify.engineering/blogs/engineering/horizontally-scaling-the-rails-backend-of-shop-app-with-vitess">Horizontally scaling the Rails backend of Shop app with Vitess</a></td>
          <td>MySQL 生態下何時改走 Vitess</td>
          <td><a href="/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1</a>、<a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
      </tr>
      <tr>
          <td><a href="https://discord.com/blog/how-discord-stores-trillions-of-messages">How Discord Stores Trillions of Messages</a></td>
          <td>儲存引擎選型如何隨成長重評</td>
          <td><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a>、<a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a></td>
      </tr>
      <tr>
          <td><a href="https://www.uber.com/en-GB/blog/microservice-architecture/">Introducing Domain-Oriented Microservice Architecture</a></td>
          <td>微服務邊界與複雜度治理如何重新切分</td>
          <td><a href="/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0</a>、<a href="/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1</a></td>
      </tr>
      <tr>
          <td><a href="https://aws.amazon.com/builders-library/workload-isolation-using-shuffle-sharding/">Workload isolation using shuffle-sharding</a></td>
          <td>多租戶隔離與 blast radius 如何進選型決策</td>
          <td><a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a>、<a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a></td>
      </tr>
  </tbody>
</table>
<p>若要做「跨產業 × 跨規模」的系統化案例蒐集與回寫，直接使用 <a href="/blog/backend/00-service-selection/enterprise-selection-case-atlas/" data-link-title="0.14 企業選型案例圖譜" data-link-desc="蒐集不同類型與不同規模企業的技術選型案例，作為後端選型判讀的跨情境補充。">0.14 企業選型案例圖譜</a>；該章節提供分組後案例地圖與覆蓋缺口檢查表，可直接當後續補強 backlog。</p>
<h2 id="本模組不處理">本模組不處理</h2>
<p>本模組只處理需求分析與選型入口。具體 SQL schema、Redis command、RabbitMQ exchange、Prometheus query、Kubernetes deployment 或 <a href="/blog/backend/knowledge-cards/chaos-test/" data-link-title="Chaos Test" data-link-desc="說明透過受控故障注入驗證系統在異常條件下的恢復能力">chaos test</a> 設計，會放在後續對應模組中。</p>
<h2 id="實作探討入口">實作探討入口</h2>
<p>當你準備從概念層切到實作層，建議先選一條單一業務路徑做最小切片，並同時建立三個 artifact：</p>
<ol>
<li>觀測證據： <a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a></li>
<li>驗證證據： <a href="/blog/backend/06-reliability/verification-evidence-handoff/" data-link-title="6.23 Verification Evidence Handoff" data-link-desc="把 SLO、load、chaos、DR 與 readiness 結果包成 release / incident 可用證據">6.23 Verification Evidence Handoff</a></li>
<li>事故決策： <a href="/blog/backend/08-incident-response/incident-decision-log/" data-link-title="8.19 Incident Decision Log" data-link-desc="把事中假設、決策、證據、回退條件與責任人留下可復盤紀錄">8.19 Incident Decision Log</a></li>
</ol>
<p>這三個 artifact 先接起來，再補該路徑的 DB、cache、queue、deployment 細節，實作討論會更穩定，也更容易做跨模組回寫。</p>
<p>完整撰寫順序與服務路徑選擇依 <a href="/blog/backend/#%e5%ad%b8%e7%bf%92%e8%b7%af%e7%b7%9a" data-link-title="Backend 服務實務指南" data-link-desc="用跨語言教學路線整理資料庫、快取、訊息佇列、觀測、部署、可靠性、資安、事故與容量等後端服務能力">Backend 學習路線</a> 安排。</p>
<h2 id="大綱待辦">大綱待辦</h2>
<p>這一節只記錄仍需要沿著原子卡原則拆出的概念，之後補卡、拆卡或新增卡都先回到這裡確認。</p>
<h3 id="已完成拆分">已完成拆分</h3>
<ul>
<li><code>endpoint</code>：service endpoint / public API endpoint / admin endpoint / diagnostic endpoint / internal endpoint</li>
<li><code>gateway</code>：API gateway / request routing</li>
<li><code>contract</code>：boundary contract / API contract / deployment contract / queue contract / load balancer contract</li>
<li><code>protocol</code>：communication protocol / request-response protocol / message protocol / webhook protocol</li>
<li><code>adapter</code>：integration adapter / repository adapter / provider adapter / notification adapter</li>
<li><code>middleware</code>：request middleware / authentication middleware / authorization middleware / observability middleware / security middleware / validation middleware</li>
</ul>
<h3 id="需要保留為議題入口的章節">需要保留為議題入口的章節</h3>
<ul>
<li><a href="/blog/backend/00-service-selection/backend-demand-taxonomy/" data-link-title="0.0 後端需求分類地圖" data-link-desc="先從需求形狀辨識狀態、讀取、非同步、即時、診斷、交付與可靠性問題">0.0</a> 後端需求分類地圖</li>
<li><a href="/blog/backend/00-service-selection/service-capability-map/" data-link-title="0.1 後端服務能力地圖" data-link-desc="用需求類型判斷應先評估資料庫、快取、訊息佇列、觀測平台或部署平台">0.1</a> 後端服務能力地圖</li>
<li><a href="/blog/backend/00-service-selection/state-storage-selection/" data-link-title="0.2 狀態與資料儲存選型" data-link-desc="區分 source of truth、快取、搜尋索引、event log 與 object storage 的選型邊界">0.2</a> 狀態與資料儲存選型</li>
<li><a href="/blog/backend/00-service-selection/async-delivery-selection/" data-link-title="0.3 非同步與事件傳遞選型" data-link-desc="區分背景工作、durable queue、stream、pub/sub 與 outbox 的選型邊界">0.3</a> 非同步與事件傳遞選型</li>
<li><a href="/blog/backend/00-service-selection/operations-platform-selection/" data-link-title="0.4 操作平台選型" data-link-desc="區分 log、metric、trace、dashboard、alert、deployment 與 reliability 的選型邊界">0.4</a> 操作平台選型</li>
<li><a href="/blog/backend/00-service-selection/traffic-data-scale/" data-link-title="0.5 流量與資料量評估" data-link-desc="用流量形狀、資料成長、hot key、保留期限與尖峰模式評估後端需求規模">0.5</a> 流量與資料量評估</li>
<li><a href="/blog/backend/00-service-selection/cost-risk-tradeoffs/" data-link-title="0.6 成本、風險與選型取捨" data-link-desc="用人力成本、雲端成本、操作成本與失敗代價判斷後端能力投入順序">0.6</a> 成本、風險與選型取捨</li>
<li><a href="/blog/backend/00-service-selection/failure-observability-design/" data-link-title="0.7 錯誤定位、觀測訊號與備援切換設計" data-link-desc="從錯誤分類、定位線索、降級策略與 failover 設計服務可維護性">0.7</a> 錯誤定位、觀測訊號與備援切換設計</li>
<li><a href="/blog/backend/00-service-selection/security-data-protection-requirements/" data-link-title="0.8 資安與資料保護需求" data-link-desc="從權限分級、伺服器防護、資料遮罩、傳輸保護與稽核設計安全邊界">0.8</a> 資安與資料保護需求</li>
<li><a href="/blog/backend/00-service-selection/knowledge-graph-message-flow/" data-link-title="0.9 知識網：訊息與事件決策路徑" data-link-desc="把 broker、queue、ack、retry、DLQ、replay 與 idempotency 串成可操作的非同步決策語言">0.9</a> 知識網：訊息與事件決策路徑</li>
<li><a href="/blog/backend/00-service-selection/knowledge-graph-operations-security/" data-link-title="0.10 知識網：容量、觀測與資安決策路徑" data-link-desc="把容量、可觀測、備援、權限、憑證與稽核術語串成統一的服務治理語言">0.10</a> 知識網：容量、觀測與資安決策路徑</li>
<li><a href="/blog/backend/00-service-selection/red-team-cross-service-weaknesses/" data-link-title="0.11 攻擊者視角（紅隊）：跨服務弱點判讀總表" data-link-desc="用攻擊面、可觀察訊號與失敗代價，建立 backend 選型前的弱點盤點框架">0.11</a> 攻擊者視角（紅隊）：跨服務弱點判讀總表</li>
<li><a href="/blog/backend/00-service-selection/operations-control-service-selection/" data-link-title="0.12 觀測、可靠性與事故服務選型" data-link-desc="從訊號、驗證與響應三層能力判斷操作控制服務的選型順序">0.12</a> 觀測、可靠性與事故服務選型</li>
<li><a href="/blog/backend/00-service-selection/operations-control-vertical-slice/" data-link-title="0.13 操作控制 vertical slice 實作入口" data-link-desc="用一個服務串起觀測證據、可靠性驗證、事故決策與回寫閉環">0.13</a> 操作控制 vertical slice 實作入口</li>
<li><a href="/blog/backend/00-service-selection/enterprise-selection-case-atlas/" data-link-title="0.14 企業選型案例圖譜" data-link-desc="蒐集不同類型與不同規模企業的技術選型案例，作為後端選型判讀的跨情境補充。">0.14</a> 企業選型案例圖譜</li>
<li><a href="/blog/backend/00-service-selection/cloud-vendor-capability-mapping/" data-link-title="0.19 雲端服務對照地圖（AWS / GCP / Azure）" data-link-desc="把後端能力分類對照到 AWS / GCP / Azure 的具體服務名稱、保留跨雲遷移與選型差異的判讀重點">0.19</a> 雲端服務對照地圖（AWS / GCP / Azure）</li>
</ul>
]]></content:encoded></item></channel></rss>