<?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>Knowledge Cards on Tarragon</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/</link><description>Recent content in Knowledge Cards on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Thu, 23 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/backend/knowledge-cards/index.xml" rel="self" type="application/rss+xml"/><item><title>Broker</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/broker/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/broker/</guid><description>&lt;p>Broker 的核心概念是「位於 &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/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer&lt;/a> 之間的訊息中介」。Producer 把工作或事件交給 broker，broker 依照 &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/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/routing-rule/" data-link-title="Routing Rule" data-link-desc="說明訊息系統如何依規則把訊息送到不同處理路徑">routing rule&lt;/a> 或 stream position 保存與分派訊息，consumer 再從 broker 取得訊息並處理。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Broker 把「送出訊息」與「處理訊息」分開。這個分離讓 request 可以先完成，背景工作可以稍後處理，也讓多個服務用同一個事件來源協作。RabbitMQ、Kafka、NATS JetStream、Redis Streams 都可以扮演 broker，但它們對 routing、持久化、順序、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay&lt;/a> 與 consumer 協調的模型不同。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 broker 的訊號是工作已經超出單一 request 或單一 process 的生命週期。常見訊號包括寄信、轉檔、通知、同步外部系統、資料匯入、事件審計與跨服務廣播。這些工作需要排隊、&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>、削峰或讓多個 consumer 分工處理。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>電商付款完成後，訂單服務可以把 &lt;code>OrderPaid&lt;/code> 事件交給 broker。寄信服務處理通知，倉儲服務處理出貨，分析服務處理報表。這些 consumer 的速度、失敗與部署週期彼此不同，broker 讓事件先被保存，再由各 consumer 依自己的節奏處理。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Broker 導入後，系統要明確定義訊息格式、投遞保證、&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;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/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook&lt;/a>。設計焦點是把「訊息送出去」升級成「訊息可追蹤、可恢復、可控制地被處理」。&lt;/p></description><content:encoded><![CDATA[<p>Broker 的核心概念是「位於 <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> 之間的訊息中介」。Producer 把工作或事件交給 broker，broker 依照 <a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic</a>、<a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a>、<a href="/blog/backend/knowledge-cards/routing-rule/" data-link-title="Routing Rule" data-link-desc="說明訊息系統如何依規則把訊息送到不同處理路徑">routing rule</a> 或 stream position 保存與分派訊息，consumer 再從 broker 取得訊息並處理。</p>
<h2 id="概念位置">概念位置</h2>
<p>Broker 把「送出訊息」與「處理訊息」分開。這個分離讓 request 可以先完成，背景工作可以稍後處理，也讓多個服務用同一個事件來源協作。RabbitMQ、Kafka、NATS JetStream、Redis Streams 都可以扮演 broker，但它們對 routing、持久化、順序、<a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay</a> 與 consumer 協調的模型不同。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 broker 的訊號是工作已經超出單一 request 或單一 process 的生命週期。常見訊號包括寄信、轉檔、通知、同步外部系統、資料匯入、事件審計與跨服務廣播。這些工作需要排隊、<a href="/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">retry policy</a>、削峰或讓多個 consumer 分工處理。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>電商付款完成後，訂單服務可以把 <code>OrderPaid</code> 事件交給 broker。寄信服務處理通知，倉儲服務處理出貨，分析服務處理報表。這些 consumer 的速度、失敗與部署週期彼此不同，broker 讓事件先被保存，再由各 consumer 依自己的節奏處理。</p>
<h2 id="設計責任">設計責任</h2>
<p>Broker 導入後，系統要明確定義訊息格式、投遞保證、<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>、<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/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook</a>。設計焦點是把「訊息送出去」升級成「訊息可追蹤、可恢復、可控制地被處理」。</p>
]]></content:encoded></item><item><title>Consumer Lag</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-lag/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-lag/</guid><description>&lt;p>Consumer lag 的核心概念是「consumer 已處理位置落後於 broker 最新訊息位置的距離」。這個距離可以用訊息數量、offset 差距或預估處理時間表示，它反映事件進入系統的速度是否高於處理速度。 可先對照 &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;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Consumer lag 是訊息系統的容量與健康訊號。Lag 上升代表某個 consumer group 正在累積未處理工作；lag 下降代表處理速度追上進入速度。不同 broker 的名稱不同，例如 Kafka 常看 offset lag，Redis Streams 可看 pending 與未讀項目，RabbitMQ 常看 queue depth 與 unacked messages。 可先對照 &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;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要關注 consumer lag 的訊號是「工作延遲開始影響產品結果」。例如通知延遲、報表延遲、搜尋索引更新延遲、訂單狀態同步延遲。Lag 也常伴隨 CPU 飽和、下游 API 變慢、資料庫鎖競爭或 consumer 反覆重試。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>外送平台在尖峰時段大量產生訂單事件。若地圖更新 consumer 的 lag 持續上升，使用者看到的騎手位置會落後；若付款入帳 consumer 的 lag 上升，客服與帳務對帳會延後。兩者都叫 lag，但產品代價不同，因此告警門檻也應分開設計。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Consumer lag 要搭配 runbook 使用。Runbook 應說明 lag 上升時先看進入量、處理耗時、錯誤率、下游延遲、重試數與 instance 數量；再決定擴容、暫停低優先工作、修復 poison message 或調整下游保護。&lt;/p></description><content:encoded><![CDATA[<p>Consumer lag 的核心概念是「consumer 已處理位置落後於 broker 最新訊息位置的距離」。這個距離可以用訊息數量、offset 差距或預估處理時間表示，它反映事件進入系統的速度是否高於處理速度。 可先對照 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">Consumer</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Consumer lag 是訊息系統的容量與健康訊號。Lag 上升代表某個 consumer group 正在累積未處理工作；lag 下降代表處理速度追上進入速度。不同 broker 的名稱不同，例如 Kafka 常看 offset lag，Redis Streams 可看 pending 與未讀項目，RabbitMQ 常看 queue depth 與 unacked messages。 可先對照 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">Consumer</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要關注 consumer lag 的訊號是「工作延遲開始影響產品結果」。例如通知延遲、報表延遲、搜尋索引更新延遲、訂單狀態同步延遲。Lag 也常伴隨 CPU 飽和、下游 API 變慢、資料庫鎖競爭或 consumer 反覆重試。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>外送平台在尖峰時段大量產生訂單事件。若地圖更新 consumer 的 lag 持續上升，使用者看到的騎手位置會落後；若付款入帳 consumer 的 lag 上升，客服與帳務對帳會延後。兩者都叫 lag，但產品代價不同，因此告警門檻也應分開設計。</p>
<h2 id="設計責任">設計責任</h2>
<p>Consumer lag 要搭配 runbook 使用。Runbook 應說明 lag 上升時先看進入量、處理耗時、錯誤率、下游延遲、重試數與 instance 數量；再決定擴容、暫停低優先工作、修復 poison message 或調整下游保護。</p>
]]></content:encoded></item><item><title>Dead-Letter Queue</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/dead-letter-queue/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/dead-letter-queue/</guid><description>&lt;p>Dead-letter queue 的核心概念是「把超過處理條件的訊息移到隔離區」。訊息經過 &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/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&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> 會把它送進 dead-letter queue，讓主要 &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>Dead-letter queue 是可靠性與診斷工具。它讓系統把暫時性失敗與需要人工判斷的訊息分開：暫時性失敗可以重試，需要分析的訊息則進入隔離區，等待修復資料、修復程式或建立 &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;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 dead-letter queue 的訊號是某些訊息反覆阻塞處理流程。常見原因包括 payload schema 與 consumer 版本不同步、外部系統回傳永久錯誤、資料狀態已被取消、權限不足或訊息內容缺少必要欄位。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>訂單通知 consumer 連續處理某筆事件失敗。訊息留在主要 queue 反覆重試時，後續正常訂單可能延遲；訊息進入 dead-letter queue 後，on-call 可以查看失敗原因、修復資料或部署修正後再重放該批訊息。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Dead-letter queue 要搭配分類欄位與處理流程。訊息進入隔離區時，應保留錯誤類型、最後錯誤、重試次數、原始 &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/correlation-id/" data-link-title="Correlation ID" data-link-desc="說明跨事件或跨服務的關聯識別碼如何支援排障">correlation id&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;/p></description><content:encoded><![CDATA[<p>Dead-letter queue 的核心概念是「把超過處理條件的訊息移到隔離區」。訊息經過 <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/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> 或 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a> 會把它送進 dead-letter queue，讓主要 <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a> 保持可前進。</p>
<h2 id="概念位置">概念位置</h2>
<p>Dead-letter queue 是可靠性與診斷工具。它讓系統把暫時性失敗與需要人工判斷的訊息分開：暫時性失敗可以重試，需要分析的訊息則進入隔離區，等待修復資料、修復程式或建立 <a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 dead-letter queue 的訊號是某些訊息反覆阻塞處理流程。常見原因包括 payload schema 與 consumer 版本不同步、外部系統回傳永久錯誤、資料狀態已被取消、權限不足或訊息內容缺少必要欄位。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>訂單通知 consumer 連續處理某筆事件失敗。訊息留在主要 queue 反覆重試時，後續正常訂單可能延遲；訊息進入 dead-letter queue 後，on-call 可以查看失敗原因、修復資料或部署修正後再重放該批訊息。</p>
<h2 id="設計責任">設計責任</h2>
<p>Dead-letter queue 要搭配分類欄位與處理流程。訊息進入隔離區時，應保留錯誤類型、最後錯誤、重試次數、原始 <a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic</a>、<a href="/blog/backend/knowledge-cards/correlation-id/" data-link-title="Correlation ID" data-link-desc="說明跨事件或跨服務的關聯識別碼如何支援排障">correlation id</a> 與建立時間；<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 應定義誰能重放、重放前檢查什麼、如何控制副作用範圍。</p>
]]></content:encoded></item><item><title>Replay Runbook</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/replay-runbook/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/replay-runbook/</guid><description>&lt;p>Replay runbook 的核心概念是「把事件重放變成可控操作」。Replay 會讓歷史訊息再次進入處理流程，因此 &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;p>Replay 常用在修復資料、補送事件、重建投影、重新產生搜尋索引或處理 &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>。它是一種高權限操作，因為同一批事件再次執行可能觸發通知、扣款、出貨、積分或外部 API 呼叫。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 replay runbook 的訊號是「資料可以由事件重建，但重建會影響現有狀態」。例如報表漏算一段時間、搜尋索引落後、某版 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer&lt;/a> 寫錯衍生資料、dead-letter queue 累積一批已修復訊息。這些情境都需要重放，但每種重放的副作用不同。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>會員等級計算服務因部署錯誤漏掉一天事件。團隊可以從 event log 重放該日事件重建會員等級；runbook 需要指定時間範圍、只重建等級投影、暫停對外通知，並在重放後比對抽樣帳號與總量指標。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Replay runbook 應包含 dry run、資料備份、權限核准、&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/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a> 與停止條件。設計重點是讓重放成為可審核、可停止、可驗證的操作，而非臨時手動補資料。&lt;/p></description><content:encoded><![CDATA[<p>Replay runbook 的核心概念是「把事件重放變成可控操作」。Replay 會讓歷史訊息再次進入處理流程，因此 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 要定義重放範圍、順序、速率、驗證方式、回滾策略與負責人。</p>
<h2 id="概念位置">概念位置</h2>
<p>Replay 常用在修復資料、補送事件、重建投影、重新產生搜尋索引或處理 <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>。它是一種高權限操作，因為同一批事件再次執行可能觸發通知、扣款、出貨、積分或外部 API 呼叫。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 replay runbook 的訊號是「資料可以由事件重建，但重建會影響現有狀態」。例如報表漏算一段時間、搜尋索引落後、某版 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a> 寫錯衍生資料、dead-letter queue 累積一批已修復訊息。這些情境都需要重放，但每種重放的副作用不同。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>會員等級計算服務因部署錯誤漏掉一天事件。團隊可以從 event log 重放該日事件重建會員等級；runbook 需要指定時間範圍、只重建等級投影、暫停對外通知，並在重放後比對抽樣帳號與總量指標。</p>
<h2 id="設計責任">設計責任</h2>
<p>Replay runbook 應包含 dry run、資料備份、權限核准、<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/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> 與停止條件。設計重點是讓重放成為可審核、可停止、可驗證的操作，而非臨時手動補資料。</p>
]]></content:encoded></item><item><title>Duplicate Delivery</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/duplicate-delivery/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/duplicate-delivery/</guid><description>&lt;p>重複投遞的核心概念是「同一個工作或事件可能被 consumer 看見多次」。在 at-least-once delivery 模型中，broker 會優先保證訊息有機會被處理；當 ack 遺失、consumer crash、網路中斷或 timeout 發生時，同一則訊息可能再次投遞。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>重複投遞是可靠訊息系統的正常設計條件。它要求 consumer 把「收到訊息」與「造成外部結果」分開思考，並用 idempotency key、dedup store、唯一約束、狀態機或業務檢查讓多次處理得到同一個結果。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要處理重複投遞的訊號是訊息會造成金錢、庫存、通知、帳務、點數或外部 API 副作用。只更新可重建投影的事件，重複通常只增加成本；會寄信、扣款、出貨或新增記錄的事件，重複可能造成產品事故。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>付款成功事件被投遞兩次。若出貨 consumer 只看「收到付款事件」就建立出貨單，可能造成重複出貨；若 consumer 以付款交易 ID 建立唯一處理紀錄，第二次投遞會命中已處理狀態，結果保持穩定。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Consumer 設計要明確標出 idempotency 邊界。重要事件應有穩定事件 ID、業務鍵、處理紀錄與可觀測欄位；測試要包含同一訊息連續處理、處理中 crash 後重試、外部 API timeout 後重試等情境。&lt;/p></description><content:encoded><![CDATA[<p>重複投遞的核心概念是「同一個工作或事件可能被 consumer 看見多次」。在 at-least-once delivery 模型中，broker 會優先保證訊息有機會被處理；當 ack 遺失、consumer crash、網路中斷或 timeout 發生時，同一則訊息可能再次投遞。 可先對照 <a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">Durable Queue</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>重複投遞是可靠訊息系統的正常設計條件。它要求 consumer 把「收到訊息」與「造成外部結果」分開思考，並用 idempotency key、dedup store、唯一約束、狀態機或業務檢查讓多次處理得到同一個結果。 可先對照 <a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">Durable Queue</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要處理重複投遞的訊號是訊息會造成金錢、庫存、通知、帳務、點數或外部 API 副作用。只更新可重建投影的事件，重複通常只增加成本；會寄信、扣款、出貨或新增記錄的事件，重複可能造成產品事故。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>付款成功事件被投遞兩次。若出貨 consumer 只看「收到付款事件」就建立出貨單，可能造成重複出貨；若 consumer 以付款交易 ID 建立唯一處理紀錄，第二次投遞會命中已處理狀態，結果保持穩定。</p>
<h2 id="設計責任">設計責任</h2>
<p>Consumer 設計要明確標出 idempotency 邊界。重要事件應有穩定事件 ID、業務鍵、處理紀錄與可觀測欄位；測試要包含同一訊息連續處理、處理中 crash 後重試、外部 API timeout 後重試等情境。</p>
]]></content:encoded></item><item><title>Cache Invalidation</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-invalidation/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-invalidation/</guid><description>&lt;p>快取失效策略的核心概念是「定義快取資料何時離開可用狀態」。快取可以加速讀取與降低下游壓力，但資料來源更新後，快取需要透過 TTL、主動刪除、版本鍵、write-through、event invalidation 或重建流程維持合理一致性。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-prefetching/" data-link-title="Cache Prefetching" data-link-desc="說明系統如何在資料被需要前預先載入快取">Cache Prefetching&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>快取失效是讀取效能與資料正確性的交界。失效太頻繁會降低快取命中率；失效太慢會讓使用者看到過期資料。多層快取還會增加判斷難度，因為 browser、CDN、application cache、Redis 與 local memory 可能各自保存不同版本。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-prefetching/" data-link-title="Cache Prefetching" data-link-desc="說明系統如何在資料被需要前預先載入快取">Cache Prefetching&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要整理失效策略的訊號是資料更新後，讀取結果在不同頁面、不同使用者或不同服務之間出現差異。常見場景包括商品價格、庫存、會員權限、設定檔、排行榜、熱門文章與 feature flag。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>電商後台更新商品價格後，搜尋頁仍顯示舊價格，商品頁顯示新價格，結帳頁又重新查資料庫。這代表不同讀取路徑使用不同快取層，失效策略需要定義更新事件要清哪些 key、哪些頁面可接受短暫延遲、結帳是否必須讀正式來源。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>快取設計要把資料語意分級。價格、庫存、權限這類影響交易或安全的資料需要更短 TTL、版本控制或讀正式來源；排行榜、推薦與統計可以接受較長延遲。Runbook 應提供查 key、清 key、比對正式資料與追蹤失效事件的方法。&lt;/p></description><content:encoded><![CDATA[<p>快取失效策略的核心概念是「定義快取資料何時離開可用狀態」。快取可以加速讀取與降低下游壓力，但資料來源更新後，快取需要透過 TTL、主動刪除、版本鍵、write-through、event invalidation 或重建流程維持合理一致性。 可先對照 <a href="/blog/backend/knowledge-cards/cache-prefetching/" data-link-title="Cache Prefetching" data-link-desc="說明系統如何在資料被需要前預先載入快取">Cache Prefetching</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>快取失效是讀取效能與資料正確性的交界。失效太頻繁會降低快取命中率；失效太慢會讓使用者看到過期資料。多層快取還會增加判斷難度，因為 browser、CDN、application cache、Redis 與 local memory 可能各自保存不同版本。 可先對照 <a href="/blog/backend/knowledge-cards/cache-prefetching/" data-link-title="Cache Prefetching" data-link-desc="說明系統如何在資料被需要前預先載入快取">Cache Prefetching</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要整理失效策略的訊號是資料更新後，讀取結果在不同頁面、不同使用者或不同服務之間出現差異。常見場景包括商品價格、庫存、會員權限、設定檔、排行榜、熱門文章與 feature flag。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>電商後台更新商品價格後，搜尋頁仍顯示舊價格，商品頁顯示新價格，結帳頁又重新查資料庫。這代表不同讀取路徑使用不同快取層，失效策略需要定義更新事件要清哪些 key、哪些頁面可接受短暫延遲、結帳是否必須讀正式來源。</p>
<h2 id="設計責任">設計責任</h2>
<p>快取設計要把資料語意分級。價格、庫存、權限這類影響交易或安全的資料需要更短 TTL、版本控制或讀正式來源；排行榜、推薦與統計可以接受較長延遲。Runbook 應提供查 key、清 key、比對正式資料與追蹤失效事件的方法。</p>
]]></content:encoded></item><item><title>Data Inconsistency</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/data-inconsistency/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/data-inconsistency/</guid><description>&lt;p>資料不一致的核心概念是「同一個業務事實在不同儲存位置呈現不同狀態」。資料庫、快取、搜尋索引、read model、報表、第三方系統與前端本地狀態都可能保存同一個事實的副本，因此更新傳播需要時間與規則。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-lifecycle/" data-link-title="Data Lifecycle" data-link-desc="說明資料從建立、使用、保留到刪除的責任邊界">Data Lifecycle&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>資料不一致需要先分辨 source of truth 與衍生資料。Source of truth 承擔正式判斷，例如訂單付款狀態；衍生資料負責查詢、展示或分析，例如搜尋索引與報表。設計時要明確哪些資料可以重建，哪些資料代表正式狀態。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-lifecycle/" data-link-title="Data Lifecycle" data-link-desc="說明資料從建立、使用、保留到刪除的責任邊界">Data Lifecycle&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要處理資料不一致的訊號是不同入口看到不同結果。使用者頁面、客服後台、管理報表、搜尋頁、通知訊息與第三方系統若對同一筆資料有不同說法，團隊就需要追蹤資料從正式來源到各副本的傳播路徑。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>使用者取消訂單後，訂單詳情顯示已取消，但搜尋列表仍顯示可出貨。若出貨流程讀搜尋索引，可能產生錯誤操作；若出貨流程讀正式訂單資料，搜尋列表延遲只影響展示。這個差異決定修復優先級。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>資料不一致的 runbook 要能回答四件事：正式來源在哪裡、哪些副本落後、更新事件是否送達、是否需要補償或重建。系統也要提供版本、更新時間、correlation id 或事件 ID，讓排查能沿著資料流定位。&lt;/p></description><content:encoded><![CDATA[<p>資料不一致的核心概念是「同一個業務事實在不同儲存位置呈現不同狀態」。資料庫、快取、搜尋索引、read model、報表、第三方系統與前端本地狀態都可能保存同一個事實的副本，因此更新傳播需要時間與規則。 可先對照 <a href="/blog/backend/knowledge-cards/data-lifecycle/" data-link-title="Data Lifecycle" data-link-desc="說明資料從建立、使用、保留到刪除的責任邊界">Data Lifecycle</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>資料不一致需要先分辨 source of truth 與衍生資料。Source of truth 承擔正式判斷，例如訂單付款狀態；衍生資料負責查詢、展示或分析，例如搜尋索引與報表。設計時要明確哪些資料可以重建，哪些資料代表正式狀態。 可先對照 <a href="/blog/backend/knowledge-cards/data-lifecycle/" data-link-title="Data Lifecycle" data-link-desc="說明資料從建立、使用、保留到刪除的責任邊界">Data Lifecycle</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要處理資料不一致的訊號是不同入口看到不同結果。使用者頁面、客服後台、管理報表、搜尋頁、通知訊息與第三方系統若對同一筆資料有不同說法，團隊就需要追蹤資料從正式來源到各副本的傳播路徑。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>使用者取消訂單後，訂單詳情顯示已取消，但搜尋列表仍顯示可出貨。若出貨流程讀搜尋索引，可能產生錯誤操作；若出貨流程讀正式訂單資料，搜尋列表延遲只影響展示。這個差異決定修復優先級。</p>
<h2 id="設計責任">設計責任</h2>
<p>資料不一致的 runbook 要能回答四件事：正式來源在哪裡、哪些副本落後、更新事件是否送達、是否需要補償或重建。系統也要提供版本、更新時間、correlation id 或事件 ID，讓排查能沿著資料流定位。</p>
]]></content:encoded></item><item><title>Degradation</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/degradation/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/degradation/</guid><description>&lt;p>降級的核心概念是「在部分依賴失效或容量不足時，保留最重要的產品能力」。降級設計會預先定義哪些功能可以暫停、改用簡化結果、延後處理或只提供只讀能力，讓系統在壓力下維持可控狀態。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>降級是可靠性設計的一部分。它和 failover、rate limit、circuit breaker、feature flag、cache fallback、read-only mode 相關，但重點是產品取捨：哪些功能必須保留，哪些功能可以暫時縮小。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要降級設計的訊號是下游失敗會拖垮核心流程。常見場景包括推薦系統逾時、報表服務過慢、第三方通知失敗、搜尋服務不穩、尖峰流量超過容量。這些場景應先保護登入、瀏覽、下單、付款或資料保存等核心路徑。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>活動期間推薦服務延遲升高。商品頁可以先顯示熱門商品或空推薦，讓使用者仍能瀏覽與下單；若商品頁等待推薦結果才回應，推薦服務的延遲會擴散成整站變慢。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>降級策略要有觸發條件、使用者體驗、資料一致性影響、告警與恢復條件。它也需要演練，因為未演練的降級常在事故中暴露缺少設定、權限、dashboard 或回復流程。&lt;/p></description><content:encoded><![CDATA[<p>降級的核心概念是「在部分依賴失效或容量不足時，保留最重要的產品能力」。降級設計會預先定義哪些功能可以暫停、改用簡化結果、延後處理或只提供只讀能力，讓系統在壓力下維持可控狀態。 可先對照 <a href="/blog/backend/knowledge-cards/delivery-mode/" data-link-title="Delivery Mode" data-link-desc="說明訊息投遞模式如何影響可靠性、延遲與成本">Delivery Mode</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>降級是可靠性設計的一部分。它和 failover、rate limit、circuit breaker、feature flag、cache fallback、read-only mode 相關，但重點是產品取捨：哪些功能必須保留，哪些功能可以暫時縮小。 可先對照 <a href="/blog/backend/knowledge-cards/delivery-mode/" data-link-title="Delivery Mode" data-link-desc="說明訊息投遞模式如何影響可靠性、延遲與成本">Delivery Mode</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要降級設計的訊號是下游失敗會拖垮核心流程。常見場景包括推薦系統逾時、報表服務過慢、第三方通知失敗、搜尋服務不穩、尖峰流量超過容量。這些場景應先保護登入、瀏覽、下單、付款或資料保存等核心路徑。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>活動期間推薦服務延遲升高。商品頁可以先顯示熱門商品或空推薦，讓使用者仍能瀏覽與下單；若商品頁等待推薦結果才回應，推薦服務的延遲會擴散成整站變慢。</p>
<h2 id="設計責任">設計責任</h2>
<p>降級策略要有觸發條件、使用者體驗、資料一致性影響、告警與恢復條件。它也需要演練，因為未演練的降級常在事故中暴露缺少設定、權限、dashboard 或回復流程。</p>
]]></content:encoded></item><item><title>Downtime</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/downtime/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/downtime/</guid><description>&lt;p>停機的核心概念是「服務承諾能力在一段時間內中斷」。停機可能來自部署、基礎設施故障、資料庫服務中斷、憑證失效、外部依賴中斷、資安事件或人為操作失誤。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>停機討論要回到產品承諾。不同服務的中斷代價不同：登入停機會阻止使用者進入系統，付款停機會直接影響收入，報表停機可能延後內部決策，通知停機可能造成延遲但可補送。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要停機應變設計的訊號是服務有明確 SLO、收入影響、法規要求、資料保存責任或大量使用者依賴。停機風險也會在部署頻繁、單點依賴、缺少備份、缺少演練或缺少 rollback 時上升。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>票券平台開賣時付款服務停機。系統需要先保護訂單狀態與付款一致性，再決定是否暫停結帳、排隊等候、延長付款期限或開啟公告。若只追求快速恢復流量，可能讓使用者重複付款或訂單狀態混亂。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>停機 runbook 要定義事件分級、對外溝通、負責人、rollback、備援切換、資料保護與事後復盤。關鍵系統還要預先定義 RTO、RPO、備份驗證、演練頻率與決策權限。&lt;/p></description><content:encoded><![CDATA[<p>停機的核心概念是「服務承諾能力在一段時間內中斷」。停機可能來自部署、基礎設施故障、資料庫服務中斷、憑證失效、外部依賴中斷、資安事件或人為操作失誤。 可先對照 <a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>停機討論要回到產品承諾。不同服務的中斷代價不同：登入停機會阻止使用者進入系統，付款停機會直接影響收入，報表停機可能延後內部決策，通知停機可能造成延遲但可補送。 可先對照 <a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要停機應變設計的訊號是服務有明確 SLO、收入影響、法規要求、資料保存責任或大量使用者依賴。停機風險也會在部署頻繁、單點依賴、缺少備份、缺少演練或缺少 rollback 時上升。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>票券平台開賣時付款服務停機。系統需要先保護訂單狀態與付款一致性，再決定是否暫停結帳、排隊等候、延長付款期限或開啟公告。若只追求快速恢復流量，可能讓使用者重複付款或訂單狀態混亂。</p>
<h2 id="設計責任">設計責任</h2>
<p>停機 runbook 要定義事件分級、對外溝通、負責人、rollback、備援切換、資料保護與事後復盤。關鍵系統還要預先定義 RTO、RPO、備份驗證、演練頻率與決策權限。</p>
]]></content:encoded></item><item><title>Readiness</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/readiness/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/readiness/</guid><description>&lt;p>Readiness 的核心概念是「instance 是否已準備好接收正式流量」。部署平台或 load balancer 會根據 readiness 訊號決定是否把 request 導到該 instance。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/redelivery-loop/" data-link-title="Redelivery Loop" data-link-desc="說明同一訊息反覆投遞失敗如何消耗 consumer 容量">Redelivery Loop&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Readiness 是 application 與平台之間的流量合約。Application 啟動成功只代表 process 存活；readiness 代表必要設定、連線、migration 狀態、背景初始化、cache warmup 或依賴檢查已達到接流量條件。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/redelivery-loop/" data-link-title="Redelivery Loop" data-link-desc="說明同一訊息反覆投遞失敗如何消耗 consumer 容量">Redelivery Loop&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 readiness 合約的訊號是部署或擴容期間出現短暫錯誤。常見情境包括 pod 剛啟動就接流量、service discovery 尚未更新、cache 還在 warming、資料庫連線池尚未建立、背景 worker 尚未完成初始化。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>Kubernetes rolling update 建立新 pod 後，若 readiness 太早通過，新 pod 可能在還沒載入設定時接到 checkout request。正確的 readiness 會等必要依賴可用、設定載入完成、核心路由可處理後再開放流量。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Readiness endpoint 要反映接流量所需的最小條件，並且控制下游短暫波動對流量調度的影響。設計時要分清 readiness、liveness 與深度依賴檢查，讓平台能做穩定調度。&lt;/p></description><content:encoded><![CDATA[<p>Readiness 的核心概念是「instance 是否已準備好接收正式流量」。部署平台或 load balancer 會根據 readiness 訊號決定是否把 request 導到該 instance。 可先對照 <a href="/blog/backend/knowledge-cards/redelivery-loop/" data-link-title="Redelivery Loop" data-link-desc="說明同一訊息反覆投遞失敗如何消耗 consumer 容量">Redelivery Loop</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Readiness 是 application 與平台之間的流量合約。Application 啟動成功只代表 process 存活；readiness 代表必要設定、連線、migration 狀態、背景初始化、cache warmup 或依賴檢查已達到接流量條件。 可先對照 <a href="/blog/backend/knowledge-cards/redelivery-loop/" data-link-title="Redelivery Loop" data-link-desc="說明同一訊息反覆投遞失敗如何消耗 consumer 容量">Redelivery Loop</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 readiness 合約的訊號是部署或擴容期間出現短暫錯誤。常見情境包括 pod 剛啟動就接流量、service discovery 尚未更新、cache 還在 warming、資料庫連線池尚未建立、背景 worker 尚未完成初始化。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>Kubernetes rolling update 建立新 pod 後，若 readiness 太早通過，新 pod 可能在還沒載入設定時接到 checkout request。正確的 readiness 會等必要依賴可用、設定載入完成、核心路由可處理後再開放流量。</p>
<h2 id="設計責任">設計責任</h2>
<p>Readiness endpoint 要反映接流量所需的最小條件，並且控制下游短暫波動對流量調度的影響。設計時要分清 readiness、liveness 與深度依賴檢查，讓平台能做穩定調度。</p>
]]></content:encoded></item><item><title>Graceful Shutdown</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/graceful-shutdown/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/graceful-shutdown/</guid><description>&lt;p>Graceful shutdown 的核心概念是「instance 收到停止訊號後，以可控流程結束服務」。它會先停止接收新工作，再讓正在處理的 request、長連線、consumer 或背景任務在期限內完成、保存狀態或交回 broker。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Graceful shutdown 是 application 與部署平台的停止合約。平台負責送出停止訊號、移出流量與設定期限；application 負責停止入口、排空處理中工作、釋放連線、提交 checkpoint、送出最後 log 與 metrics。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 graceful shutdown 的訊號是部署、擴容縮容或主機維護時出現 request 中斷、訊息重複、長連線突斷、資料寫入半途失敗或 worker 遺失進度。這些現象表示停止流程與工作生命週期沒有對齊。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>背景 worker 正在處理影片轉檔時收到部署停止訊號。Graceful shutdown 應停止取得新工作，讓目前轉檔在期限內完成；若超過期限，worker 需要保存進度或讓 broker 重新投遞，並留下可追蹤的狀態。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Graceful shutdown 要搭配 timeout、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">idle timeout&lt;/a>、idempotency 與觀測訊號。Runbook 應能看到停止期間的 in-flight request、consumer ack、長連線數、錯誤率與強制終止次數，讓部署問題可以被定位。&lt;/p></description><content:encoded><![CDATA[<p>Graceful shutdown 的核心概念是「instance 收到停止訊號後，以可控流程結束服務」。它會先停止接收新工作，再讓正在處理的 request、長連線、consumer 或背景任務在期限內完成、保存狀態或交回 broker。 可先對照 <a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Graceful shutdown 是 application 與部署平台的停止合約。平台負責送出停止訊號、移出流量與設定期限；application 負責停止入口、排空處理中工作、釋放連線、提交 checkpoint、送出最後 log 與 metrics。 可先對照 <a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 graceful shutdown 的訊號是部署、擴容縮容或主機維護時出現 request 中斷、訊息重複、長連線突斷、資料寫入半途失敗或 worker 遺失進度。這些現象表示停止流程與工作生命週期沒有對齊。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>背景 worker 正在處理影片轉檔時收到部署停止訊號。Graceful shutdown 應停止取得新工作，讓目前轉檔在期限內完成；若超過期限，worker 需要保存進度或讓 broker 重新投遞，並留下可追蹤的狀態。</p>
<h2 id="設計責任">設計責任</h2>
<p>Graceful shutdown 要搭配 timeout、<a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining</a>、<a href="/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">idle timeout</a>、idempotency 與觀測訊號。Runbook 應能看到停止期間的 in-flight request、consumer ack、長連線數、錯誤率與強制終止次數，讓部署問題可以被定位。</p>
]]></content:encoded></item><item><title>Source of Truth</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/</guid><description>&lt;p>Source of truth 的核心概念是「某個業務事實的正式判斷來源」。同一筆資料可能出現在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a>、快取、搜尋索引、報表、第三方系統與前端畫面，但只有一個位置應承擔正式狀態判斷。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Source of truth 讓系統知道衝突時該相信誰。訂單狀態通常以訂單 database 為準，搜尋索引只是查詢副本；會員權限通常以權限服務或 database 為準，快取只是加速讀取。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要明確 source of truth 的訊號是不同入口呈現不同結果。客服後台顯示訂單已取消，搜尋頁仍顯示可出貨時，團隊要先知道出貨流程應讀正式訂單資料，而非搜尋索引。&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></description><content:encoded><![CDATA[<p>Source of truth 的核心概念是「某個業務事實的正式判斷來源」。同一筆資料可能出現在 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a>、快取、搜尋索引、報表、第三方系統與前端畫面，但只有一個位置應承擔正式狀態判斷。</p>
<h2 id="概念位置">概念位置</h2>
<p>Source of truth 讓系統知道衝突時該相信誰。訂單狀態通常以訂單 database 為準，搜尋索引只是查詢副本；會員權限通常以權限服務或 database 為準，快取只是加速讀取。 可先對照 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要明確 source of truth 的訊號是不同入口呈現不同結果。客服後台顯示訂單已取消，搜尋頁仍顯示可出貨時，團隊要先知道出貨流程應讀正式訂單資料，而非搜尋索引。</p>
<h2 id="設計責任">設計責任</h2>
<p>資料設計要標出正式來源、衍生副本、重建方式與修復順序。<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">Runbook</a> 應說明資料衝突時如何查正式來源、如何重建副本、如何確認修復完成。</p>
]]></content:encoded></item><item><title>Data Lifecycle</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/data-lifecycle/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/data-lifecycle/</guid><description>&lt;p>資料生命週期的核心概念是「資料從建立到移除之間的責任安排」。後端系統要知道資料何時建立、誰能修改、保存多久、何時封存、何時刪除，以及刪除後哪些副本也要同步處理。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>資料生命週期連接產品需求、成本與資安。訂單資料可能需要長期保存以支援稽核；debug log 可能只保留數天；匯出檔案可能需要短期下載期限與自動清除。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要資料生命週期設計的訊號是資料量持續成長、使用者要求刪除資料、稽核要求保存證據，或觀測資料成本快速上升。聊天訊息、付款紀錄、trace、報表檔案的保留策略通常不同。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>生命週期設計要定義保留期限、刪除流程、封存策略、備份影響、權限與 audit。資料移除時也要處理 cache、search index、object storage、log 與第三方系統副本。&lt;/p></description><content:encoded><![CDATA[<p>資料生命週期的核心概念是「資料從建立到移除之間的責任安排」。後端系統要知道資料何時建立、誰能修改、保存多久、何時封存、何時刪除，以及刪除後哪些副本也要同步處理。 可先對照 <a href="/blog/backend/knowledge-cards/data-masking/" data-link-title="Data Masking" data-link-desc="說明敏感資料如何在顯示、匯出、log 與測試資料中降低暴露">Data Masking</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>資料生命週期連接產品需求、成本與資安。訂單資料可能需要長期保存以支援稽核；debug log 可能只保留數天；匯出檔案可能需要短期下載期限與自動清除。 可先對照 <a href="/blog/backend/knowledge-cards/data-masking/" data-link-title="Data Masking" data-link-desc="說明敏感資料如何在顯示、匯出、log 與測試資料中降低暴露">Data Masking</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要資料生命週期設計的訊號是資料量持續成長、使用者要求刪除資料、稽核要求保存證據，或觀測資料成本快速上升。聊天訊息、付款紀錄、trace、報表檔案的保留策略通常不同。</p>
<h2 id="設計責任">設計責任</h2>
<p>生命週期設計要定義保留期限、刪除流程、封存策略、備份影響、權限與 audit。資料移除時也要處理 cache、search index、object storage、log 與第三方系統副本。</p>
]]></content:encoded></item><item><title>Transaction Boundary</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/transaction-boundary/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/transaction-boundary/</guid><description>&lt;p>Transaction boundary 的核心概念是「一組資料變更必須一起成功或一起回復的範圍」。交易邊界決定哪些狀態需要被 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a> &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="概念位置">概念位置&lt;/h2>
&lt;p>交易適合保護同一個 database 內的正式狀態變更。建立訂單與扣庫存可能需要同一個交易；寄信、呼叫外部 API 或發布 &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/outbox-pattern/" data-link-title="Outbox Pattern" data-link-desc="說明資料庫狀態變更與事件發布如何透過 outbox 維持一致">outbox pattern&lt;/a> 或補償流程，因為它們超出 database transaction 能力。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要交易邊界的訊號是「半成功」會造成產品錯誤。若付款紀錄已建立但訂單狀態未更新，客服與帳務會看到衝突狀態；若通知寄送失敗，通常可以重試或補送。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>交易邊界要盡量短，並明確處理 deadlock、&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/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout&lt;/a> 與錯誤分類。跨 database 或跨服務的一致性要改用 outbox、saga、補償或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">data reconciliation&lt;/a>，而非假設單一交易能包住所有事情。&lt;/p></description><content:encoded><![CDATA[<p>Transaction boundary 的核心概念是「一組資料變更必須一起成功或一起回復的範圍」。交易邊界決定哪些狀態需要被 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a> <a href="/blog/backend/knowledge-cards/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">transaction</a> 保護，哪些外部動作應放在交易之外。</p>
<h2 id="概念位置">概念位置</h2>
<p>交易適合保護同一個 database 內的正式狀態變更。建立訂單與扣庫存可能需要同一個交易；寄信、呼叫外部 API 或發布 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> 訊息則常需要 <a href="/blog/backend/knowledge-cards/outbox-pattern/" data-link-title="Outbox Pattern" data-link-desc="說明資料庫狀態變更與事件發布如何透過 outbox 維持一致">outbox pattern</a> 或補償流程，因為它們超出 database transaction 能力。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要交易邊界的訊號是「半成功」會造成產品錯誤。若付款紀錄已建立但訂單狀態未更新，客服與帳務會看到衝突狀態；若通知寄送失敗，通常可以重試或補送。</p>
<h2 id="設計責任">設計責任</h2>
<p>交易邊界要盡量短，並明確處理 deadlock、<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/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout</a> 與錯誤分類。跨 database 或跨服務的一致性要改用 outbox、saga、補償或 <a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">data reconciliation</a>，而非假設單一交易能包住所有事情。</p>
]]></content:encoded></item><item><title>Schema Migration</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/</guid><description>&lt;p>Schema migration 的核心概念是「用版本化流程修改 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a> 結構」。資料表、欄位、索引、constraint 與資料修補都會影響 application，因此 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration&lt;/a> 要和部署、回滾、資料量與相容性一起設計。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Migration 是 database 與 release 流程的交界。小型服務可能只需要簡單版本檔；正式服務通常需要 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract&lt;/a> 策略，先新增可相容欄位，再部署 application，最後移除舊欄位。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 migration 策略的訊號是多個版本會同時存在。Rolling update 期間，新舊 application 可能同時讀寫資料庫；若 migration 一次移除舊欄位，舊版本 instance 可能立刻失敗。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Migration 設計要包含相容性、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">backfill&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>。高風險 migration 應先在接近正式資料量的環境驗證。&lt;/p></description><content:encoded><![CDATA[<p>Schema migration 的核心概念是「用版本化流程修改 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a> 結構」。資料表、欄位、索引、constraint 與資料修補都會影響 application，因此 <a href="/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration</a> 要和部署、回滾、資料量與相容性一起設計。</p>
<h2 id="概念位置">概念位置</h2>
<p>Migration 是 database 與 release 流程的交界。小型服務可能只需要簡單版本檔；正式服務通常需要 <a href="/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract</a> 策略，先新增可相容欄位，再部署 application，最後移除舊欄位。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 migration 策略的訊號是多個版本會同時存在。Rolling update 期間，新舊 application 可能同時讀寫資料庫；若 migration 一次移除舊欄位，舊版本 instance 可能立刻失敗。</p>
<h2 id="設計責任">設計責任</h2>
<p>Migration 設計要包含相容性、<a href="/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">backfill</a>、索引建立成本、鎖表風險、回滾策略與 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a>。高風險 migration 應先在接近正式資料量的環境驗證。</p>
]]></content:encoded></item><item><title>Isolation Level</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/isolation-level/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/isolation-level/</guid><description>&lt;p>Isolation level 的核心概念是「交易彼此看見資料變更的規則」。隔離級別越高，越能降低並發異常；同時也可能增加鎖競爭、等待與重試成本。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/jitter/" data-link-title="Jitter" data-link-desc="說明重試或排程加入隨機偏移如何降低同步尖峰">Jitter&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>隔離級別處理的是同一份資料被多個交易同時讀寫時的行為。常見問題包括 dirty read、non-repeatable read、phantom read、lost update 與 write skew。不同資料庫的預設隔離與實作細節不同。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/jitter/" data-link-title="Jitter" data-link-desc="說明重試或排程加入隨機偏移如何降低同步尖峰">Jitter&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要討論隔離級別的訊號是高併發更新同一類資料。兩個使用者同時搶最後一件庫存、兩個 worker 同時認領同一筆工作、兩個後台操作同時修改權限，都需要明確的一致性策略。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要先定義可接受的並發結果，再選擇 transaction、lock、unique constraint、optimistic concurrency 或 retry。隔離級別是工具之一，業務層仍需要狀態機與唯一約束表達正式規則。&lt;/p></description><content:encoded><![CDATA[<p>Isolation level 的核心概念是「交易彼此看見資料變更的規則」。隔離級別越高，越能降低並發異常；同時也可能增加鎖競爭、等待與重試成本。 可先對照 <a href="/blog/backend/knowledge-cards/jitter/" data-link-title="Jitter" data-link-desc="說明重試或排程加入隨機偏移如何降低同步尖峰">Jitter</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>隔離級別處理的是同一份資料被多個交易同時讀寫時的行為。常見問題包括 dirty read、non-repeatable read、phantom read、lost update 與 write skew。不同資料庫的預設隔離與實作細節不同。 可先對照 <a href="/blog/backend/knowledge-cards/jitter/" data-link-title="Jitter" data-link-desc="說明重試或排程加入隨機偏移如何降低同步尖峰">Jitter</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要討論隔離級別的訊號是高併發更新同一類資料。兩個使用者同時搶最後一件庫存、兩個 worker 同時認領同一筆工作、兩個後台操作同時修改權限，都需要明確的一致性策略。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要先定義可接受的並發結果，再選擇 transaction、lock、unique constraint、optimistic concurrency 或 retry。隔離級別是工具之一，業務層仍需要狀態機與唯一約束表達正式規則。</p>
]]></content:encoded></item><item><title>Connection Pool</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/</guid><description>&lt;p>Connection pool 的核心概念是「重用並限制到下游服務的連線」。資料庫、Redis、broker 與 HTTP client 都可能使用連線池；連線池決定同時有多少工作能進入下游。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-capacity/" data-link-title="Consumer Capacity" data-link-desc="說明 consumer 群組每秒能穩定處理多少工作">Consumer Capacity&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>連線池是 application 並發與下游容量的閘門。Pool 太小會讓 request 等待；pool 太大會把壓力轉移到資料庫或外部服務，造成 timeout、排隊與資源耗盡。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-capacity/" data-link-title="Consumer Capacity" data-link-desc="說明 consumer 群組每秒能穩定處理多少工作">Consumer Capacity&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要檢查 connection pool 的訊號是 latency 升高但 CPU 不高，或高峰時大量 request 等待資料庫。活動期間 checkout 變慢，可能是 database pool 已滿，也可能是資料庫本身查詢變慢。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Pool 設定要搭配 timeout、查詢耗時、instance 數量與下游最大連線數。Runbook 應能看到 pool in-use、idle、wait count、timeout 與下游 error rate。&lt;/p></description><content:encoded><![CDATA[<p>Connection pool 的核心概念是「重用並限制到下游服務的連線」。資料庫、Redis、broker 與 HTTP client 都可能使用連線池；連線池決定同時有多少工作能進入下游。 可先對照 <a href="/blog/backend/knowledge-cards/consumer-capacity/" data-link-title="Consumer Capacity" data-link-desc="說明 consumer 群組每秒能穩定處理多少工作">Consumer Capacity</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>連線池是 application 並發與下游容量的閘門。Pool 太小會讓 request 等待；pool 太大會把壓力轉移到資料庫或外部服務，造成 timeout、排隊與資源耗盡。 可先對照 <a href="/blog/backend/knowledge-cards/consumer-capacity/" data-link-title="Consumer Capacity" data-link-desc="說明 consumer 群組每秒能穩定處理多少工作">Consumer Capacity</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要檢查 connection pool 的訊號是 latency 升高但 CPU 不高，或高峰時大量 request 等待資料庫。活動期間 checkout 變慢，可能是 database pool 已滿，也可能是資料庫本身查詢變慢。</p>
<h2 id="設計責任">設計責任</h2>
<p>Pool 設定要搭配 timeout、查詢耗時、instance 數量與下游最大連線數。Runbook 應能看到 pool in-use、idle、wait count、timeout 與下游 error rate。</p>
]]></content:encoded></item><item><title>TTL</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/ttl/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/ttl/</guid><description>&lt;p>TTL 的核心概念是「資料在指定時間後自動過期」。TTL 常用在 cache、session、presence、temporary token、匯出檔案與去重紀錄，讓系統用時間控制資料有效性。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/unacked-message/" data-link-title="Unacked Message" data-link-desc="說明 broker 已投遞但尚未收到 consumer 確認的訊息">Unacked Message&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>TTL 是資料新鮮度與操作成本的取捨。TTL 長可以提高命中率與降低下游壓力；TTL 短可以降低過期資料風險，但會增加重新載入與下游查詢。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/unacked-message/" data-link-title="Unacked Message" data-link-desc="說明 broker 已投遞但尚未收到 consumer 確認的訊息">Unacked Message&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要調整 TTL 的訊號是資料過期造成錯誤體驗，或 cache miss 造成下游壓力。商品價格 cache 的 TTL 通常短於熱門文章榜；presence 狀態需要跟心跳頻率一起設計。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>TTL 要依資料語意分級，並搭配主動失效、版本鍵或背景刷新。Runbook 應能查 key 剩餘時間、命中率、miss rate 與過期後重建成本。&lt;/p></description><content:encoded><![CDATA[<p>TTL 的核心概念是「資料在指定時間後自動過期」。TTL 常用在 cache、session、presence、temporary token、匯出檔案與去重紀錄，讓系統用時間控制資料有效性。 可先對照 <a href="/blog/backend/knowledge-cards/unacked-message/" data-link-title="Unacked Message" data-link-desc="說明 broker 已投遞但尚未收到 consumer 確認的訊息">Unacked Message</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>TTL 是資料新鮮度與操作成本的取捨。TTL 長可以提高命中率與降低下游壓力；TTL 短可以降低過期資料風險，但會增加重新載入與下游查詢。 可先對照 <a href="/blog/backend/knowledge-cards/unacked-message/" data-link-title="Unacked Message" data-link-desc="說明 broker 已投遞但尚未收到 consumer 確認的訊息">Unacked Message</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要調整 TTL 的訊號是資料過期造成錯誤體驗，或 cache miss 造成下游壓力。商品價格 cache 的 TTL 通常短於熱門文章榜；presence 狀態需要跟心跳頻率一起設計。</p>
<h2 id="設計責任">設計責任</h2>
<p>TTL 要依資料語意分級，並搭配主動失效、版本鍵或背景刷新。Runbook 應能查 key 剩餘時間、命中率、miss rate 與過期後重建成本。</p>
]]></content:encoded></item><item><title>Eviction</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/eviction/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/eviction/</guid><description>&lt;p>Eviction 的核心概念是「容量不足時系統選擇移除哪些資料」。快取與記憶體型服務需要 eviction policy，因為可用容量有限，資料量與 hot key 會隨流量變化。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/excessive-data-exposure/" data-link-title="Excessive Data Exposure" data-link-desc="說明 API 回傳過多資料如何增加敏感資訊外洩風險">Excessive Data Exposure&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Eviction 處理的是容量控制，TTL 處理的是時間有效性。Redis、CDN、local cache 都可能在容量壓力下淘汰資料；被淘汰的資料若可重建，系統會承擔額外查詢成本。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/excessive-data-exposure/" data-link-title="Excessive Data Exposure" data-link-desc="說明 API 回傳過多資料如何增加敏感資訊外洩風險">Excessive Data Exposure&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要關注 eviction 的訊號是 cache hit rate 突然下降、Redis memory 接近上限、下游資料庫壓力升高。熱門商品活動可能讓大量 key 進入快取，造成原本常用資料被擠出。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Eviction 策略要搭配 key 設計、容量規劃、資料重要性與告警。高價值或難重建資料應有更穩定的保存方式，一般快取淘汰策略只適合可重建資料。&lt;/p></description><content:encoded><![CDATA[<p>Eviction 的核心概念是「容量不足時系統選擇移除哪些資料」。快取與記憶體型服務需要 eviction policy，因為可用容量有限，資料量與 hot key 會隨流量變化。 可先對照 <a href="/blog/backend/knowledge-cards/excessive-data-exposure/" data-link-title="Excessive Data Exposure" data-link-desc="說明 API 回傳過多資料如何增加敏感資訊外洩風險">Excessive Data Exposure</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Eviction 處理的是容量控制，TTL 處理的是時間有效性。Redis、CDN、local cache 都可能在容量壓力下淘汰資料；被淘汰的資料若可重建，系統會承擔額外查詢成本。 可先對照 <a href="/blog/backend/knowledge-cards/excessive-data-exposure/" data-link-title="Excessive Data Exposure" data-link-desc="說明 API 回傳過多資料如何增加敏感資訊外洩風險">Excessive Data Exposure</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要關注 eviction 的訊號是 cache hit rate 突然下降、Redis memory 接近上限、下游資料庫壓力升高。熱門商品活動可能讓大量 key 進入快取，造成原本常用資料被擠出。</p>
<h2 id="設計責任">設計責任</h2>
<p>Eviction 策略要搭配 key 設計、容量規劃、資料重要性與告警。高價值或難重建資料應有更穩定的保存方式，一般快取淘汰策略只適合可重建資料。</p>
]]></content:encoded></item><item><title>Cache Aside</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-aside/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-aside/</guid><description>&lt;p>Cache aside 的核心概念是「application 先查快取，miss 時查正式來源，再把結果寫回快取」。這個模式讓 application 控制讀取流程、key 設計、TTL 與失效策略。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-miss/" data-link-title="Cache Hit / Miss" data-link-desc="說明快取命中與未命中如何影響讀取成本與下游壓力">Cache Hit / Miss&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cache aside 適合可重建的讀取資料。商品詳情、權限摘要、設定檔與熱門內容常用這種方式加速讀取；正式資料仍然在資料庫或下游服務，快取只是副本。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-miss/" data-link-title="Cache Hit / Miss" data-link-desc="說明快取命中與未命中如何影響讀取成本與下游壓力">Cache Hit / Miss&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統適合 cache aside 的訊號是讀多寫少、資料可重建、讀取成本高。商品頁查詢頻繁時，cache aside 可以降低資料庫壓力；結帳確認價格時仍應回到正式來源或使用更嚴格一致性策略。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Cache aside 要定義 cache miss、資料載入、寫回、失效、錯誤 fallback 與防止 stampede 的方式。測試要覆蓋 hit、miss、正式來源失敗、快取寫入失敗與過期資料情境。&lt;/p></description><content:encoded><![CDATA[<p>Cache aside 的核心概念是「application 先查快取，miss 時查正式來源，再把結果寫回快取」。這個模式讓 application 控制讀取流程、key 設計、TTL 與失效策略。 可先對照 <a href="/blog/backend/knowledge-cards/cache-hit-miss/" data-link-title="Cache Hit / Miss" data-link-desc="說明快取命中與未命中如何影響讀取成本與下游壓力">Cache Hit / Miss</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cache aside 適合可重建的讀取資料。商品詳情、權限摘要、設定檔與熱門內容常用這種方式加速讀取；正式資料仍然在資料庫或下游服務，快取只是副本。 可先對照 <a href="/blog/backend/knowledge-cards/cache-hit-miss/" data-link-title="Cache Hit / Miss" data-link-desc="說明快取命中與未命中如何影響讀取成本與下游壓力">Cache Hit / Miss</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統適合 cache aside 的訊號是讀多寫少、資料可重建、讀取成本高。商品頁查詢頻繁時，cache aside 可以降低資料庫壓力；結帳確認價格時仍應回到正式來源或使用更嚴格一致性策略。</p>
<h2 id="設計責任">設計責任</h2>
<p>Cache aside 要定義 cache miss、資料載入、寫回、失效、錯誤 fallback 與防止 stampede 的方式。測試要覆蓋 hit、miss、正式來源失敗、快取寫入失敗與過期資料情境。</p>
]]></content:encoded></item><item><title>Hot Key</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/hot-key/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/hot-key/</guid><description>&lt;p>Hot key 的核心概念是「少數 key 承受遠高於平均值的流量」。快取、資料庫、broker partition、rate limit counter 與排行榜都可能因 hot key 形成單點瓶頸。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP Client&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Hot key 是流量分布問題。總 QPS 看起來可承受時，單一商品、直播間、明星帳號、熱門活動或全域 counter 仍可能把某個 shard、partition 或 Redis node 打滿。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP Client&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 hot key 分析的訊號是整體容量尚可，但特定頁面、特定商品或特定 tenant 延遲異常。大型促銷活動中，熱門商品庫存 key 可能比其他商品多出數百倍讀寫。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Hot key 設計要考慮分片、local cache、讀寫分離、批次更新、限流與降級。觀測上要能按 key pattern、tenant、topic 或 partition 看流量集中度。&lt;/p></description><content:encoded><![CDATA[<p>Hot key 的核心概念是「少數 key 承受遠高於平均值的流量」。快取、資料庫、broker partition、rate limit counter 與排行榜都可能因 hot key 形成單點瓶頸。 可先對照 <a href="/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP Client</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Hot key 是流量分布問題。總 QPS 看起來可承受時，單一商品、直播間、明星帳號、熱門活動或全域 counter 仍可能把某個 shard、partition 或 Redis node 打滿。 可先對照 <a href="/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP Client</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 hot key 分析的訊號是整體容量尚可，但特定頁面、特定商品或特定 tenant 延遲異常。大型促銷活動中，熱門商品庫存 key 可能比其他商品多出數百倍讀寫。</p>
<h2 id="設計責任">設計責任</h2>
<p>Hot key 設計要考慮分片、local cache、讀寫分離、批次更新、限流與降級。觀測上要能按 key pattern、tenant、topic 或 partition 看流量集中度。</p>
]]></content:encoded></item><item><title>Cache Stampede</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-stampede/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-stampede/</guid><description>&lt;p>Cache stampede 的核心概念是「大量 request 在同一時間遇到 cache miss，並同時打向正式來源」。這個現象常出現在熱門 key 過期、服務重啟、快取清空或活動流量尖峰。 可先對照 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cache stampede 是快取失效與下游保護的交界。快取原本用來保護資料庫；若熱門資料同時過期，快取反而會把大量請求集中送到資料庫。 可先對照 &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>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要處理 stampede 的訊號是 cache miss rate 突然升高，同時資料庫查詢數、latency 與 timeout 上升。熱門文章榜每分鐘整點過期，可能讓所有 request 在同一秒重建同一份資料。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>常見策略包括 singleflight、soft TTL、background refresh、jitter、lock 與 fallback stale data。設計時要讓少數 request 負責重建，多數 request 使用既有資料或等待有界時間。&lt;/p></description><content:encoded><![CDATA[<p>Cache stampede 的核心概念是「大量 request 在同一時間遇到 cache miss，並同時打向正式來源」。這個現象常出現在熱門 key 過期、服務重啟、快取清空或活動流量尖峰。 可先對照 <a href="/blog/backend/knowledge-cards/cache-warmup/" data-link-title="Cache Warmup" data-link-desc="說明服務啟動或活動前如何預先建立快取資料">Cache Warmup</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cache stampede 是快取失效與下游保護的交界。快取原本用來保護資料庫；若熱門資料同時過期，快取反而會把大量請求集中送到資料庫。 可先對照 <a href="/blog/backend/knowledge-cards/cache-warmup/" data-link-title="Cache Warmup" data-link-desc="說明服務啟動或活動前如何預先建立快取資料">Cache Warmup</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要處理 stampede 的訊號是 cache miss rate 突然升高，同時資料庫查詢數、latency 與 timeout 上升。熱門文章榜每分鐘整點過期，可能讓所有 request 在同一秒重建同一份資料。</p>
<h2 id="設計責任">設計責任</h2>
<p>常見策略包括 singleflight、soft TTL、background refresh、jitter、lock 與 fallback stale data。設計時要讓少數 request 負責重建，多數 request 使用既有資料或等待有界時間。</p>
]]></content:encoded></item><item><title>Ack / Nack</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/ack-nack/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/ack-nack/</guid><description>&lt;p>Ack / nack 的核心概念是「&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/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a> 回報訊息處理結果」。Ack 表示訊息已完成處理，可以從待處理集合移除；nack 或 reject 表示處理未完成，需要 &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/requeue/" data-link-title="Requeue" data-link-desc="說明處理失敗的訊息重新排回 queue 時的風險與控制條件">requeue&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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Ack / nack 是投遞保證的關鍵協議。Consumer crash、網路中斷或 ack timeout 都可能讓 broker 判斷訊息尚未完成，進而 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/redelivery/" data-link-title="Redelivery" data-link-desc="說明 broker 重新投遞訊息時 consumer 需要承擔的重入責任">redelivery&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要理解 ack / nack 的訊號是訊息重複、&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/unacked-message/" data-link-title="Unacked Message" data-link-desc="說明 broker 已投遞但尚未收到 consumer 確認的訊息">unacked message&lt;/a> 累積。影片轉檔 worker 若在完成前 crash，訊息應重新投遞；若已產生外部副作用，consumer 需要 &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;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Consumer 要明確決定何時 ack。通常應在業務處理與必要狀態保存完成後 ack；永久性錯誤要分類送往 dead-letter queue；暫時性錯誤要搭配 retry policy、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/exponential-backoff/" data-link-title="Exponential Backoff" data-link-desc="說明重試間隔如何逐步拉長以降低下游壓力">exponential backoff&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/jitter/" data-link-title="Jitter" data-link-desc="說明重試或排程加入隨機偏移如何降低同步尖峰">jitter&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Ack / nack 的核心概念是「<a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a> 對 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> 回報訊息處理結果」。Ack 表示訊息已完成處理，可以從待處理集合移除；nack 或 reject 表示處理未完成，需要 <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/requeue/" data-link-title="Requeue" data-link-desc="說明處理失敗的訊息重新排回 queue 時的風險與控制條件">requeue</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>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Ack / nack 是投遞保證的關鍵協議。Consumer crash、網路中斷或 ack timeout 都可能讓 broker 判斷訊息尚未完成，進而 <a href="/blog/backend/knowledge-cards/redelivery/" data-link-title="Redelivery" data-link-desc="說明 broker 重新投遞訊息時 consumer 需要承擔的重入責任">redelivery</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要理解 ack / nack 的訊號是訊息重複、<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/unacked-message/" data-link-title="Unacked Message" data-link-desc="說明 broker 已投遞但尚未收到 consumer 確認的訊息">unacked message</a> 累積。影片轉檔 worker 若在完成前 crash，訊息應重新投遞；若已產生外部副作用，consumer 需要 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 保護。</p>
<h2 id="設計責任">設計責任</h2>
<p>Consumer 要明確決定何時 ack。通常應在業務處理與必要狀態保存完成後 ack；永久性錯誤要分類送往 dead-letter queue；暫時性錯誤要搭配 retry policy、<a href="/blog/backend/knowledge-cards/exponential-backoff/" data-link-title="Exponential Backoff" data-link-desc="說明重試間隔如何逐步拉長以降低下游壓力">exponential backoff</a> 與 <a href="/blog/backend/knowledge-cards/jitter/" data-link-title="Jitter" data-link-desc="說明重試或排程加入隨機偏移如何降低同步尖峰">jitter</a>。</p>
]]></content:encoded></item><item><title>Retry Policy</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/retry-policy/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/retry-policy/</guid><description>&lt;p>Retry policy 的核心概念是「定義失敗後何時再試、試幾次、用什麼間隔、何時停止」。重試可以吸收暫時性故障（網路抖動、下游短暫不可用），但也可能放大下游壓力或重複造成副作用，因此跟 &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/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">dead-letter queue&lt;/a> 是成對設計。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Retry policy 跟 &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> 構成錯誤處理的兩層機制 — retry 處理暫時性失敗，DLQ 承接 retry 耗盡後仍無法處理的訊息。Retry 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency&lt;/a> 是成對的設計 — 有 retry 就要有 idempotent consumer，否則重試可能造成重複扣款、重複發通知。&lt;/p>
&lt;p>Retry 跟 &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> 的關係是：大量 consumer 同時 retry 失敗的訊息會形成下游的流量尖峰，把暫時性故障放大成全系統問題。Exponential backoff + jitter 是緩解 retry storm 的標準做法。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 retry policy 的訊號是下游偶發失敗影響成功率。付款查詢 API 短暫 timeout 可以重試；已送出的扣款請求則需要先查詢結果或用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency&lt;/a> key，避免重試造成重複扣款。&lt;/p>
&lt;p>Retry 的判斷分類：暫時性錯誤（5xx、timeout、connection refused）適合 retry；永久性錯誤（4xx、schema validation failure、business rule violation）不應該 retry，直接送 DLQ 或 reject。分類錯誤是 retry policy 最常見的 bug — 對永久性錯誤 retry 只會消耗 quota、延遲問題被發現的時間。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Retry policy 要包含最大重試次數、backoff 策略（fixed / exponential / exponential + jitter）、每次 retry 的 timeout、錯誤分類規則（哪些 error code 算暫時性）、觀測欄位（retry count、最終結果）與停止條件（超過 N 次進 DLQ）。高流量系統還要設定 retry budget — 限制 retry 流量佔總流量的比例，避免 retry 自身成為負載來源。&lt;/p></description><content:encoded><![CDATA[<p>Retry policy 的核心概念是「定義失敗後何時再試、試幾次、用什麼間隔、何時停止」。重試可以吸收暫時性故障（網路抖動、下游短暫不可用），但也可能放大下游壓力或重複造成副作用，因此跟 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</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> 是成對設計。</p>
<h2 id="概念位置">概念位置</h2>
<p>Retry policy 跟 <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> 構成錯誤處理的兩層機制 — retry 處理暫時性失敗，DLQ 承接 retry 耗盡後仍無法處理的訊息。Retry 跟 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 是成對的設計 — 有 retry 就要有 idempotent consumer，否則重試可能造成重複扣款、重複發通知。</p>
<p>Retry 跟 <a href="/blog/backend/knowledge-cards/retry-storm/" data-link-title="Retry Storm" data-link-desc="說明大量重試如何把局部故障放大成系統壓力">retry storm</a> 的關係是：大量 consumer 同時 retry 失敗的訊息會形成下游的流量尖峰，把暫時性故障放大成全系統問題。Exponential backoff + jitter 是緩解 retry storm 的標準做法。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 retry policy 的訊號是下游偶發失敗影響成功率。付款查詢 API 短暫 timeout 可以重試；已送出的扣款請求則需要先查詢結果或用 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> key，避免重試造成重複扣款。</p>
<p>Retry 的判斷分類：暫時性錯誤（5xx、timeout、connection refused）適合 retry；永久性錯誤（4xx、schema validation failure、business rule violation）不應該 retry，直接送 DLQ 或 reject。分類錯誤是 retry policy 最常見的 bug — 對永久性錯誤 retry 只會消耗 quota、延遲問題被發現的時間。</p>
<h2 id="設計責任">設計責任</h2>
<p>Retry policy 要包含最大重試次數、backoff 策略（fixed / exponential / exponential + jitter）、每次 retry 的 timeout、錯誤分類規則（哪些 error code 算暫時性）、觀測欄位（retry count、最終結果）與停止條件（超過 N 次進 DLQ）。高流量系統還要設定 retry budget — 限制 retry 流量佔總流量的比例，避免 retry 自身成為負載來源。</p>
]]></content:encoded></item><item><title>Idempotency</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/</guid><description>&lt;p>Idempotency 的核心概念是「同一操作執行一次或多次，最終業務結果相同」。後端系統用 idempotency 保護重試、重複投遞、使用者重送 request 與外部 API timeout。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">Idle Timeout&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Idempotency 是副作用邊界的穩定性設計。查詢通常天然接近 idempotent；建立訂單、扣款、出貨、寄送通知與發放點數都需要額外設計 idempotency key 或狀態檢查。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">Idle Timeout&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 idempotency 的訊號是同一 intent 可能重送。使用者按兩次付款、broker 重複投遞付款成功事件、HTTP client timeout 後重試，都可能讓同一業務意圖進入系統多次。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Idempotency 設計要有穩定 key、唯一約束、處理紀錄、結果查詢與過期策略。測試要覆蓋連續重送、處理中 crash、外部 API timeout 與 replay。&lt;/p></description><content:encoded><![CDATA[<p>Idempotency 的核心概念是「同一操作執行一次或多次，最終業務結果相同」。後端系統用 idempotency 保護重試、重複投遞、使用者重送 request 與外部 API timeout。 可先對照 <a href="/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">Idle Timeout</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Idempotency 是副作用邊界的穩定性設計。查詢通常天然接近 idempotent；建立訂單、扣款、出貨、寄送通知與發放點數都需要額外設計 idempotency key 或狀態檢查。 可先對照 <a href="/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">Idle Timeout</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 idempotency 的訊號是同一 intent 可能重送。使用者按兩次付款、broker 重複投遞付款成功事件、HTTP client timeout 後重試，都可能讓同一業務意圖進入系統多次。</p>
<h2 id="設計責任">設計責任</h2>
<p>Idempotency 設計要有穩定 key、唯一約束、處理紀錄、結果查詢與過期策略。測試要覆蓋連續重送、處理中 crash、外部 API timeout 與 replay。</p>
]]></content:encoded></item><item><title>Outbox Pattern</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/outbox-pattern/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/outbox-pattern/</guid><description>&lt;p>Outbox pattern 的核心概念是「把業務資料變更與待發布事件寫進同一個資料庫交易」。交易提交後，獨立 publisher 再從 outbox table 讀出事件並發布到 broker。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ownership/" data-link-title="Ownership" data-link-desc="說明 ownership 如何把問題、決策與交接責任固定到可執行角色">Ownership&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Outbox 解決的是資料已寫入但事件發布失敗的半成功問題。資料庫交易保護業務狀態與 outbox 紀錄；broker 發布則用後續重試與 idempotency 保證最終送出。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ownership/" data-link-title="Ownership" data-link-desc="說明 ownership 如何把問題、決策與交接責任固定到可執行角色">Ownership&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 outbox 的訊號是「狀態改變後，其他服務必須知道」。訂單付款完成後，倉儲、通知與分析都需要收到事件；若事件發布失敗但訂單已付款，後續流程會漏執行。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Outbox 要設計 event schema、publisher checkpoint、retry、dead-letter、去重與監控。Runbook 應能看到 outbox backlog、發布錯誤、最舊未發布時間與 replay 流程。&lt;/p></description><content:encoded><![CDATA[<p>Outbox pattern 的核心概念是「把業務資料變更與待發布事件寫進同一個資料庫交易」。交易提交後，獨立 publisher 再從 outbox table 讀出事件並發布到 broker。 可先對照 <a href="/blog/backend/knowledge-cards/ownership/" data-link-title="Ownership" data-link-desc="說明 ownership 如何把問題、決策與交接責任固定到可執行角色">Ownership</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Outbox 解決的是資料已寫入但事件發布失敗的半成功問題。資料庫交易保護業務狀態與 outbox 紀錄；broker 發布則用後續重試與 idempotency 保證最終送出。 可先對照 <a href="/blog/backend/knowledge-cards/ownership/" data-link-title="Ownership" data-link-desc="說明 ownership 如何把問題、決策與交接責任固定到可執行角色">Ownership</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 outbox 的訊號是「狀態改變後，其他服務必須知道」。訂單付款完成後，倉儲、通知與分析都需要收到事件；若事件發布失敗但訂單已付款，後續流程會漏執行。</p>
<h2 id="設計責任">設計責任</h2>
<p>Outbox 要設計 event schema、publisher checkpoint、retry、dead-letter、去重與監控。Runbook 應能看到 outbox backlog、發布錯誤、最舊未發布時間與 replay 流程。</p>
]]></content:encoded></item><item><title>Saga</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/saga/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/saga/</guid><description>&lt;p>Saga 是處理跨服務分散事務的設計模式：把一筆業務動作拆成一系列局部 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">transaction&lt;/a>、每個 step 在對應服務內以本地 transaction 完成、若中途某 step 失敗、就反向執行已完成 step 的補償 transaction 回到一致狀態。Saga 不提供 ACID 的 atomic 保證、是用最終一致 + 補償可回退換取跨服務獨立性。跟 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency&lt;/a> 共同構成 microservice 一致性的三件套。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Saga 處於跨服務分散事務的設計層。Saga 解「跨服務事務一致」、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/outbox-pattern/" data-link-title="Outbox Pattern" data-link-desc="說明資料庫狀態變更與事件發布如何透過 outbox 維持一致">outbox&lt;/a> 解「事件不丟」、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency&lt;/a> 解「補償可重放」。兩種常見實作 variant：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Choreography（編舞）&lt;/strong>：每個服務監聽事件、自行決定下一步動作、不需要中央協調者。耦合低；業務流程散落、debug 困難。&lt;/li>
&lt;li>&lt;strong>Orchestration（編排）&lt;/strong>：用一個中央 saga orchestrator 持有 state machine、逐步呼叫各服務並追蹤狀態。流程集中可見；orchestrator 是單點。&lt;/li>
&lt;/ul>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>電商 checkout 是典型 saga：下訂單 → 扣庫存 → 扣餘額 → 出貨。任一 step 失敗、反向觸發補償（退款、回滾庫存、取消訂單）。Order management、支付清算、跨服務交易都會用到。補償 transaction 失敗率非零、saga 引擎需要 retry + dead letter queue 處理。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>補償 transaction 必須是 idempotent — saga 引擎在故障重試時會重放補償。缺 idempotent 設計時、saga 補償會變成新事故來源。Choreography vs orchestration 的選擇要看「業務流程穩定度」— 流程穩定可走 choreography 簡化耦合、流程多變或 audit 要求高選 orchestration 保留 state machine。Saga timeout 跟 step timeout 要明示、確保 saga 推進到終態（成功或補償完成）。&lt;/p></description><content:encoded><![CDATA[<p>Saga 是處理跨服務分散事務的設計模式：把一筆業務動作拆成一系列局部 <a href="/blog/backend/knowledge-cards/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">transaction</a>、每個 step 在對應服務內以本地 transaction 完成、若中途某 step 失敗、就反向執行已完成 step 的補償 transaction 回到一致狀態。Saga 不提供 ACID 的 atomic 保證、是用最終一致 + 補償可回退換取跨服務獨立性。跟 <a href="/blog/backend/knowledge-cards/outbox-pattern/" data-link-title="Outbox Pattern" data-link-desc="說明資料庫狀態變更與事件發布如何透過 outbox 維持一致">outbox pattern</a> 跟 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 共同構成 microservice 一致性的三件套。</p>
<h2 id="概念位置">概念位置</h2>
<p>Saga 處於跨服務分散事務的設計層。Saga 解「跨服務事務一致」、<a href="/blog/backend/knowledge-cards/outbox-pattern/" data-link-title="Outbox Pattern" data-link-desc="說明資料庫狀態變更與事件發布如何透過 outbox 維持一致">outbox</a> 解「事件不丟」、<a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 解「補償可重放」。兩種常見實作 variant：</p>
<ul>
<li><strong>Choreography（編舞）</strong>：每個服務監聽事件、自行決定下一步動作、不需要中央協調者。耦合低；業務流程散落、debug 困難。</li>
<li><strong>Orchestration（編排）</strong>：用一個中央 saga orchestrator 持有 state machine、逐步呼叫各服務並追蹤狀態。流程集中可見；orchestrator 是單點。</li>
</ul>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>電商 checkout 是典型 saga：下訂單 → 扣庫存 → 扣餘額 → 出貨。任一 step 失敗、反向觸發補償（退款、回滾庫存、取消訂單）。Order management、支付清算、跨服務交易都會用到。補償 transaction 失敗率非零、saga 引擎需要 retry + dead letter queue 處理。</p>
<h2 id="設計責任">設計責任</h2>
<p>補償 transaction 必須是 idempotent — saga 引擎在故障重試時會重放補償。缺 idempotent 設計時、saga 補償會變成新事故來源。Choreography vs orchestration 的選擇要看「業務流程穩定度」— 流程穩定可走 choreography 簡化耦合、流程多變或 audit 要求高選 orchestration 保留 state machine。Saga timeout 跟 step timeout 要明示、確保 saga 推進到終態（成功或補償完成）。</p>
]]></content:encoded></item><item><title>Backpressure</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/backpressure/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/backpressure/</guid><description>&lt;p>Backpressure 的核心概念是「下游處理能力不足時，讓上游感知並放慢」。它把上游從「盲目送出」轉為「依下游能力送出」，讓系統在壓力下排隊、拒絕、降級或削峰，以保護下游資源並維持整體可預測性。Backpressure 的本質是「壓力從下游往上游傳遞」的訊號通道，覆蓋範圍比單純的拒絕策略更廣。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Backpressure 出現在 &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/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP client&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&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;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/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">stream pipeline&lt;/a>。它處理的是速度不匹配：進入速度高於處理速度。&lt;/p>
&lt;p>Backpressure 與 &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> 的差別在於資訊流向：rate limit 由上游主動設閘門（「每秒最多 N 個」），屬於容量規劃；backpressure 由下游回饋壓力（「我現在只能吃 M 個」），屬於動態調速。兩者常搭配使用：rate limit 處理已知的規劃容量，backpressure 處理無法預先預測的即時變化。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>需要 backpressure 的訊號包含 &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/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout&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> 加深、下游 error rate 上升。當這些指標同時出現而上游流量維持穩定時，代表處理鏈某一段已成為瓶頸，壓力需要向上傳遞，而不是繼續往 buffer 堆積。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>通知服務在行銷活動期間收到大量派送任務。若任務直接交給 worker 處理，worker 很快會塞滿下游第三方 API 的連線配額，latency 暴增、重試加倍，最終把佇列塞爆。導入 backpressure 後，服務依下游 API 實際吞吐動態調整 worker 取件速度：API 回應變慢時 worker 取件速度自動下降，上游請求端收到「任務已接收但延後送達」的回覆。整條 pipeline 的處理速度由最慢的一段決定，系統保留在可預測、可恢復的狀態。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Backpressure 導入後，團隊需要定義以下邊界：&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/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/load-shedding/" data-link-title="Load Shedding" data-link-desc="說明服務過載時如何主動拒絕低優先工作以保護核心能力">load shedding&lt;/a> 與對使用者的回饋（429 / 503 / 延後通知）。觀測上應能看到 &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>、in-flight 數量、處理耗時、drop count、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout&lt;/a>、下游 error rate，並把關鍵指標放進 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a>。&lt;/p>
&lt;p>設計取捨的核心是 buffer 尺度：buffer 太小會讓瞬間尖峰被過度拒絕，流失可接受的請求；buffer 太大則延遲失控並可能拖累記憶體。穩定做法是「有限 buffer + 明確拒絕策略」，讓系統在超載時 fail fast，避免把壓力延後累積成更大的雪崩。&lt;/p>
&lt;p>監控系統中 collector 用 HTTP 429 向 SDK 傳遞背壓的具體實作見 &lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="下游處理能力不足時向上游回傳「慢下來」訊號的流量控制機制 — 監控系統中 collector 用 HTTP 429 向 SDK 傳遞背壓">監控知識卡：Backpressure&lt;/a>。&lt;/p>
&lt;!--
codex-check:
 C1-intent: pass
 C2-atomic: pass (聚焦 backpressure 本身，相鄰概念皆以連結引用)
 C3-business-first: pass (定義段落說明要解決的問題)
 C4-reasoning-path: pass (概念位置 → 訊號 → 例子 → 設計責任)
 C5-searchable: pass (關鍵詞 backpressure / buffer / queue depth 皆 grep 友善)
 C6-positive-framing: pass (「避免」僅用於安全警示語境，屬正面表述例外（物理限制、安全警示、反模式對照）)
 C7-source-verified: pass
 reviewed-at: 2026-04-23
 role: reference-sample (brief 檔案結構段指定正面範例卡片)
--></description><content:encoded><![CDATA[<p>Backpressure 的核心概念是「下游處理能力不足時，讓上游感知並放慢」。它把上游從「盲目送出」轉為「依下游能力送出」，讓系統在壓力下排隊、拒絕、降級或削峰，以保護下游資源並維持整體可預測性。Backpressure 的本質是「壓力從下游往上游傳遞」的訊號通道，覆蓋範圍比單純的拒絕策略更廣。 可先對照 <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>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Backpressure 出現在 <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/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a>、<a href="/blog/backend/knowledge-cards/worker-pool/" data-link-title="Worker Pool" data-link-desc="說明一組 worker 如何限制同時處理量並保護下游資源">worker pool</a>、<a href="/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP client</a>、<a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a>、<a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> 的 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a> 與 <a href="/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">stream pipeline</a>。它處理的是速度不匹配：進入速度高於處理速度。</p>
<p>Backpressure 與 <a href="/blog/backend/knowledge-cards/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">rate limit</a> 的差別在於資訊流向：rate limit 由上游主動設閘門（「每秒最多 N 個」），屬於容量規劃；backpressure 由下游回饋壓力（「我現在只能吃 M 個」），屬於動態調速。兩者常搭配使用：rate limit 處理已知的規劃容量，backpressure 處理無法預先預測的即時變化。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>需要 backpressure 的訊號包含 <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/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout</a> 比例擴大、<a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag</a> 加深、下游 error rate 上升。當這些指標同時出現而上游流量維持穩定時，代表處理鏈某一段已成為瓶頸，壓力需要向上傳遞，而不是繼續往 buffer 堆積。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>通知服務在行銷活動期間收到大量派送任務。若任務直接交給 worker 處理，worker 很快會塞滿下游第三方 API 的連線配額，latency 暴增、重試加倍，最終把佇列塞爆。導入 backpressure 後，服務依下游 API 實際吞吐動態調整 worker 取件速度：API 回應變慢時 worker 取件速度自動下降，上游請求端收到「任務已接收但延後送達」的回覆。整條 pipeline 的處理速度由最慢的一段決定，系統保留在可預測、可恢復的狀態。</p>
<h2 id="設計責任">設計責任</h2>
<p>Backpressure 導入後，團隊需要定義以下邊界：<a href="/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">buffer</a> 大小、排隊上限、等待期限、拒絕策略、<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/load-shedding/" data-link-title="Load Shedding" data-link-desc="說明服務過載時如何主動拒絕低優先工作以保護核心能力">load shedding</a> 與對使用者的回饋（429 / 503 / 延後通知）。觀測上應能看到 <a href="/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">queue depth</a>、in-flight 數量、處理耗時、drop count、<a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout</a>、下游 error rate，並把關鍵指標放進 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a>。</p>
<p>設計取捨的核心是 buffer 尺度：buffer 太小會讓瞬間尖峰被過度拒絕，流失可接受的請求；buffer 太大則延遲失控並可能拖累記憶體。穩定做法是「有限 buffer + 明確拒絕策略」，讓系統在超載時 fail fast，避免把壓力延後累積成更大的雪崩。</p>
<p>監控系統中 collector 用 HTTP 429 向 SDK 傳遞背壓的具體實作見 <a href="/blog/monitoring/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="下游處理能力不足時向上游回傳「慢下來」訊號的流量控制機制 — 監控系統中 collector 用 HTTP 429 向 SDK 傳遞背壓">監控知識卡：Backpressure</a>。</p>
<!--
codex-check:
  C1-intent: pass
  C2-atomic: pass (聚焦 backpressure 本身，相鄰概念皆以連結引用)
  C3-business-first: pass (定義段落說明要解決的問題)
  C4-reasoning-path: pass (概念位置 → 訊號 → 例子 → 設計責任)
  C5-searchable: pass (關鍵詞 backpressure / buffer / queue depth 皆 grep 友善)
  C6-positive-framing: pass (「避免」僅用於安全警示語境，屬正面表述例外（物理限制、安全警示、反模式對照）)
  C7-source-verified: pass
  reviewed-at: 2026-04-23
  role: reference-sample (brief 檔案結構段指定正面範例卡片)
-->
]]></content:encoded></item><item><title>Consensus Protocol</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/consensus-protocol/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/consensus-protocol/</guid><description>&lt;p>Consensus protocol 的核心責任是「讓多個獨立節點在訊息可能延遲、丟失、亂序的網路環境下、仍能對同一個值或同一個決策達成一致」。常見演算法：Paxos（理論基礎、難實作）、Raft（教學友善、Etcd / Consul / CockroachDB 採用）、ZAB（ZooKeeper 採用）、Multi-Paxos / EPaxos（Paxos 工程變體）。是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/leader-election/" data-link-title="Leader Election" data-link-desc="從一群對等節點中選出單一主節點負責獨佔工作、leader 失效時自動選新 leader">leader election&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-lock/" data-link-title="Distributed Lock" data-link-desc="跨機器跨 process 的互斥鎖、用 lease 機制處理 holder 失效">distributed lock&lt;/a> 的底層機制、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-channel/" data-link-title="Replication Channel" data-link-desc="說明多來源複製中，每個來源對應的獨立複製通道如何成為隔離單位">replication channel&lt;/a> 互補（consensus 保證一致順序、replication 負責複製狀態）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Consensus protocol 處於分散式系統的協調控制底層、上面分別構築 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/leader-election/" data-link-title="Leader Election" data-link-desc="從一群對等節點中選出單一主節點負責獨佔工作、leader 失效時自動選新 leader">leader election&lt;/a>、state machine replication、cluster membership 三類能力。每筆 write 通常要跨 majority quorum 節點 round trip — 5 節點 cluster 失去 3 節點以上就停寫保護（防範 split-brain）。對比 gossip protocol（SWIM、Serf）— consensus 給「強一致順序」、gossip 給「最終一致成員管理」、各自適用情境。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Etcd / Consul / ZooKeeper 都是 consensus 服務、被 Kubernetes、Vault、Patroni 等系統當 coordination backend。實測 commit latency 隨 cluster 大小升高（3 節點同 AZ ~ 1-5ms、5 節點跨 region 可能 50-200ms）。故障恢復期間 election timeout 典型 150-500ms、期間短暫不可寫。CockroachDB / Spanner 在 OLTP write 路徑同樣依賴 consensus、是寫入延遲的下限。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>水平擴展 stateful 服務時、若依賴 distributed lock 或 leader election 來協調工作、要把 consensus latency 算進事故時的 RTO。Quorum 大小設計要考慮「容忍 N 節點失效」需要至少 2N+1 節點。跨 region 部署的 consensus 服務、要明示「region 失效時降級為 read-only」的策略 — region 失效時 quorum 可能跨不過、要事先規劃降級路徑。&lt;/p></description><content:encoded><![CDATA[<p>Consensus protocol 的核心責任是「讓多個獨立節點在訊息可能延遲、丟失、亂序的網路環境下、仍能對同一個值或同一個決策達成一致」。常見演算法：Paxos（理論基礎、難實作）、Raft（教學友善、Etcd / Consul / CockroachDB 採用）、ZAB（ZooKeeper 採用）、Multi-Paxos / EPaxos（Paxos 工程變體）。是 <a href="/blog/backend/knowledge-cards/leader-election/" data-link-title="Leader Election" data-link-desc="從一群對等節點中選出單一主節點負責獨佔工作、leader 失效時自動選新 leader">leader election</a> 跟 <a href="/blog/backend/knowledge-cards/distributed-lock/" data-link-title="Distributed Lock" data-link-desc="跨機器跨 process 的互斥鎖、用 lease 機制處理 holder 失效">distributed lock</a> 的底層機制、跟 <a href="/blog/backend/knowledge-cards/replication-channel/" data-link-title="Replication Channel" data-link-desc="說明多來源複製中，每個來源對應的獨立複製通道如何成為隔離單位">replication channel</a> 互補（consensus 保證一致順序、replication 負責複製狀態）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Consensus protocol 處於分散式系統的協調控制底層、上面分別構築 <a href="/blog/backend/knowledge-cards/leader-election/" data-link-title="Leader Election" data-link-desc="從一群對等節點中選出單一主節點負責獨佔工作、leader 失效時自動選新 leader">leader election</a>、state machine replication、cluster membership 三類能力。每筆 write 通常要跨 majority quorum 節點 round trip — 5 節點 cluster 失去 3 節點以上就停寫保護（防範 split-brain）。對比 gossip protocol（SWIM、Serf）— consensus 給「強一致順序」、gossip 給「最終一致成員管理」、各自適用情境。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Etcd / Consul / ZooKeeper 都是 consensus 服務、被 Kubernetes、Vault、Patroni 等系統當 coordination backend。實測 commit latency 隨 cluster 大小升高（3 節點同 AZ ~ 1-5ms、5 節點跨 region 可能 50-200ms）。故障恢復期間 election timeout 典型 150-500ms、期間短暫不可寫。CockroachDB / Spanner 在 OLTP write 路徑同樣依賴 consensus、是寫入延遲的下限。</p>
<h2 id="設計責任">設計責任</h2>
<p>水平擴展 stateful 服務時、若依賴 distributed lock 或 leader election 來協調工作、要把 consensus latency 算進事故時的 RTO。Quorum 大小設計要考慮「容忍 N 節點失效」需要至少 2N+1 節點。跨 region 部署的 consensus 服務、要明示「region 失效時降級為 read-only」的策略 — region 失效時 quorum 可能跨不過、要事先規劃降級路徑。</p>
]]></content:encoded></item><item><title>Rate Limit</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/rate-limit/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/rate-limit/</guid><description>&lt;p>Rate limit 的核心概念是「限制某個主體在一段時間內可以使用的資源量」。主體可以是 user、API key、IP、tenant、endpoint、worker、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer&lt;/a> 或內部服務。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Rate limit 是容量保護與公平性工具。它可以保護登入、搜尋、匯出、第三方 API、webhook endpoint 與下游服務，降低單一來源耗盡共享資源的風險。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">Producer&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 rate limit 的訊號是少數使用者或客戶端造成大量 request。匯出報表 API 缺少 rate limit 時，單一 tenant 的批次工作可能佔滿 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a> &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&lt;/a>，影響其他 tenant 的正常查詢。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>限流設計要定義主體、窗口、配額、超限回應、例外權限與觀測欄位。對外 API 要提供清楚的 retry-after 或配額資訊；內部服務要搭配 &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/token-bucket/" data-link-title="Token Bucket" data-link-desc="說明 token bucket 如何用配額與補充速率控制流量">token bucket&lt;/a> 與容量規劃。完整的實作指南（單機 middleware、Redis 分散式限速、配額設計）見 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/rate-limit-implementation/" data-link-title="Rate Limit 實作" data-link-desc="單機 middleware / Redis 分散式限速 / 配額設計 — 概念見 DevOps 流量管控，本章聚焦後端實作">Rate Limit 實作&lt;/a>。&lt;/p>
&lt;p>監控系統中 per-SDK rate limiting 和偽造流量防護的具體實作見 &lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/rate-limiting/" data-link-title="Rate Limiting" data-link-desc="限制每個 client 在單位時間內可送出的事件數量 — 防止單一 SDK bug 或偽造流量消耗整個 collector 的處理能力">監控知識卡：Rate Limiting&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Rate limit 的核心概念是「限制某個主體在一段時間內可以使用的資源量」。主體可以是 user、API key、IP、tenant、endpoint、worker、<a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer</a> 或內部服務。</p>
<h2 id="概念位置">概念位置</h2>
<p>Rate limit 是容量保護與公平性工具。它可以保護登入、搜尋、匯出、第三方 API、webhook endpoint 與下游服務，降低單一來源耗盡共享資源的風險。 可先對照 <a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">Producer</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 rate limit 的訊號是少數使用者或客戶端造成大量 request。匯出報表 API 缺少 rate limit 時，單一 tenant 的批次工作可能佔滿 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a> <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a>，影響其他 tenant 的正常查詢。</p>
<h2 id="設計責任">設計責任</h2>
<p>限流設計要定義主體、窗口、配額、超限回應、例外權限與觀測欄位。對外 API 要提供清楚的 retry-after 或配額資訊；內部服務要搭配 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>、<a href="/blog/backend/knowledge-cards/token-bucket/" data-link-title="Token Bucket" data-link-desc="說明 token bucket 如何用配額與補充速率控制流量">token bucket</a> 與容量規劃。完整的實作指南（單機 middleware、Redis 分散式限速、配額設計）見 <a href="/blog/backend/09-performance-capacity/rate-limit-implementation/" data-link-title="Rate Limit 實作" data-link-desc="單機 middleware / Redis 分散式限速 / 配額設計 — 概念見 DevOps 流量管控，本章聚焦後端實作">Rate Limit 實作</a>。</p>
<p>監控系統中 per-SDK rate limiting 和偽造流量防護的具體實作見 <a href="/blog/monitoring/knowledge-cards/rate-limiting/" data-link-title="Rate Limiting" data-link-desc="限制每個 client 在單位時間內可送出的事件數量 — 防止單一 SDK bug 或偽造流量消耗整個 collector 的處理能力">監控知識卡：Rate Limiting</a>。</p>
]]></content:encoded></item><item><title>Stale-While-Revalidate</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/stale-while-revalidate/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/stale-while-revalidate/</guid><description>&lt;p>Stale-while-revalidate（SWR）的核心概念是「&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ttl/" data-link-title="TTL" data-link-desc="說明資料過期時間如何影響快取新鮮度、成本與一致性">TTL&lt;/a> 過期後仍可立即回舊版本給使用者、同時背景發出 origin request 拉取新版本更新快取」。使用者體驗永遠快、新鮮度有「最多 stale &lt;code>max-age + swr&lt;/code>」秒的上限。是天然的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">cache stampede&lt;/a> 緩解機制 — 把「TTL 過期那一刻 N 個請求同時打 origin」變成「TTL 過期那一刻 1 個請求打 origin、其他 N-1 個拿舊版」。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SWR 處於 HTTP cache 失效策略層、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ttl/" data-link-title="TTL" data-link-desc="說明資料過期時間如何影響快取新鮮度、成本與一致性">TTL&lt;/a>、&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> 是兄弟概念。TTL 定義「何時 expire」、SWR 定義「expire 之後仍允許用舊版的時間窗口」、cache invalidation 定義「主動清掉」。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stale-if-error/" data-link-title="Stale-If-Error" data-link-desc="HTTP cache-control directive、origin 出錯時用舊版頂著、確保使用者拿到有效回應">Stale-If-Error&lt;/a> 屬不同維度但常一起配置 — SWR 處理過期、SIE 處理錯誤。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>&lt;code>Cache-Control: max-age=60, stale-while-revalidate=600&lt;/code> 的服務行為：60 秒內 cache 完全新鮮、60-660 秒之間 client 仍立即拿到舊版（但 cache 已背景重整）、660 秒後才強制等 origin response。Cloudflare / Fastly / Varnish 都支援、瀏覽器 cache 也尊重這個 directive。&lt;/p>
&lt;p>新鮮度敏感的場景（庫存、價格、權限）應限縮 SWR 範圍或關閉、保住 stale 風險的上限；blog 文章、商品描述、靜態 metadata 適合 SWR 降低 origin 壓力。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選擇 SWR window 要在「origin 壓力」跟「freshness budget」間取捨。Window 越長、origin 壓力越低、stale 容忍度越高；window 越短、freshness 越接近 TTL、但 cache stampede 緩解效果下降。常見組合是 &lt;code>stale-while-revalidate&lt;/code> 設成 &lt;code>max-age&lt;/code> 的 5-10 倍。資料新鮮度敏感場景要走白名單路徑、由 endpoint 個別 opt-in 開啟 SWR。&lt;/p></description><content:encoded><![CDATA[<p>Stale-while-revalidate（SWR）的核心概念是「<a href="/blog/backend/knowledge-cards/ttl/" data-link-title="TTL" data-link-desc="說明資料過期時間如何影響快取新鮮度、成本與一致性">TTL</a> 過期後仍可立即回舊版本給使用者、同時背景發出 origin request 拉取新版本更新快取」。使用者體驗永遠快、新鮮度有「最多 stale <code>max-age + swr</code>」秒的上限。是天然的 <a href="/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">cache stampede</a> 緩解機制 — 把「TTL 過期那一刻 N 個請求同時打 origin」變成「TTL 過期那一刻 1 個請求打 origin、其他 N-1 個拿舊版」。</p>
<h2 id="概念位置">概念位置</h2>
<p>SWR 處於 HTTP cache 失效策略層、跟 <a href="/blog/backend/knowledge-cards/ttl/" data-link-title="TTL" data-link-desc="說明資料過期時間如何影響快取新鮮度、成本與一致性">TTL</a>、<a href="/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">Cache Invalidation</a> 是兄弟概念。TTL 定義「何時 expire」、SWR 定義「expire 之後仍允許用舊版的時間窗口」、cache invalidation 定義「主動清掉」。跟 <a href="/blog/backend/knowledge-cards/stale-if-error/" data-link-title="Stale-If-Error" data-link-desc="HTTP cache-control directive、origin 出錯時用舊版頂著、確保使用者拿到有效回應">Stale-If-Error</a> 屬不同維度但常一起配置 — SWR 處理過期、SIE 處理錯誤。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p><code>Cache-Control: max-age=60, stale-while-revalidate=600</code> 的服務行為：60 秒內 cache 完全新鮮、60-660 秒之間 client 仍立即拿到舊版（但 cache 已背景重整）、660 秒後才強制等 origin response。Cloudflare / Fastly / Varnish 都支援、瀏覽器 cache 也尊重這個 directive。</p>
<p>新鮮度敏感的場景（庫存、價格、權限）應限縮 SWR 範圍或關閉、保住 stale 風險的上限；blog 文章、商品描述、靜態 metadata 適合 SWR 降低 origin 壓力。</p>
<h2 id="設計責任">設計責任</h2>
<p>選擇 SWR window 要在「origin 壓力」跟「freshness budget」間取捨。Window 越長、origin 壓力越低、stale 容忍度越高；window 越短、freshness 越接近 TTL、但 cache stampede 緩解效果下降。常見組合是 <code>stale-while-revalidate</code> 設成 <code>max-age</code> 的 5-10 倍。資料新鮮度敏感場景要走白名單路徑、由 endpoint 個別 opt-in 開啟 SWR。</p>
]]></content:encoded></item><item><title>Circuit Breaker</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/circuit-breaker/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/circuit-breaker/</guid><description>&lt;p>Circuit breaker 的核心概念是「下游持續失敗時，暫時停止呼叫該下游」。它讓 application &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fail-fast/" data-link-title="Fail Fast" data-link-desc="說明已知無法完成時快速回應如何保護資源與上游判斷">fail fast&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">degradation&lt;/a>，降低每個 request 都等待同一個失效依賴的風險。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Circuit breaker 是失敗隔離工具。它通常搭配 &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/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/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">rate limit&lt;/a>、fallback 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a> 使用；目標是控制故障擴散，而非修復下游。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 circuit breaker 的訊號是下游錯誤率高、latency 飆升，並拖慢上游服務。推薦服務持續 timeout 時，商品頁可以短暫停止呼叫推薦，改顯示熱門商品。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Circuit breaker 要定義開啟條件、半開探測、恢復條件、fallback 行為與 &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/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics&lt;/a> 要一起調整。&lt;/p></description><content:encoded><![CDATA[<p>Circuit breaker 的核心概念是「下游持續失敗時，暫時停止呼叫該下游」。它讓 application <a href="/blog/backend/knowledge-cards/fail-fast/" data-link-title="Fail Fast" data-link-desc="說明已知無法完成時快速回應如何保護資源與上游判斷">fail fast</a>、使用 <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>，降低每個 request 都等待同一個失效依賴的風險。</p>
<h2 id="概念位置">概念位置</h2>
<p>Circuit breaker 是失敗隔離工具。它通常搭配 <a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout</a>、<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/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">rate limit</a>、fallback 與 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> 使用；目標是控制故障擴散，而非修復下游。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 circuit breaker 的訊號是下游錯誤率高、latency 飆升，並拖慢上游服務。推薦服務持續 timeout 時，商品頁可以短暫停止呼叫推薦，改顯示熱門商品。</p>
<h2 id="設計責任">設計責任</h2>
<p>Circuit breaker 要定義開啟條件、半開探測、恢復條件、fallback 行為與 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>。設計時要控制短暫波動對可用性的影響，因此門檻與 <a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics</a> 要一起調整。</p>
]]></content:encoded></item><item><title>Stale-If-Error</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/stale-if-error/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/stale-if-error/</guid><description>&lt;p>Stale-if-error（SIE）的核心概念是「cache 過期後若 origin 回 5xx 或不可達、用舊版本頂著、確保使用者仍能拿到回應」。是 cache 充當 fallback 的明示授權 — 把 &lt;a href="https://tarrragon.github.io/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 策略">origin protection&lt;/a> 從「降低 origin 流量」延伸到「origin 故障時保持服務」。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stale-while-revalidate/" data-link-title="Stale-While-Revalidate" data-link-desc="HTTP cache-control directive，cache 過期後仍立即回舊版、背景發出 origin request 拉取新版本更新快取">Stale-While-Revalidate&lt;/a> 屬不同維度但常一起配置 — SWR 處理過期、SIE 處理錯誤。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SIE 處於 HTTP cache 失效策略層、是 cache 從「降延遲工具」升級成「fallback 機制」的關鍵 directive。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ttl/" data-link-title="TTL" data-link-desc="說明資料過期時間如何影響快取新鮮度、成本與一致性">TTL&lt;/a>、&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> 是兄弟。觸發條件跟 SWR 不同：SWR 是「TTL 過期但 origin 正常」、SIE 是「origin 出錯」— 一個是 condition-driven、一個是 error-driven。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>&lt;code>Cache-Control: max-age=60, stale-if-error=86400&lt;/code> 的服務行為：origin 正常時、60 秒新鮮、之後正常 revalidate；origin 回 5xx 或網路不可達時、cache 在 86400 秒（1 天）內仍可用舊版本回應。Cloudflare / Fastly / Akamai 支援度因 vendor 而異、部分 vendor 有 origin shield 整合。&lt;/p>
&lt;p>電商商品頁、新聞文章、blog post 適合大 SIE window（origin 出事時舊版可用 1-7 天）；交易型 API、付款流程應該關閉 SIE — 在這類場景中、回 5xx 讓 client retry 比回 stale 安全。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>開啟 SIE 是明示「在 origin 故障期間、業務願意接受 stale data 換 availability」。Freshness-sensitive 場景要走白名單路徑、由 endpoint 個別 opt-in 開啟 SIE。SIE window 通常比 SWR 長（後者是常態、前者是故障 fallback）— 常見組合是 SIE 設一天、SWR 設十分鐘。同時搭配 origin 監控、確保 SIE 期間真實事故仍被察覺。&lt;/p></description><content:encoded><![CDATA[<p>Stale-if-error（SIE）的核心概念是「cache 過期後若 origin 回 5xx 或不可達、用舊版本頂著、確保使用者仍能拿到回應」。是 cache 充當 fallback 的明示授權 — 把 <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 策略">origin protection</a> 從「降低 origin 流量」延伸到「origin 故障時保持服務」。跟 <a href="/blog/backend/knowledge-cards/stale-while-revalidate/" data-link-title="Stale-While-Revalidate" data-link-desc="HTTP cache-control directive，cache 過期後仍立即回舊版、背景發出 origin request 拉取新版本更新快取">Stale-While-Revalidate</a> 屬不同維度但常一起配置 — SWR 處理過期、SIE 處理錯誤。</p>
<h2 id="概念位置">概念位置</h2>
<p>SIE 處於 HTTP cache 失效策略層、是 cache 從「降延遲工具」升級成「fallback 機制」的關鍵 directive。跟 <a href="/blog/backend/knowledge-cards/ttl/" data-link-title="TTL" data-link-desc="說明資料過期時間如何影響快取新鮮度、成本與一致性">TTL</a>、<a href="/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">Cache Invalidation</a> 是兄弟。觸發條件跟 SWR 不同：SWR 是「TTL 過期但 origin 正常」、SIE 是「origin 出錯」— 一個是 condition-driven、一個是 error-driven。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p><code>Cache-Control: max-age=60, stale-if-error=86400</code> 的服務行為：origin 正常時、60 秒新鮮、之後正常 revalidate；origin 回 5xx 或網路不可達時、cache 在 86400 秒（1 天）內仍可用舊版本回應。Cloudflare / Fastly / Akamai 支援度因 vendor 而異、部分 vendor 有 origin shield 整合。</p>
<p>電商商品頁、新聞文章、blog post 適合大 SIE window（origin 出事時舊版可用 1-7 天）；交易型 API、付款流程應該關閉 SIE — 在這類場景中、回 5xx 讓 client retry 比回 stale 安全。</p>
<h2 id="設計責任">設計責任</h2>
<p>開啟 SIE 是明示「在 origin 故障期間、業務願意接受 stale data 換 availability」。Freshness-sensitive 場景要走白名單路徑、由 endpoint 個別 opt-in 開啟 SIE。SIE window 通常比 SWR 長（後者是常態、前者是故障 fallback）— 常見組合是 SIE 設一天、SWR 設十分鐘。同時搭配 origin 監控、確保 SIE 期間真實事故仍被察覺。</p>
]]></content:encoded></item><item><title>Failover</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/failover/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/failover/</guid><description>&lt;p>Failover 的核心概念是「主要路徑失效時切換到備援路徑」。備援可以是另一個 instance、另一個 availability zone、另一個資料庫 replica、另一個服務供應商或簡化功能。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">Fallback Plan&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Failover 是可用性設計的一部分。它要處理健康判斷、切換觸發、資料一致性、DNS 或 load balancer 更新、連線重建與回切流程。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">Fallback Plan&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 failover 的訊號是單一節點、單一區域或單一供應商故障會造成停機。付款服務可以在主要供應商中斷時切到備援供應商，但要處理交易查詢、費率、風控與對帳差異。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Failover runbook 要定義觸發條件、切換步驟、資料檢查、回切條件與演練頻率。自動 failover 需要更嚴格的健康訊號，人工 failover 則需要清楚的決策權限。&lt;/p></description><content:encoded><![CDATA[<p>Failover 的核心概念是「主要路徑失效時切換到備援路徑」。備援可以是另一個 instance、另一個 availability zone、另一個資料庫 replica、另一個服務供應商或簡化功能。 可先對照 <a href="/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">Fallback Plan</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Failover 是可用性設計的一部分。它要處理健康判斷、切換觸發、資料一致性、DNS 或 load balancer 更新、連線重建與回切流程。 可先對照 <a href="/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">Fallback Plan</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 failover 的訊號是單一節點、單一區域或單一供應商故障會造成停機。付款服務可以在主要供應商中斷時切到備援供應商，但要處理交易查詢、費率、風控與對帳差異。</p>
<h2 id="設計責任">設計責任</h2>
<p>Failover runbook 要定義觸發條件、切換步驟、資料檢查、回切條件與演練頻率。自動 failover 需要更嚴格的健康訊號，人工 failover 則需要清楚的決策權限。</p>
]]></content:encoded></item><item><title>Leader Election</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/leader-election/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/leader-election/</guid><description>&lt;p>Leader election 的核心責任是「從一群對等節點選出單一主來執行某類獨佔工作（執行排程、接受寫入、coordinate cluster state）」。Leader 失效時、剩餘節點要在有限時間內選出新 leader。底層通常依賴 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consensus-protocol/" data-link-title="Consensus Protocol" data-link-desc="讓多個獨立節點在訊息可能延遲、丟失、亂序的網路下對單一決策達成一致的演算法">consensus protocol&lt;/a>（Raft / ZAB）保證選舉一致、確保任何時刻只有單一 leader（防範 split-brain）。是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-lock/" data-link-title="Distributed Lock" data-link-desc="跨機器跨 process 的互斥鎖、用 lease 機制處理 holder 失效">distributed lock&lt;/a> 在「服務角色互斥」這個情境的應用。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Leader election 處於分散式協調控制層、是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consensus-protocol/" data-link-title="Consensus Protocol" data-link-desc="讓多個獨立節點在訊息可能延遲、丟失、亂序的網路下對單一決策達成一致的演算法">consensus protocol&lt;/a> 三大責任（election / state machine replication / cluster membership）中最常被獨立使用的一支。常見實作載體：ZooKeeper ephemeral node、Etcd lease + revision、Consul session、Kubernetes lease object、Redis 加 fencing token 的近似實作。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>每個 cluster 同時間至多一個 leader 持有 election lease；leader 失效後典型 election timeout 在 150ms-500ms 之間（依 consensus 算法跟 cluster 大小）。應用情境包含：分散式排程器（Quartz cluster、Apache Airflow scheduler）、Kafka controller、PostgreSQL primary 選舉（Patroni）、Kubernetes controller manager / scheduler 的 leader-elect 機制。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Election timeout 太短會誤判（網路抖動觸發多餘的切換）、太長會延遲 failover。Fencing token 是必備設計 — 舊 leader 跟新 leader 並存的 split-brain 期間、用單調遞增 token 讓資源側拒絕舊 leader 的寫入。應用層接 leader election 要明確「在 follower 角色時做什麼」— 通常是 stand-by + 監控 election event、每個操作前主動檢查自己當前是否為 leader。&lt;/p></description><content:encoded><![CDATA[<p>Leader election 的核心責任是「從一群對等節點選出單一主來執行某類獨佔工作（執行排程、接受寫入、coordinate cluster state）」。Leader 失效時、剩餘節點要在有限時間內選出新 leader。底層通常依賴 <a href="/blog/backend/knowledge-cards/consensus-protocol/" data-link-title="Consensus Protocol" data-link-desc="讓多個獨立節點在訊息可能延遲、丟失、亂序的網路下對單一決策達成一致的演算法">consensus protocol</a>（Raft / ZAB）保證選舉一致、確保任何時刻只有單一 leader（防範 split-brain）。是 <a href="/blog/backend/knowledge-cards/distributed-lock/" data-link-title="Distributed Lock" data-link-desc="跨機器跨 process 的互斥鎖、用 lease 機制處理 holder 失效">distributed lock</a> 在「服務角色互斥」這個情境的應用。</p>
<h2 id="概念位置">概念位置</h2>
<p>Leader election 處於分散式協調控制層、是 <a href="/blog/backend/knowledge-cards/consensus-protocol/" data-link-title="Consensus Protocol" data-link-desc="讓多個獨立節點在訊息可能延遲、丟失、亂序的網路下對單一決策達成一致的演算法">consensus protocol</a> 三大責任（election / state machine replication / cluster membership）中最常被獨立使用的一支。常見實作載體：ZooKeeper ephemeral node、Etcd lease + revision、Consul session、Kubernetes lease object、Redis 加 fencing token 的近似實作。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>每個 cluster 同時間至多一個 leader 持有 election lease；leader 失效後典型 election timeout 在 150ms-500ms 之間（依 consensus 算法跟 cluster 大小）。應用情境包含：分散式排程器（Quartz cluster、Apache Airflow scheduler）、Kafka controller、PostgreSQL primary 選舉（Patroni）、Kubernetes controller manager / scheduler 的 leader-elect 機制。</p>
<h2 id="設計責任">設計責任</h2>
<p>Election timeout 太短會誤判（網路抖動觸發多餘的切換）、太長會延遲 failover。Fencing token 是必備設計 — 舊 leader 跟新 leader 並存的 split-brain 期間、用單調遞增 token 讓資源側拒絕舊 leader 的寫入。應用層接 leader election 要明確「在 follower 角色時做什麼」— 通常是 stand-by + 監控 election event、每個操作前主動檢查自己當前是否為 leader。</p>
]]></content:encoded></item><item><title>Liveness</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/health-check-liveness/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/health-check-liveness/</guid><description>&lt;p>Liveness 的核心概念是「判斷 instance 是否仍能維持基本存活」。平台用這類訊號決定是否重啟 instance；readiness 則決定 instance 是否接收正式流量。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">Health Check&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Liveness 關注 process 是否卡死、主 loop 是否停止、必要 runtime 是否失效。Readiness 關注接流量條件。兩者混用會讓平台在下游短暫故障時重啟正常 instance，造成更大波動。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">Health Check&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要分清 liveness 與 readiness 的訊號是部署或下游波動時 instance 被反覆重啟。資料庫短暫 timeout 應影響 readiness 或功能降級；process deadlock 才應觸發 liveness 失敗。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Liveness check 要簡單、穩定、成本低。Runbook 應說明 liveness fail 代表什麼、平台何時重啟、重啟後如何觀察 crash loop 與資源限制。&lt;/p></description><content:encoded><![CDATA[<p>Liveness 的核心概念是「判斷 instance 是否仍能維持基本存活」。平台用這類訊號決定是否重啟 instance；readiness 則決定 instance 是否接收正式流量。 可先對照 <a href="/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">Health Check</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Liveness 關注 process 是否卡死、主 loop 是否停止、必要 runtime 是否失效。Readiness 關注接流量條件。兩者混用會讓平台在下游短暫故障時重啟正常 instance，造成更大波動。 可先對照 <a href="/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">Health Check</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要分清 liveness 與 readiness 的訊號是部署或下游波動時 instance 被反覆重啟。資料庫短暫 timeout 應影響 readiness 或功能降級；process deadlock 才應觸發 liveness 失敗。</p>
<h2 id="設計責任">設計責任</h2>
<p>Liveness check 要簡單、穩定、成本低。Runbook 應說明 liveness fail 代表什麼、平台何時重啟、重啟後如何觀察 crash loop 與資源限制。</p>
]]></content:encoded></item><item><title>Log Schema</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/log-schema/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/log-schema/</guid><description>&lt;p>Log schema 的核心概念是「用穩定欄位描述 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&lt;/a> 事件」。結構化 log 應包含時間、等級、服務名稱、事件名稱、錯誤類型、&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>、&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>、tenant、資源 ID 與處理結果。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Log schema 是可觀測性的事件明細層。&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> 提供跨服務路徑，log 提供單一事件的上下文與細節。三者透過共享欄位（&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>、correlation id）互相連結。&lt;/p>
&lt;p>Log schema 的穩定性決定了查詢的效率 — 跨服務使用不同的欄位名稱記錄同一概念時，查詢需要窮舉所有變體。見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/log-schema/" data-link-title="4.1 log schema 與搜尋規劃" data-link-desc="整理 log 欄位、索引與搜尋策略">4.1 log schema 與搜尋規劃&lt;/a>。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 log schema 的訊號是事故時查詢依賴全文搜尋或逐台機器翻查。Checkout 失敗時，穩定欄位讓團隊用 order_id、payment_id、request_id 在秒級內追出同一流程的所有紀錄。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Log schema 要控制欄位名稱（跨服務統一）、錯誤分類（error type / error code 有界而非 free-form message）、敏感資料遮罩（API key / token / PII 在寫入前 redact）與索引成本（高 cardinality 欄位不全部建索引）。高流量服務還要管理 log level、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="說明觀測資料如何抽樣以控制成本並保留診斷能力">sampling&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;/p></description><content:encoded><![CDATA[<p>Log schema 的核心概念是「用穩定欄位描述 <a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a> 事件」。結構化 log 應包含時間、等級、服務名稱、事件名稱、錯誤類型、<a href="/blog/backend/knowledge-cards/request-id/" data-link-title="Request ID" data-link-desc="說明單次 request 的識別碼如何支援 log 搜尋與問題定位">request id</a>、<a href="/blog/backend/knowledge-cards/correlation-id/" data-link-title="Correlation ID" data-link-desc="說明跨事件或跨服務的關聯識別碼如何支援排障">correlation id</a>、tenant、資源 ID 與處理結果。</p>
<h2 id="概念位置">概念位置</h2>
<p>Log schema 是可觀測性的事件明細層。<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> 提供跨服務路徑，log 提供單一事件的上下文與細節。三者透過共享欄位（<a href="/blog/backend/knowledge-cards/trace-id/" data-link-title="Trace ID" data-link-desc="說明分散式追蹤中同一條呼叫路徑的識別碼">trace id</a>、correlation id）互相連結。</p>
<p>Log schema 的穩定性決定了查詢的效率 — 跨服務使用不同的欄位名稱記錄同一概念時，查詢需要窮舉所有變體。見 <a href="/blog/backend/04-observability/log-schema/" data-link-title="4.1 log schema 與搜尋規劃" data-link-desc="整理 log 欄位、索引與搜尋策略">4.1 log schema 與搜尋規劃</a>。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 log schema 的訊號是事故時查詢依賴全文搜尋或逐台機器翻查。Checkout 失敗時，穩定欄位讓團隊用 order_id、payment_id、request_id 在秒級內追出同一流程的所有紀錄。</p>
<h2 id="設計責任">設計責任</h2>
<p>Log schema 要控制欄位名稱（跨服務統一）、錯誤分類（error type / error code 有界而非 free-form message）、敏感資料遮罩（API key / token / PII 在寫入前 redact）與索引成本（高 cardinality 欄位不全部建索引）。高流量服務還要管理 log level、<a href="/blog/backend/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="說明觀測資料如何抽樣以控制成本並保留診斷能力">sampling</a>、<a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention</a> 與查詢成本。</p>
]]></content:encoded></item><item><title>Metrics</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/</guid><description>&lt;p>Metrics 的核心概念是「用可聚合數值描述系統行為的時間序列」。常見指標包括 request count、error rate、latency、&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>、CPU、memory、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&lt;/a> 使用量與 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Metrics 是趨勢觀測跟 &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/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&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>（跨服務路徑）互補：log 適合查單一事件的細節，trace 適合看一次 request 的路徑，metrics 適合回答「服務是否在變慢、錯誤是否在增加、容量是否接近上限」。&lt;/p>
&lt;p>Metrics 有三種基本型別：counter（累積計數、只增不減）、gauge（瞬間值、可增可減）、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/histogram/" data-link-title="Histogram" data-link-desc="說明 histogram 如何用分桶統計延遲、大小與分布">histogram&lt;/a>（分布、支援 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/percentile/" data-link-title="Percentile" data-link-desc="說明 p95 與 p99 如何描述長尾延遲與使用者體驗">percentile&lt;/a> 計算）。選錯型別會讓後面的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI&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> 跟 alert 建立在錯誤訊號上。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 metrics 的訊號是團隊需要在使用者回報前知道服務異常。Checkout p95 latency 上升、Redis &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/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a> lag 擴大，都應先從 metrics 看見。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Metrics 設計要選擇正確的型別（latency 用 histogram、request count 用 counter、connection pool size 用 gauge）跟有界的 label（service、method、status_code，排除 user_id / request_id）。重要指標要能對應 &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/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a>；高 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">cardinality&lt;/a> label 會推高儲存跟查詢成本。Metrics 的聚合查詢跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule&lt;/a> 設計見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">4.2 metrics basics&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Metrics 的核心概念是「用可聚合數值描述系統行為的時間序列」。常見指標包括 request count、error rate、latency、<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>、CPU、memory、<a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a> 使用量與 <a href="/blog/backend/knowledge-cards/cache-hit-rate/" data-link-title="Cache Hit Rate" data-link-desc="說明快取命中比例如何衡量加速效果與下游保護">cache hit rate</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Metrics 是趨勢觀測跟 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 的基礎。跟 <a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a>（事件明細）跟 <a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a>（跨服務路徑）互補：log 適合查單一事件的細節，trace 適合看一次 request 的路徑，metrics 適合回答「服務是否在變慢、錯誤是否在增加、容量是否接近上限」。</p>
<p>Metrics 有三種基本型別：counter（累積計數、只增不減）、gauge（瞬間值、可增可減）、<a href="/blog/backend/knowledge-cards/histogram/" data-link-title="Histogram" data-link-desc="說明 histogram 如何用分桶統計延遲、大小與分布">histogram</a>（分布、支援 <a href="/blog/backend/knowledge-cards/percentile/" data-link-title="Percentile" data-link-desc="說明 p95 與 p99 如何描述長尾延遲與使用者體驗">percentile</a> 計算）。選錯型別會讓後面的 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI</a>、<a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> 跟 alert 建立在錯誤訊號上。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 metrics 的訊號是團隊需要在使用者回報前知道服務異常。Checkout p95 latency 上升、Redis <a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout</a> 增加、<a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> lag 擴大，都應先從 metrics 看見。</p>
<h2 id="設計責任">設計責任</h2>
<p>Metrics 設計要選擇正確的型別（latency 用 histogram、request count 用 counter、connection pool size 用 gauge）跟有界的 label（service、method、status_code，排除 user_id / request_id）。重要指標要能對應 <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/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a>；高 <a href="/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">cardinality</a> label 會推高儲存跟查詢成本。Metrics 的聚合查詢跟 <a href="/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule</a> 設計見 <a href="/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">4.2 metrics basics</a>。</p>
]]></content:encoded></item><item><title>SLI / SLO</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/</guid><description>&lt;p>SLI / SLO 的核心概念是「用可量測訊號表達服務承諾」。SLI（Service Level Indicator）是服務品質指標 — 成功率、延遲、可用性；SLO（Service Level Objective）是這些指標的目標 — 99.9% request 在 300ms 內成功回應。SLO 的執行力來自 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SLI / SLO 把觀測資料轉成決策語言。單純看到 error rate 上升只能說明症狀；對照 SLO 後，團隊才能判斷是否需要暫停發版、啟動 incident、擴容或降級。SLO 不是「越高越好」— 99.999% 的 SLO 意味著幾乎沒有 &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;/p>
&lt;p>SLI 的設計起點是使用者旅程（checkout 是否成功、搜尋是否夠快），量測點選擇（edge / gateway / service）決定了 SLI 反映的是「使用者體驗」還是「基礎設施健康」。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 SLI / SLO 的訊號是服務重要性已經影響收入、合約或使用者信任。付款、登入、訂單建立與訊息送達通常需要不同 SLO，因為失敗代價不同。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>SLI 需要定義「什麼算 good request」的邊界（5xx 算 bad、4xx 通常不算）。SLO 需要定義目標值、量測窗口（30 天 rolling）跟 owner。SLO 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">burn rate&lt;/a> alerting 搭配使用，讓 &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/04-observability/sli-slo-signal/" data-link-title="4.6 SLI 量測與 SLO 訊號設計" data-link-desc="把可靠性目標的訊號從 metric 端設計好、餵給 6.6 SLO 政策">4.6 SLI/SLO 訊號設計&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>SLI / SLO 的核心概念是「用可量測訊號表達服務承諾」。SLI（Service Level Indicator）是服務品質指標 — 成功率、延遲、可用性；SLO（Service Level Objective）是這些指標的目標 — 99.9% request 在 300ms 內成功回應。SLO 的執行力來自 <a href="/blog/backend/knowledge-cards/error-budget/" data-link-title="Error Budget" data-link-desc="說明 SLO 允許的失敗額度如何影響發版與可靠性投入">error budget</a> — 預算耗盡就暫停發版。</p>
<h2 id="概念位置">概念位置</h2>
<p>SLI / SLO 把觀測資料轉成決策語言。單純看到 error rate 上升只能說明症狀；對照 SLO 後，團隊才能判斷是否需要暫停發版、啟動 incident、擴容或降級。SLO 不是「越高越好」— 99.999% 的 SLO 意味著幾乎沒有 <a href="/blog/backend/knowledge-cards/error-budget/" data-link-title="Error Budget" data-link-desc="說明 SLO 允許的失敗額度如何影響發版與可靠性投入">error budget</a> 做變更，反而限制了功能交付速度。</p>
<p>SLI 的設計起點是使用者旅程（checkout 是否成功、搜尋是否夠快），量測點選擇（edge / gateway / service）決定了 SLI 反映的是「使用者體驗」還是「基礎設施健康」。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 SLI / SLO 的訊號是服務重要性已經影響收入、合約或使用者信任。付款、登入、訂單建立與訊息送達通常需要不同 SLO，因為失敗代價不同。</p>
<h2 id="設計責任">設計責任</h2>
<p>SLI 需要定義「什麼算 good request」的邊界（5xx 算 bad、4xx 通常不算）。SLO 需要定義目標值、量測窗口（30 天 rolling）跟 owner。SLO 跟 <a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">burn rate</a> alerting 搭配使用，讓 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 反映使用者影響而非基礎設施噪音。完整設計見 <a href="/blog/backend/04-observability/sli-slo-signal/" data-link-title="4.6 SLI 量測與 SLO 訊號設計" data-link-desc="把可靠性目標的訊號從 metric 端設計好、餵給 6.6 SLO 政策">4.6 SLI/SLO 訊號設計</a>。</p>
]]></content:encoded></item><item><title>Trace Context</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/trace-context/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/trace-context/</guid><description>&lt;p>Trace context 的核心概念是「讓同一個 request 在跨服務呼叫中保持同一條追蹤線」。它包含 &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>（標識整條 trace）、span id（標識上游 span）與 trace flags（sampling 決策），讓下游服務建立的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/span/" data-link-title="Span" data-link-desc="說明 trace 中一段工作如何記錄耗時、狀態與關聯">span&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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Trace 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> 互補 — correlation id 關聯業務流程、trace context 關聯技術呼叫路徑。它的傳遞機制決定 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace&lt;/a> 能不能完整串起 — context 斷掉的地方，trace 就從「完整路徑」退化成需要人工拼接的局部紀錄。&lt;/p>
&lt;p>W3C Trace Context 標準定義了 HTTP 的傳遞格式：&lt;code>traceparent&lt;/code> header 帶 version + trace id + parent span id + trace flags，&lt;code>tracestate&lt;/code> header 帶 vendor-specific 附加資訊。OpenTelemetry SDK 預設使用 W3C 格式。部分 vendor 有自己的 header（Datadog 用 &lt;code>x-datadog-trace-id&lt;/code>、AWS X-Ray 用 &lt;code>X-Amzn-Trace-Id&lt;/code>），跨 vendor 時需要在 collector 層轉換。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 trace context 的訊號是延遲或錯誤跨越多個服務。Checkout 變慢時，trace context 讓 tracing 系統把 API gateway、order service、payment service、database query 的 span 串成一條路徑，在 waterfall view 中直接看到時間花在哪。&lt;/p>
&lt;p>Context 在 HTTP call、gRPC metadata、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a> message header 上傳遞。Queue 邊界的 propagation 比 HTTP 複雜 — consumer 可能在 producer 之後很久才消費，context 的時間跨度從毫秒擴大到分鐘。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Trace context 設計要處理四個邊界的傳遞：HTTP / gRPC（SDK auto-instrumentation 自動處理）、queue（需要 instrumented client 注入 message header）、thread pool（需要語言級的 context 傳播機制）、background job（需要在 job 啟動時建立 root span）。&lt;/p>
&lt;p>斷鏈的常見原因和修復策略見 &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">4.3 tracing 與 context link&lt;/a>。Sampling 決策跟 trace context 的關係見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/cardinality-cost-governance/#sampling-%e7%ad%96%e7%95%a5" data-link-title="4.7 Cardinality 治理與成本邊界" data-link-desc="把 metric / log / trace 的 cardinality 與成本作為平台一級治理議題">4.7 sampling 策略&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Trace context 的核心概念是「讓同一個 request 在跨服務呼叫中保持同一條追蹤線」。它包含 <a href="/blog/backend/knowledge-cards/trace-id/" data-link-title="Trace ID" data-link-desc="說明分散式追蹤中同一條呼叫路徑的識別碼">trace id</a>（標識整條 trace）、span id（標識上游 span）與 trace flags（sampling 決策），讓下游服務建立的 <a href="/blog/backend/knowledge-cards/span/" data-link-title="Span" data-link-desc="說明 trace 中一段工作如何記錄耗時、狀態與關聯">span</a> 能歸屬同一條 <a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Trace context 是跨服務診斷的關聯層，跟 <a href="/blog/backend/knowledge-cards/correlation-id/" data-link-title="Correlation ID" data-link-desc="說明跨事件或跨服務的關聯識別碼如何支援排障">correlation id</a> 互補 — correlation id 關聯業務流程、trace context 關聯技術呼叫路徑。它的傳遞機制決定 <a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a> 能不能完整串起 — context 斷掉的地方，trace 就從「完整路徑」退化成需要人工拼接的局部紀錄。</p>
<p>W3C Trace Context 標準定義了 HTTP 的傳遞格式：<code>traceparent</code> header 帶 version + trace id + parent span id + trace flags，<code>tracestate</code> header 帶 vendor-specific 附加資訊。OpenTelemetry SDK 預設使用 W3C 格式。部分 vendor 有自己的 header（Datadog 用 <code>x-datadog-trace-id</code>、AWS X-Ray 用 <code>X-Amzn-Trace-Id</code>），跨 vendor 時需要在 collector 層轉換。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 trace context 的訊號是延遲或錯誤跨越多個服務。Checkout 變慢時，trace context 讓 tracing 系統把 API gateway、order service、payment service、database query 的 span 串成一條路徑，在 waterfall view 中直接看到時間花在哪。</p>
<p>Context 在 HTTP call、gRPC metadata、<a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a> message header 上傳遞。Queue 邊界的 propagation 比 HTTP 複雜 — consumer 可能在 producer 之後很久才消費，context 的時間跨度從毫秒擴大到分鐘。</p>
<h2 id="設計責任">設計責任</h2>
<p>Trace context 設計要處理四個邊界的傳遞：HTTP / gRPC（SDK auto-instrumentation 自動處理）、queue（需要 instrumented client 注入 message header）、thread pool（需要語言級的 context 傳播機制）、background job（需要在 job 啟動時建立 root span）。</p>
<p>斷鏈的常見原因和修復策略見 <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 link</a>。Sampling 決策跟 trace context 的關係見 <a href="/blog/backend/04-observability/cardinality-cost-governance/#sampling-%e7%ad%96%e7%95%a5" data-link-title="4.7 Cardinality 治理與成本邊界" data-link-desc="把 metric / log / trace 的 cardinality 與成本作為平台一級治理議題">4.7 sampling 策略</a>。</p>
]]></content:encoded></item><item><title>Metric Cardinality</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/metric-cardinality/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/metric-cardinality/</guid><description>&lt;p>Metric cardinality 的核心概念是「指標 label 組合會產生多少條時間序列」。Label 越多、值越分散，時間序列越多，儲存、查詢與告警成本越高。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">Metrics&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cardinality 是 metrics 設計的成本邊界。&lt;code>status&lt;/code>、&lt;code>method&lt;/code>、&lt;code>endpoint&lt;/code> 常可接受；&lt;code>user_id&lt;/code>、&lt;code>order_id&lt;/code>、&lt;code>request_id&lt;/code> 通常會讓時間序列爆炸，應放進 log 或 trace。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">Metrics&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要檢查 cardinality 的訊號是 metrics 儲存成本上升、查詢變慢、Prometheus 或後端儲存壓力升高。把 tenant_id 放進每個高流量指標前，要先評估 tenant 數量與查詢目的。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Metrics 設計要先定義問題，再選 label。高基數資訊可以改用抽樣 log、trace attribute、top-N 指標或離線分析。&lt;/p></description><content:encoded><![CDATA[<p>Metric cardinality 的核心概念是「指標 label 組合會產生多少條時間序列」。Label 越多、值越分散，時間序列越多，儲存、查詢與告警成本越高。 可先對照 <a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">Metrics</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cardinality 是 metrics 設計的成本邊界。<code>status</code>、<code>method</code>、<code>endpoint</code> 常可接受；<code>user_id</code>、<code>order_id</code>、<code>request_id</code> 通常會讓時間序列爆炸，應放進 log 或 trace。 可先對照 <a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">Metrics</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要檢查 cardinality 的訊號是 metrics 儲存成本上升、查詢變慢、Prometheus 或後端儲存壓力升高。把 tenant_id 放進每個高流量指標前，要先評估 tenant 數量與查詢目的。</p>
<h2 id="設計責任">設計責任</h2>
<p>Metrics 設計要先定義問題，再選 label。高基數資訊可以改用抽樣 log、trace attribute、top-N 指標或離線分析。</p>
]]></content:encoded></item><item><title>Alert Runbook</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/alert-runbook/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/alert-runbook/</guid><description>&lt;p>Alert runbook 的核心概念是「每個需要人處理的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert&lt;/a> 都要附上下一步」。Alert 通知異常，runbook 則說明如何判斷影響、查哪些 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a>、執行哪些修復、何時升級。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Alert runbook 是可觀測性與操作流程的交界。告警搭配 &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;p>系統需要 alert runbook 的訊號是 on-call 收到告警後仍要臨場猜原因。&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/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">queue depth&lt;/a>、error rate、下游 latency、&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;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Runbook 要包含影響判斷、查詢連結、原因分類、立即緩解、回復驗證與升級路徑。每次事故後應更新 runbook，讓下一次處理更可重現。&lt;/p></description><content:encoded><![CDATA[<p>Alert runbook 的核心概念是「每個需要人處理的 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 都要附上下一步」。Alert 通知異常，runbook 則說明如何判斷影響、查哪些 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a>、執行哪些修復、何時升級。</p>
<h2 id="概念位置">概念位置</h2>
<p>Alert runbook 是可觀測性與操作流程的交界。告警搭配 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 後，事故處理可以從個人經驗轉成團隊流程。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 alert runbook 的訊號是 on-call 收到告警後仍要臨場猜原因。<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/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">queue depth</a>、error rate、下游 latency、<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> 數量與擴容或暫停流程。</p>
<h2 id="設計責任">設計責任</h2>
<p>Runbook 要包含影響判斷、查詢連結、原因分類、立即緩解、回復驗證與升級路徑。每次事故後應更新 runbook，讓下一次處理更可重現。</p>
]]></content:encoded></item><item><title>Authorization</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/</guid><description>&lt;p>Authorization 的核心概念是「判斷已識別主體是否能執行某個操作」。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication&lt;/a> 回答你是誰；authorization 回答你能做什麼、對哪個資源做、在什麼條件下做。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Authorization 是資料保護與操作安全的核心邊界。它可以用 role、permission、policy、&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>、resource owner 或 attribute-based rule 表達。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要授權模型的訊號是角色、資料範圍或操作風險開始分級。客服可以查看訂單狀態，但調整退款、下載 &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/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log&lt;/a>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>授權設計要定義主體、資源、操作、條件、拒絕原因與稽核欄位。測試要覆蓋跨 tenant 存取、低權限升級、高風險操作、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/function-level-authorization/" data-link-title="Function-Level Authorization" data-link-desc="說明功能操作本身也需要授權，不只資源 ID 需要授權">function-level authorization&lt;/a> 與資料匯出。&lt;/p></description><content:encoded><![CDATA[<p>Authorization 的核心概念是「判斷已識別主體是否能執行某個操作」。<a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication</a> 回答你是誰；authorization 回答你能做什麼、對哪個資源做、在什麼條件下做。</p>
<h2 id="概念位置">概念位置</h2>
<p>Authorization 是資料保護與操作安全的核心邊界。它可以用 role、permission、policy、<a href="/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">tenant boundary</a>、resource owner 或 attribute-based rule 表達。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要授權模型的訊號是角色、資料範圍或操作風險開始分級。客服可以查看訂單狀態，但調整退款、下載 <a href="/blog/backend/knowledge-cards/pii/" data-link-title="PII" data-link-desc="說明可識別個人的資料如何影響權限、遮罩、保留與稽核">PII</a> 或修改權限應需要更高權限與 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>授權設計要定義主體、資源、操作、條件、拒絕原因與稽核欄位。測試要覆蓋跨 tenant 存取、低權限升級、高風險操作、<a href="/blog/backend/knowledge-cards/function-level-authorization/" data-link-title="Function-Level Authorization" data-link-desc="說明功能操作本身也需要授權，不只資源 ID 需要授權">function-level authorization</a> 與資料匯出。</p>
]]></content:encoded></item><item><title>Data Masking</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/data-masking/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/data-masking/</guid><description>&lt;p>Data masking 的核心概念是「保留資料用途，同時降低敏感內容暴露」。遮罩可以套用在畫面、匯出檔案、log、客服後台、測試資料與分析資料集。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Data masking 是資料分級與最小揭露的實作方式。完整身份證、信用卡、電話、email、地址與 access token 都可能需要依角色、情境與用途做不同遮罩。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 data masking 的訊號是資料會離開原本受控邊界。客服查詢頁可能只顯示部分電話；報表匯出可能需要核准與遮罩；log 應避免記錄完整 token。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>遮罩策略要定義欄位分級、角色權限、匯出規則、測試資料產生與 audit。遮罩 helper 應集中管理，讓不同服務與語言維持一致規則。&lt;/p></description><content:encoded><![CDATA[<p>Data masking 的核心概念是「保留資料用途，同時降低敏感內容暴露」。遮罩可以套用在畫面、匯出檔案、log、客服後台、測試資料與分析資料集。 可先對照 <a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Data masking 是資料分級與最小揭露的實作方式。完整身份證、信用卡、電話、email、地址與 access token 都可能需要依角色、情境與用途做不同遮罩。 可先對照 <a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 data masking 的訊號是資料會離開原本受控邊界。客服查詢頁可能只顯示部分電話；報表匯出可能需要核准與遮罩；log 應避免記錄完整 token。</p>
<h2 id="設計責任">設計責任</h2>
<p>遮罩策略要定義欄位分級、角色權限、匯出規則、測試資料產生與 audit。遮罩 helper 應集中管理，讓不同服務與語言維持一致規則。</p>
]]></content:encoded></item><item><title>Secret Management</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/secret-management/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/secret-management/</guid><description>&lt;p>Secret management 的核心概念是「用受控流程管理可取得系統權限的秘密資料」。Secret 包含 API key、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a> password、JWT signing key、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS&lt;/a> private key、webhook secret 與第三方 credential。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Secret 是高風險操作能力。它們應集中放在受控系統中，並具備儲存位置、&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/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 secret management 的訊號是服務開始連接 database、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a>、雲端 API 或第三方支付。Webhook signing secret 洩漏後，攻擊者可能偽造進站事件；database 密碼洩漏後，資料存取邊界會失效。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Secret 管理要包含 &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;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>Secret management 的核心概念是「用受控流程管理可取得系統權限的秘密資料」。Secret 包含 API key、<a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a> password、JWT signing key、<a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS</a> private key、webhook secret 與第三方 credential。</p>
<h2 id="概念位置">概念位置</h2>
<p>Secret 是高風險操作能力。它們應集中放在受控系統中，並具備儲存位置、<a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">authorization</a>、使用範圍、輪替週期、撤銷流程與 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 secret management 的訊號是服務開始連接 database、<a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a>、雲端 API 或第三方支付。Webhook signing secret 洩漏後，攻擊者可能偽造進站事件；database 密碼洩漏後，資料存取邊界會失效。</p>
<h2 id="設計責任">設計責任</h2>
<p>Secret 管理要包含 <a href="/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">least privilege</a>、環境隔離、輪替演練、撤銷、版本管理與部署注入方式。<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">Runbook</a> 應說明疑似洩漏時如何停用、輪替、追查與恢復。</p>
]]></content:encoded></item><item><title>TLS / mTLS</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/tls-mtls/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/tls-mtls/</guid><description>&lt;p>TLS / mTLS 的核心概念是「保護資料在網路傳輸中的機密性、完整性與身份驗證」。TLS 通常驗證 server 並加密連線；mTLS 讓 client 與 server 彼此驗證憑證。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>TLS 是公開網路服務的基本傳輸保護。mTLS 常用在 service-to-service、內部 API、金融或高敏感資料傳輸場景，讓服務身份以憑證、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">authentication&lt;/a> 與網路邊界共同判斷。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 mTLS 的訊號是內部服務會傳遞付款、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pii/" data-link-title="PII" data-link-desc="說明可識別個人的資料如何影響權限、遮罩、保留與稽核">PII&lt;/a>、企業資料或高權限操作。服務身份與憑證輪替納入設計後，橫向移動風險可以被更早偵測與限制。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>TLS / mTLS 設計要包含 &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>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/acme-automation/" data-link-title="ACME Automation" data-link-desc="說明網站憑證如何透過 ACME 自動簽發與續期">ACME automation&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 root&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;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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert&lt;/a>、測試環境與故障排查。憑證、private key 與相關 credential 應納入 &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></description><content:encoded><![CDATA[<p>TLS / mTLS 的核心概念是「保護資料在網路傳輸中的機密性、完整性與身份驗證」。TLS 通常驗證 server 並加密連線；mTLS 讓 client 與 server 彼此驗證憑證。 可先對照 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>TLS 是公開網路服務的基本傳輸保護。mTLS 常用在 service-to-service、內部 API、金融或高敏感資料傳輸場景，讓服務身份以憑證、<a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">authentication</a> 與網路邊界共同判斷。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 mTLS 的訊號是內部服務會傳遞付款、<a href="/blog/backend/knowledge-cards/pii/" data-link-title="PII" data-link-desc="說明可識別個人的資料如何影響權限、遮罩、保留與稽核">PII</a>、企業資料或高權限操作。服務身份與憑證輪替納入設計後，橫向移動風險可以被更早偵測與限制。</p>
<h2 id="設計責任">設計責任</h2>
<p>TLS / mTLS 設計要包含 <a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">website certificate lifecycle</a>、<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-chain-trust/" data-link-title="Certificate Chain and Trust Root" data-link-desc="說明網站憑證鏈與信任根如何影響連線可用性與驗證結果">certificate chain and trust root</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>、<a href="/blog/backend/knowledge-cards/certificate-revocation/" data-link-title="Certificate Revocation" data-link-desc="說明憑證洩漏或誤發時如何撤銷並控制影響範圍">certificate revocation</a>、過期 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>、測試環境與故障排查。憑證、private key 與相關 credential 應納入 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">secret management</a>。</p>
]]></content:encoded></item><item><title>Audit Log</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/audit-log/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/audit-log/</guid><description>&lt;p>Audit log 的核心概念是「記錄誰在何時對哪個資源做了什麼高風險操作」。它支援事故調查、合規稽核、權限濫用追蹤與資料匯出責任判斷。 可先對照 &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;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Audit log 和一般 debug &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&lt;/a> 的責任不同。Debug log 幫助排查程式行為；audit log 保留安全與責任證據，因此需要更穩定的 schema、權限保護與保留策略。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 audit log 的訊號是操作會影響權限、金錢、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pii/" data-link-title="PII" data-link-desc="說明可識別個人的資料如何影響權限、遮罩、保留與稽核">PII&lt;/a>、合約或資料匯出。管理員調整角色、客服查看敏感資料、使用者匯出訂單、API key 輪替都應留下 audit record。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Audit log 要包含 actor、action、resource、result、reason、&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>、來源位置與時間。它也需要防竄改、查詢權限、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention&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></description><content:encoded><![CDATA[<p>Audit log 的核心概念是「記錄誰在何時對哪個資源做了什麼高風險操作」。它支援事故調查、合規稽核、權限濫用追蹤與資料匯出責任判斷。 可先對照 <a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">Log</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Audit log 和一般 debug <a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a> 的責任不同。Debug log 幫助排查程式行為；audit log 保留安全與責任證據，因此需要更穩定的 schema、權限保護與保留策略。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 audit log 的訊號是操作會影響權限、金錢、<a href="/blog/backend/knowledge-cards/pii/" data-link-title="PII" data-link-desc="說明可識別個人的資料如何影響權限、遮罩、保留與稽核">PII</a>、合約或資料匯出。管理員調整角色、客服查看敏感資料、使用者匯出訂單、API key 輪替都應留下 audit record。</p>
<h2 id="設計責任">設計責任</h2>
<p>Audit log 要包含 actor、action、resource、result、reason、<a href="/blog/backend/knowledge-cards/request-id/" data-link-title="Request ID" data-link-desc="說明單次 request 的識別碼如何支援 log 搜尋與問題定位">request id</a>、來源位置與時間。它也需要防竄改、查詢權限、<a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention</a> 與 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 規則。</p>
]]></content:encoded></item><item><title>Timeout</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/timeout/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/timeout/</guid><description>&lt;p>Timeout 的核心概念是「為一次等待設定時間上限」。後端服務等待 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a>、cache、&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/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP client&lt;/a> 呼叫、檔案系統或下游服務時，timeout 決定這次等待最久可以佔用多少資源。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Timeout 是資源保護與失敗分類的基礎。等待時間上限讓 connection、worker、goroutine、thread、memory 與 request slot 可以釋放，降低單一慢依賴擴散成整體容量問題的機率。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 timeout 設計的訊號是 request latency 長尾變高、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&lt;/a> 等待增加、worker 長時間卡住或使用者重複送出操作。Checkout 呼叫付款 API 時，timeout 要短到能保護使用者流程，也要長到能涵蓋正常付款延遲。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Timeout 要依呼叫目的分層設定。使用者 request、背景 job、database query、外部 API 與 &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> cleanup 應有不同時間上限；錯誤回報要標出 timeout 來源，讓 &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>Timeout 的核心概念是「為一次等待設定時間上限」。後端服務等待 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a>、cache、<a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a>、<a href="/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP client</a> 呼叫、檔案系統或下游服務時，timeout 決定這次等待最久可以佔用多少資源。</p>
<h2 id="概念位置">概念位置</h2>
<p>Timeout 是資源保護與失敗分類的基礎。等待時間上限讓 connection、worker、goroutine、thread、memory 與 request slot 可以釋放，降低單一慢依賴擴散成整體容量問題的機率。 可先對照 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 timeout 設計的訊號是 request latency 長尾變高、<a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a> 等待增加、worker 長時間卡住或使用者重複送出操作。Checkout 呼叫付款 API 時，timeout 要短到能保護使用者流程，也要長到能涵蓋正常付款延遲。</p>
<h2 id="設計責任">設計責任</h2>
<p>Timeout 要依呼叫目的分層設定。使用者 request、背景 job、database query、外部 API 與 <a href="/blog/backend/knowledge-cards/graceful-shutdown/" data-link-title="Graceful Shutdown" data-link-desc="說明服務停止前如何排空流量、完成工作與保存狀態">graceful shutdown</a> cleanup 應有不同時間上限；錯誤回報要標出 timeout 來源，讓 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 能定位是哪個依賴超時。</p>
]]></content:encoded></item><item><title>Deadline</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/deadline/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/deadline/</guid><description>&lt;p>Deadline 的核心概念是「整體操作必須完成的截止時間」。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">Timeout&lt;/a> 常是單一步驟的等待上限；deadline 則是整條 request、job 或 workflow 的總時間預算。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Deadline 讓多層呼叫共享同一份時間預算。入口 request 若只剩 200ms，下游呼叫就應知道剩餘時間，並選擇快速回應、&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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 deadline 的訊號是多個下游各自 &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>，導致整體時間遠超使用者可接受範圍。搜尋 API 需要查庫存、價格與推薦時，deadline 可以讓每個下游根據剩餘時間調整策略。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Deadline 要跨服務傳遞，並和 retry policy、fallback、cancellation 與 observability 對齊。&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/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace&lt;/a> 應記錄 deadline exceeded、剩餘時間與造成超時的依賴。&lt;/p></description><content:encoded><![CDATA[<p>Deadline 的核心概念是「整體操作必須完成的截止時間」。<a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">Timeout</a> 常是單一步驟的等待上限；deadline 則是整條 request、job 或 workflow 的總時間預算。</p>
<h2 id="概念位置">概念位置</h2>
<p>Deadline 讓多層呼叫共享同一份時間預算。入口 request 若只剩 200ms，下游呼叫就應知道剩餘時間，並選擇快速回應、<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> 或停止開始昂貴工作。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 deadline 的訊號是多個下游各自 <a href="/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">retry policy</a>，導致整體時間遠超使用者可接受範圍。搜尋 API 需要查庫存、價格與推薦時，deadline 可以讓每個下游根據剩餘時間調整策略。</p>
<h2 id="設計責任">設計責任</h2>
<p>Deadline 要跨服務傳遞，並和 retry policy、fallback、cancellation 與 observability 對齊。<a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">Log</a> 與 <a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a> 應記錄 deadline exceeded、剩餘時間與造成超時的依賴。</p>
]]></content:encoded></item><item><title>Exponential Backoff</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/exponential-backoff/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/exponential-backoff/</guid><description>&lt;p>Exponential backoff 的核心概念是「每次重試後把下一次等待時間按倍數拉長」。它讓系統在暫時性故障期間降低呼叫頻率，給下游恢復時間。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/facet-query/" data-link-title="Facet Query" data-link-desc="說明分面查詢如何提供分類統計與篩選體驗">Facet Query&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Backoff 是 retry policy 的節奏控制。固定間隔重試容易在下游尚未恢復時持續施壓；指數退避能讓重試從快速恢復逐漸轉成保守等待。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/facet-query/" data-link-title="Facet Query" data-link-desc="說明分面查詢如何提供分類統計與篩選體驗">Facet Query&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 backoff 的訊號是下游服務短暫 timeout、rate limit 或重啟。通知服務呼叫第三方簡訊 API 失敗時，可以先快速重試一次，再逐步拉長間隔，避免所有 worker 持續打向同一個故障 API。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Backoff 要搭配最大等待時間、最大重試次數、jitter 與錯誤分類。永久性錯誤應進入分類處理或 dead-letter；暫時性錯誤才適合退避重試。&lt;/p></description><content:encoded><![CDATA[<p>Exponential backoff 的核心概念是「每次重試後把下一次等待時間按倍數拉長」。它讓系統在暫時性故障期間降低呼叫頻率，給下游恢復時間。 可先對照 <a href="/blog/backend/knowledge-cards/facet-query/" data-link-title="Facet Query" data-link-desc="說明分面查詢如何提供分類統計與篩選體驗">Facet Query</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Backoff 是 retry policy 的節奏控制。固定間隔重試容易在下游尚未恢復時持續施壓；指數退避能讓重試從快速恢復逐漸轉成保守等待。 可先對照 <a href="/blog/backend/knowledge-cards/facet-query/" data-link-title="Facet Query" data-link-desc="說明分面查詢如何提供分類統計與篩選體驗">Facet Query</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 backoff 的訊號是下游服務短暫 timeout、rate limit 或重啟。通知服務呼叫第三方簡訊 API 失敗時，可以先快速重試一次，再逐步拉長間隔，避免所有 worker 持續打向同一個故障 API。</p>
<h2 id="設計責任">設計責任</h2>
<p>Backoff 要搭配最大等待時間、最大重試次數、jitter 與錯誤分類。永久性錯誤應進入分類處理或 dead-letter；暫時性錯誤才適合退避重試。</p>
]]></content:encoded></item><item><title>Jitter</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/jitter/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/jitter/</guid><description>&lt;p>Jitter 的核心概念是「在重試、排程或過期時間中加入隨機偏移」。它讓大量 client、worker 或 cache key 的動作分散發生，降低同一時間打向下游的尖峰。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Jitter 是反同步尖峰工具。Exponential backoff 只會拉長間隔；若所有 client 同時開始、使用同一公式，下一波重試仍可能同時抵達。Jitter 讓這些重試分散。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 jitter 的訊號是整點、部署後、cache 過期後或故障恢復後出現同步流量尖峰。大量 worker 在同一秒重試失敗 job，可能讓剛恢復的下游再次被打滿。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Jitter 要用在 retry delay、TTL、排程 job、polling interval 與 client reconnect。觀測上要看重試分布、尖峰流量與下游恢復時間。&lt;/p></description><content:encoded><![CDATA[<p>Jitter 的核心概念是「在重試、排程或過期時間中加入隨機偏移」。它讓大量 client、worker 或 cache key 的動作分散發生，降低同一時間打向下游的尖峰。 可先對照 <a href="/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">Least Privilege</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Jitter 是反同步尖峰工具。Exponential backoff 只會拉長間隔；若所有 client 同時開始、使用同一公式，下一波重試仍可能同時抵達。Jitter 讓這些重試分散。 可先對照 <a href="/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">Least Privilege</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 jitter 的訊號是整點、部署後、cache 過期後或故障恢復後出現同步流量尖峰。大量 worker 在同一秒重試失敗 job，可能讓剛恢復的下游再次被打滿。</p>
<h2 id="設計責任">設計責任</h2>
<p>Jitter 要用在 retry delay、TTL、排程 job、polling interval 與 client reconnect。觀測上要看重試分布、尖峰流量與下游恢復時間。</p>
]]></content:encoded></item><item><title>Retry Storm</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/retry-storm/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/retry-storm/</guid><description>&lt;p>Retry storm 的核心概念是「大量 client 或 worker 在故障期間同時重試，導致下游壓力急速放大」。重試本來用來提高成功率，但在高流量下可能把暫時性故障變成持續過載。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Retry storm 是 retry policy、timeout、backoff、jitter 與 rate limit 的共同風險。每一層服務若都自動重試，單一使用者 request 可能變成多倍下游呼叫。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要防止 retry storm 的訊號是下游錯誤率上升後，request 數、連線數與 CPU 同步上升。付款 API 短暫變慢時，所有 checkout instance 同時重試，可能讓付款 API 更難恢復。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Retry storm 防護要包含重試預算、backoff、jitter、rate limit、circuit breaker 與告警。Runbook 應能看出原始流量與重試流量的比例。&lt;/p></description><content:encoded><![CDATA[<p>Retry storm 的核心概念是「大量 client 或 worker 在故障期間同時重試，導致下游壓力急速放大」。重試本來用來提高成功率，但在高流量下可能把暫時性故障變成持續過載。 可先對照 <a href="/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Retry storm 是 retry policy、timeout、backoff、jitter 與 rate limit 的共同風險。每一層服務若都自動重試，單一使用者 request 可能變成多倍下游呼叫。 可先對照 <a href="/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要防止 retry storm 的訊號是下游錯誤率上升後，request 數、連線數與 CPU 同步上升。付款 API 短暫變慢時，所有 checkout instance 同時重試，可能讓付款 API 更難恢復。</p>
<h2 id="設計責任">設計責任</h2>
<p>Retry storm 防護要包含重試預算、backoff、jitter、rate limit、circuit breaker 與告警。Runbook 應能看出原始流量與重試流量的比例。</p>
]]></content:encoded></item><item><title>Thundering Herd</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/thundering-herd/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/thundering-herd/</guid><description>&lt;p>Thundering herd 的核心概念是「大量等待中的工作同時醒來並競爭同一個資源」。這種同步行為會製造瞬間尖峰，即使平均流量看起來可承受。 可先對照 &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;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Thundering herd 常出現在 cache 過期、鎖釋放、服務恢復、排程任務、client reconnect 與廣播通知。它和 cache stampede 相近，但範圍更廣，包含各種同時醒來與同時競爭。 可先對照 &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;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要處理 thundering herd 的訊號是故障恢復後流量突然高於平常數倍。WebSocket server 重啟後，所有 client 同時重連，可能讓 authentication、subscription 與 presence store 同時過載。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>常見策略包括 jitter、排隊、分批恢復、token bucket、singleflight、soft TTL 與 admission control。設計重點是把同步尖峰轉成可控分布。&lt;/p></description><content:encoded><![CDATA[<p>Thundering herd 的核心概念是「大量等待中的工作同時醒來並競爭同一個資源」。這種同步行為會製造瞬間尖峰，即使平均流量看起來可承受。 可先對照 <a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">Timeout</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Thundering herd 常出現在 cache 過期、鎖釋放、服務恢復、排程任務、client reconnect 與廣播通知。它和 cache stampede 相近，但範圍更廣，包含各種同時醒來與同時競爭。 可先對照 <a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">Timeout</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要處理 thundering herd 的訊號是故障恢復後流量突然高於平常數倍。WebSocket server 重啟後，所有 client 同時重連，可能讓 authentication、subscription 與 presence store 同時過載。</p>
<h2 id="設計責任">設計責任</h2>
<p>常見策略包括 jitter、排隊、分批恢復、token bucket、singleflight、soft TTL 與 admission control。設計重點是把同步尖峰轉成可控分布。</p>
]]></content:encoded></item><item><title>Transient Failure</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/transient-failure/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/transient-failure/</guid><description>&lt;p>Transient failure 的核心概念是「短時間內發生、稍後可能自行恢復的故障」。常見來源包含網路抖動、短暫 timeout、下游重啟、連線重建、rate limit 與 leader 切換。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tripwire/" data-link-title="Tripwire" data-link-desc="說明風險決策在條件變化時如何自動回到評估流程">Tripwire&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>暫時性故障適合用 retry、backoff、jitter、timeout 與 fallback 吸收。它和永久性錯誤不同；payload schema 錯、權限拒絕、業務狀態不允許通常需要分類處理，而非持續重試。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tripwire/" data-link-title="Tripwire" data-link-desc="說明風險決策在條件變化時如何自動回到評估流程">Tripwire&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要分辨 transient failure 的訊號是錯誤短暫升高後恢復。Redis failover 期間可能出現短暫連線錯誤；consumer 可以退避重試，但要控制重試量避免擴大故障。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>錯誤分類要標出 temporary、permanent、timeout、rate limited 與 dependency unavailable。Runbook 應說明哪些錯誤可以自動重試，哪些要進入 dead-letter 或人工處理。&lt;/p></description><content:encoded><![CDATA[<p>Transient failure 的核心概念是「短時間內發生、稍後可能自行恢復的故障」。常見來源包含網路抖動、短暫 timeout、下游重啟、連線重建、rate limit 與 leader 切換。 可先對照 <a href="/blog/backend/knowledge-cards/tripwire/" data-link-title="Tripwire" data-link-desc="說明風險決策在條件變化時如何自動回到評估流程">Tripwire</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>暫時性故障適合用 retry、backoff、jitter、timeout 與 fallback 吸收。它和永久性錯誤不同；payload schema 錯、權限拒絕、業務狀態不允許通常需要分類處理，而非持續重試。 可先對照 <a href="/blog/backend/knowledge-cards/tripwire/" data-link-title="Tripwire" data-link-desc="說明風險決策在條件變化時如何自動回到評估流程">Tripwire</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要分辨 transient failure 的訊號是錯誤短暫升高後恢復。Redis failover 期間可能出現短暫連線錯誤；consumer 可以退避重試，但要控制重試量避免擴大故障。</p>
<h2 id="設計責任">設計責任</h2>
<p>錯誤分類要標出 temporary、permanent、timeout、rate limited 與 dependency unavailable。Runbook 應說明哪些錯誤可以自動重試，哪些要進入 dead-letter 或人工處理。</p>
]]></content:encoded></item><item><title>Partial Failure</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/partial-failure/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/partial-failure/</guid><description>&lt;p>Partial failure 的核心概念是「系統的一部分失效，但其他部分仍然可以運作」。分散式系統很少整體同時成功或同時失敗；更常見的是某個區域、依賴、partition、consumer 或資料副本出問題。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Partial failure 是降級、fallback、circuit breaker、failover 與 observability 的共同前提。設計要先承認某些功能會局部失效，再定義核心功能如何保留。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 partial failure 設計的訊號是單一依賴失效會拖慢整體頁面。商品頁中推薦服務失效時，頁面仍可顯示商品資訊與購買按鈕；推薦區可以使用 fallback 或暫時空白。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Partial failure 設計要分清核心路徑與輔助路徑。觀測資料要能按依賴、功能區塊、tenant、region 或 endpoint 顯示故障範圍。&lt;/p></description><content:encoded><![CDATA[<p>Partial failure 的核心概念是「系統的一部分失效，但其他部分仍然可以運作」。分散式系統很少整體同時成功或同時失敗；更常見的是某個區域、依賴、partition、consumer 或資料副本出問題。 可先對照 <a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Partial failure 是降級、fallback、circuit breaker、failover 與 observability 的共同前提。設計要先承認某些功能會局部失效，再定義核心功能如何保留。 可先對照 <a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 partial failure 設計的訊號是單一依賴失效會拖慢整體頁面。商品頁中推薦服務失效時，頁面仍可顯示商品資訊與購買按鈕；推薦區可以使用 fallback 或暫時空白。</p>
<h2 id="設計責任">設計責任</h2>
<p>Partial failure 設計要分清核心路徑與輔助路徑。觀測資料要能按依賴、功能區塊、tenant、region 或 endpoint 顯示故障範圍。</p>
]]></content:encoded></item><item><title>Cascading Failure</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cascading-failure/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cascading-failure/</guid><description>&lt;p>Cascading failure 的核心概念是「局部故障沿著依賴關係擴散成更大範圍故障」。常見擴散路徑包括 timeout 太長、重試太多、connection pool 耗盡、queue 堆積、thread pool 被占滿與 fallback 過載。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cascading failure 是可靠性設計的主要防護目標。Timeout、backpressure、rate limit、circuit breaker、bulkhead 與 load shedding 都是在切斷擴散路徑。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要防 cascading failure 的訊號是原始故障在一個服務，症狀卻出現在多個上游。資料庫變慢後，API worker 卡住、queue lag 上升、retry 增加，最後登入與 checkout 都變慢。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>防護要從依賴圖出發，為每個下游設定 timeout、pool limit、重試預算與降級策略。Incident 後應檢查故障是如何跨服務擴散，而不只修復第一個壞掉的元件。&lt;/p></description><content:encoded><![CDATA[<p>Cascading failure 的核心概念是「局部故障沿著依賴關係擴散成更大範圍故障」。常見擴散路徑包括 timeout 太長、重試太多、connection pool 耗盡、queue 堆積、thread pool 被占滿與 fallback 過載。 可先對照 <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>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cascading failure 是可靠性設計的主要防護目標。Timeout、backpressure、rate limit、circuit breaker、bulkhead 與 load shedding 都是在切斷擴散路徑。 可先對照 <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>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要防 cascading failure 的訊號是原始故障在一個服務，症狀卻出現在多個上游。資料庫變慢後，API worker 卡住、queue lag 上升、retry 增加，最後登入與 checkout 都變慢。</p>
<h2 id="設計責任">設計責任</h2>
<p>防護要從依賴圖出發，為每個下游設定 timeout、pool limit、重試預算與降級策略。Incident 後應檢查故障是如何跨服務擴散，而不只修復第一個壞掉的元件。</p>
]]></content:encoded></item><item><title>Load Shedding</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/load-shedding/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/load-shedding/</guid><description>&lt;p>Load shedding 的核心概念是「在過載時主動丟棄或拒絕部分工作」。它用有限失敗保護核心能力，避免所有工作一起排隊到超時。 可先對照 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Load shedding 是過載保護工具。它和 rate limit、backpressure、degradation、priority queue 與 admission control 相關；重點是先定義哪些工作可以被拒絕，哪些工作需要保留。 可先對照 &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>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 load shedding 的訊號是流量尖峰超過服務容量。活動期間可以拒絕低優先的推薦刷新、延後報表產生，保留下單、付款與資料保存。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Load shedding 要定義優先級、拒絕回應、重試建議、告警與使用者體驗。觀測上要記錄 shed count、原因、受影響 endpoint 與核心路徑是否恢復。&lt;/p></description><content:encoded><![CDATA[<p>Load shedding 的核心概念是「在過載時主動丟棄或拒絕部分工作」。它用有限失敗保護核心能力，避免所有工作一起排隊到超時。 可先對照 <a href="/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">Load Test</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Load shedding 是過載保護工具。它和 rate limit、backpressure、degradation、priority queue 與 admission control 相關；重點是先定義哪些工作可以被拒絕，哪些工作需要保留。 可先對照 <a href="/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">Load Test</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 load shedding 的訊號是流量尖峰超過服務容量。活動期間可以拒絕低優先的推薦刷新、延後報表產生，保留下單、付款與資料保存。</p>
<h2 id="設計責任">設計責任</h2>
<p>Load shedding 要定義優先級、拒絕回應、重試建議、告警與使用者體驗。觀測上要記錄 shed count、原因、受影響 endpoint 與核心路徑是否恢復。</p>
]]></content:encoded></item><item><title>Token Bucket</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/token-bucket/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/token-bucket/</guid><description>&lt;p>Token bucket 的核心概念是「用可累積的 token 表示可使用配額」。每次操作消耗 token，系統按固定速率補充 token；bucket 容量決定可容忍的短暫 burst。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/token-revocation/" data-link-title="Token Revocation" data-link-desc="說明事件中如何撤銷 token，縮短可利用窗口">Token Revocation&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Token bucket 常用於 rate limit、retry budget、API quota、worker admission 與下游保護。它同時表達平均速率與短暫尖峰容忍度。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/token-revocation/" data-link-title="Token Revocation" data-link-desc="說明事件中如何撤銷 token，縮短可利用窗口">Token Revocation&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 token bucket 的訊號是流量有短暫尖峰，但仍需要限制長期平均使用量。第三方 API 每秒可處理固定請求量時，worker 可以用 token bucket 控制呼叫速度。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Token bucket 要定義補充速率、容量、消耗單位、超限行為與觀測欄位。多 tenant 系統還要區分全域 bucket 與 tenant bucket，保護公平性。&lt;/p></description><content:encoded><![CDATA[<p>Token bucket 的核心概念是「用可累積的 token 表示可使用配額」。每次操作消耗 token，系統按固定速率補充 token；bucket 容量決定可容忍的短暫 burst。 可先對照 <a href="/blog/backend/knowledge-cards/token-revocation/" data-link-title="Token Revocation" data-link-desc="說明事件中如何撤銷 token，縮短可利用窗口">Token Revocation</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Token bucket 常用於 rate limit、retry budget、API quota、worker admission 與下游保護。它同時表達平均速率與短暫尖峰容忍度。 可先對照 <a href="/blog/backend/knowledge-cards/token-revocation/" data-link-title="Token Revocation" data-link-desc="說明事件中如何撤銷 token，縮短可利用窗口">Token Revocation</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 token bucket 的訊號是流量有短暫尖峰，但仍需要限制長期平均使用量。第三方 API 每秒可處理固定請求量時，worker 可以用 token bucket 控制呼叫速度。</p>
<h2 id="設計責任">設計責任</h2>
<p>Token bucket 要定義補充速率、容量、消耗單位、超限行為與觀測欄位。多 tenant 系統還要區分全域 bucket 與 tenant bucket，保護公平性。</p>
]]></content:encoded></item><item><title>Dependency Isolation</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/dependency-isolation/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/dependency-isolation/</guid><description>&lt;p>Dependency isolation 的核心概念是「讓不同下游依賴使用可分開限制的資源」。如果所有依賴共用同一個 worker pool、connection pool 或 queue，單一下游變慢可能耗盡整個服務的處理能力。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/deployment-contract/" data-link-title="Deployment Contract" data-link-desc="說明服務與部署平台之間的生命週期約定">Deployment Contract&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Dependency isolation 是防止 cascading failure 的結構性設計。它可以透過獨立 pool、獨立 queue、bulkhead、timeout、rate limit 與 circuit breaker 實作。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/deployment-contract/" data-link-title="Deployment Contract" data-link-desc="說明服務與部署平台之間的生命週期約定">Deployment Contract&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 dependency isolation 的訊號是某個低優先下游變慢後，高優先流程也跟著變慢。報表服務查詢很慢時，應讓它只耗用報表專用資源，checkout 的 database pool 則保留給核心交易流程。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>依賴隔離要先標出核心路徑、輔助路徑與共享資源。觀測上要能按依賴查看 pool 使用量、queue depth、timeout 與錯誤率。&lt;/p></description><content:encoded><![CDATA[<p>Dependency isolation 的核心概念是「讓不同下游依賴使用可分開限制的資源」。如果所有依賴共用同一個 worker pool、connection pool 或 queue，單一下游變慢可能耗盡整個服務的處理能力。 可先對照 <a href="/blog/backend/knowledge-cards/deployment-contract/" data-link-title="Deployment Contract" data-link-desc="說明服務與部署平台之間的生命週期約定">Deployment Contract</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Dependency isolation 是防止 cascading failure 的結構性設計。它可以透過獨立 pool、獨立 queue、bulkhead、timeout、rate limit 與 circuit breaker 實作。 可先對照 <a href="/blog/backend/knowledge-cards/deployment-contract/" data-link-title="Deployment Contract" data-link-desc="說明服務與部署平台之間的生命週期約定">Deployment Contract</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 dependency isolation 的訊號是某個低優先下游變慢後，高優先流程也跟著變慢。報表服務查詢很慢時，應讓它只耗用報表專用資源，checkout 的 database pool 則保留給核心交易流程。</p>
<h2 id="設計責任">設計責任</h2>
<p>依賴隔離要先標出核心路徑、輔助路徑與共享資源。觀測上要能按依賴查看 pool 使用量、queue depth、timeout 與錯誤率。</p>
]]></content:encoded></item><item><title>Bulkhead</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/bulkhead/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/bulkhead/</guid><description>&lt;p>Bulkhead 的核心概念是「把服務資源分成彼此隔離的艙室」。某個艙室過載或失效時，其他艙室仍保留處理能力。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">Burn Rate&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Bulkhead 是 dependency isolation 的具體模式。它常用在 thread pool、connection pool、queue、worker group、tenant capacity 與不同優先級工作。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">Burn Rate&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 bulkhead 的訊號是單一功能或 tenant 可以拖垮整體服務。大量報表匯出可以放到獨立 worker pool，避免它佔滿處理登入、查詢與付款的資源。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Bulkhead 設計要定義分艙邊界、容量、排隊策略、拒絕行為與告警。容量切分太細會降低利用率，切分太粗會失去隔離效果。&lt;/p></description><content:encoded><![CDATA[<p>Bulkhead 的核心概念是「把服務資源分成彼此隔離的艙室」。某個艙室過載或失效時，其他艙室仍保留處理能力。 可先對照 <a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">Burn Rate</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Bulkhead 是 dependency isolation 的具體模式。它常用在 thread pool、connection pool、queue、worker group、tenant capacity 與不同優先級工作。 可先對照 <a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">Burn Rate</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 bulkhead 的訊號是單一功能或 tenant 可以拖垮整體服務。大量報表匯出可以放到獨立 worker pool，避免它佔滿處理登入、查詢與付款的資源。</p>
<h2 id="設計責任">設計責任</h2>
<p>Bulkhead 設計要定義分艙邊界、容量、排隊策略、拒絕行為與告警。容量切分太細會降低利用率，切分太粗會失去隔離效果。</p>
]]></content:encoded></item><item><title>Fallback</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/fallback/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/fallback/</guid><description>&lt;p>Fallback 的核心概念是「主要路徑失敗時使用替代結果或替代流程」。Fallback 可以是 cached data、預設值、簡化頁面、備援服務、延後處理或人工流程。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partial-failure/" data-link-title="Partial Failure" data-link-desc="說明分散式系統中部分依賴失效時如何保留整體可用性">Partial Failure&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Fallback 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partial-failure/" data-link-title="Partial Failure" data-link-desc="說明分散式系統中部分依賴失效時如何保留整體可用性">partial failure&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/stale-data/" data-link-title="Stale Data" data-link-desc="說明過期資料在快取、replica 與衍生資料中的產品影響">stale data&lt;/a>、成本增加、結果品質下降或邏輯分歧。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 fallback 的訊號是輔助依賴失敗時仍可提供核心價值。推薦服務失敗時，商品頁可以顯示熱門商品；付款服務失敗時，fallback 可能只允許保留訂單而暫停付款。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Fallback 要明確標出使用條件、資料新鮮度、使用者文案、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert&lt;/a> 與恢復條件。Fallback 路徑本身也需要測試與容量評估，因為事故時它會突然承受大量流量。&lt;/p></description><content:encoded><![CDATA[<p>Fallback 的核心概念是「主要路徑失敗時使用替代結果或替代流程」。Fallback 可以是 cached data、預設值、簡化頁面、備援服務、延後處理或人工流程。 可先對照 <a href="/blog/backend/knowledge-cards/partial-failure/" data-link-title="Partial Failure" data-link-desc="說明分散式系統中部分依賴失效時如何保留整體可用性">Partial Failure</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Fallback 是 <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/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">degradation</a> 設計的一部分。它能保留使用者流程，但也可能帶來 <a href="/blog/backend/knowledge-cards/stale-data/" data-link-title="Stale Data" data-link-desc="說明過期資料在快取、replica 與衍生資料中的產品影響">stale data</a>、成本增加、結果品質下降或邏輯分歧。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 fallback 的訊號是輔助依賴失敗時仍可提供核心價值。推薦服務失敗時，商品頁可以顯示熱門商品；付款服務失敗時，fallback 可能只允許保留訂單而暫停付款。</p>
<h2 id="設計責任">設計責任</h2>
<p>Fallback 要明確標出使用條件、資料新鮮度、使用者文案、<a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 與恢復條件。Fallback 路徑本身也需要測試與容量評估，因為事故時它會突然承受大量流量。</p>
]]></content:encoded></item><item><title>Fail Fast</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/fail-fast/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/fail-fast/</guid><description>&lt;p>Fail fast 的核心概念是「已知當前操作無法成功時，快速回應明確失敗」。它讓上游不用等待到 timeout，也讓系統保留資源給仍可能成功的工作。 可先對照 &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;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Fail fast 常和 circuit breaker、validation、dependency health、rate limit 與 load shedding 搭配。它把已知會失敗的等待轉成可分類錯誤，讓上游可以選擇 fallback、重試或停止流程。 可先對照 &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;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 fail fast 的訊號是下游已知中斷，但上游仍持續等待。若 payment provider 已進入 circuit open，checkout 可以立即回應「付款暫停」或保留訂單，讓 request 快速進入明確結果。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Fail fast 要提供清楚錯誤分類與使用者回應。對內錯誤要能區分 validation failure、dependency unavailable、quota exceeded 與 circuit open；對外回應要避免暴露敏感內部細節。&lt;/p></description><content:encoded><![CDATA[<p>Fail fast 的核心概念是「已知當前操作無法成功時，快速回應明確失敗」。它讓上游不用等待到 timeout，也讓系統保留資源給仍可能成功的工作。 可先對照 <a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">Failover</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Fail fast 常和 circuit breaker、validation、dependency health、rate limit 與 load shedding 搭配。它把已知會失敗的等待轉成可分類錯誤，讓上游可以選擇 fallback、重試或停止流程。 可先對照 <a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">Failover</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 fail fast 的訊號是下游已知中斷，但上游仍持續等待。若 payment provider 已進入 circuit open，checkout 可以立即回應「付款暫停」或保留訂單，讓 request 快速進入明確結果。</p>
<h2 id="設計責任">設計責任</h2>
<p>Fail fast 要提供清楚錯誤分類與使用者回應。對內錯誤要能區分 validation failure、dependency unavailable、quota exceeded 與 circuit open；對外回應要避免暴露敏感內部細節。</p>
]]></content:encoded></item><item><title>Retry Budget</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/retry-budget/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/retry-budget/</guid><description>&lt;p>Retry budget 的核心概念是「把重試量限制在系統可承受的預算內」。它承認重試會消耗下游容量，因此重試規則需要納入共享容量與全局保護。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Retry budget 是 retry storm 的防護工具。它可以用比例、token bucket、error budget、全域配額或每個 client 配額實作，讓重試量和正常流量維持合理比例。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 retry budget 的訊號是下游故障時重試流量比正常流量更大。搜尋服務 5% request timeout 時，如果所有 client 重試三次，下游實際壓力可能快速翻倍。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Retry budget 要定義消耗規則、補充規則、超出預算後的行為與告警。觀測上要分開顯示原始 request、retry request、retry success 與 retry failure。&lt;/p></description><content:encoded><![CDATA[<p>Retry budget 的核心概念是「把重試量限制在系統可承受的預算內」。它承認重試會消耗下游容量，因此重試規則需要納入共享容量與全局保護。 可先對照 <a href="/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">Retry Policy</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Retry budget 是 retry storm 的防護工具。它可以用比例、token bucket、error budget、全域配額或每個 client 配額實作，讓重試量和正常流量維持合理比例。 可先對照 <a href="/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">Retry Policy</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 retry budget 的訊號是下游故障時重試流量比正常流量更大。搜尋服務 5% request timeout 時，如果所有 client 重試三次，下游實際壓力可能快速翻倍。</p>
<h2 id="設計責任">設計責任</h2>
<p>Retry budget 要定義消耗規則、補充規則、超出預算後的行為與告警。觀測上要分開顯示原始 request、retry request、retry success 與 retry failure。</p>
]]></content:encoded></item><item><title>Prefetch</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/prefetch/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/prefetch/</guid><description>&lt;p>Prefetch 的核心概念是「限制 consumer 一次可以持有多少尚未 ack 的訊息」。它讓 broker 控制訊息分派速度，避免單一 consumer 拿走過多工作。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/probe/" data-link-title="Probe" data-link-desc="說明平台如何透過 probe 判斷服務狀態與接流量條件">Probe&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Prefetch 是 broker backpressure 與 consumer fairness 的工具。Prefetch 太高會讓慢 consumer 囤積訊息；prefetch 太低會降低吞吐，讓 consumer 閒置等待。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/probe/" data-link-title="Probe" data-link-desc="說明平台如何透過 probe 判斷服務狀態與接流量條件">Probe&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要調整 prefetch 的訊號是 unacked messages 偏高、某些 consumer 忙碌但其他 consumer 閒置，或單筆工作耗時差異很大。影片轉檔工作長短差異大時，較低 prefetch 能讓工作更公平分配。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Prefetch 要和 handler 耗時、並發數、ack timeout、下游容量與 retry policy 一起調整。觀測上要看 unacked messages、consumer utilization、處理耗時與 redelivery。&lt;/p></description><content:encoded><![CDATA[<p>Prefetch 的核心概念是「限制 consumer 一次可以持有多少尚未 ack 的訊息」。它讓 broker 控制訊息分派速度，避免單一 consumer 拿走過多工作。 可先對照 <a href="/blog/backend/knowledge-cards/probe/" data-link-title="Probe" data-link-desc="說明平台如何透過 probe 判斷服務狀態與接流量條件">Probe</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Prefetch 是 broker backpressure 與 consumer fairness 的工具。Prefetch 太高會讓慢 consumer 囤積訊息；prefetch 太低會降低吞吐，讓 consumer 閒置等待。 可先對照 <a href="/blog/backend/knowledge-cards/probe/" data-link-title="Probe" data-link-desc="說明平台如何透過 probe 判斷服務狀態與接流量條件">Probe</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要調整 prefetch 的訊號是 unacked messages 偏高、某些 consumer 忙碌但其他 consumer 閒置，或單筆工作耗時差異很大。影片轉檔工作長短差異大時，較低 prefetch 能讓工作更公平分配。</p>
<h2 id="設計責任">設計責任</h2>
<p>Prefetch 要和 handler 耗時、並發數、ack timeout、下游容量與 retry policy 一起調整。觀測上要看 unacked messages、consumer utilization、處理耗時與 redelivery。</p>
]]></content:encoded></item><item><title>In-Flight Message</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/in-flight-message/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/in-flight-message/</guid><description>&lt;p>In-flight message 的核心概念是「已經交給 consumer，但尚未完成 ack 或 nack 的訊息」。這些訊息正在處理中，broker 通常會把它們和可投遞訊息分開管理。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>In-flight 狀態是 consumer lifecycle 的中間階段。它連接 prefetch、ack timeout、redelivery、consumer crash 與 graceful shutdown。In-flight 訊息越多，代表系統有越多未完成副作用。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要觀察 in-flight 訊息的訊號是部署或故障期間出現大量重複處理。Consumer 收到訂單事件後還沒 ack 就 crash，broker 可能重新投遞該事件，因此 handler 需要 idempotency。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Consumer shutdown 要先停止取新訊息，再處理或交回 in-flight 訊息。Runbook 應能看到 in-flight 數量、最久處理時間、redelivery 次數與 consumer crash 紀錄。&lt;/p></description><content:encoded><![CDATA[<p>In-flight message 的核心概念是「已經交給 consumer，但尚未完成 ack 或 nack 的訊息」。這些訊息正在處理中，broker 通常會把它們和可投遞訊息分開管理。 可先對照 <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>。</p>
<h2 id="概念位置">概念位置</h2>
<p>In-flight 狀態是 consumer lifecycle 的中間階段。它連接 prefetch、ack timeout、redelivery、consumer crash 與 graceful shutdown。In-flight 訊息越多，代表系統有越多未完成副作用。 可先對照 <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>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要觀察 in-flight 訊息的訊號是部署或故障期間出現大量重複處理。Consumer 收到訂單事件後還沒 ack 就 crash，broker 可能重新投遞該事件，因此 handler 需要 idempotency。</p>
<h2 id="設計責任">設計責任</h2>
<p>Consumer shutdown 要先停止取新訊息，再處理或交回 in-flight 訊息。Runbook 應能看到 in-flight 數量、最久處理時間、redelivery 次數與 consumer crash 紀錄。</p>
]]></content:encoded></item><item><title>Unacked Message</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/unacked-message/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/unacked-message/</guid><description>&lt;p>Unacked message 的核心概念是「broker 已投遞出去，但尚未收到 consumer ack 的訊息」。它通常代表訊息正在處理、consumer 卡住、ack 遺失或 handler 耗時過長。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/unrestricted-resource-consumption/" data-link-title="Unrestricted Resource Consumption" data-link-desc="說明缺少資源限制如何讓 API 被濫用或拖垮">Unrestricted Resource Consumption&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Unacked message 是 queue health 的重要訊號。Queue depth 告訴團隊有多少訊息等著處理；unacked 則告訴團隊有多少訊息卡在 consumer 手上。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/unrestricted-resource-consumption/" data-link-title="Unrestricted Resource Consumption" data-link-desc="說明缺少資源限制如何讓 API 被濫用或拖垮">Unrestricted Resource Consumption&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要追蹤 unacked 的訊號是 queue 看起來已分派，但產品結果仍然延遲。寄信 consumer 拿到大量訊息後卡在外部 SMTP API，queue ready 數不高，但 unacked 數會持續上升。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Unacked 告警要和 prefetch、handler timeout、consumer health 與 downstream latency 一起看。Runbook 應說明何時重啟 consumer、何時調整 prefetch、何時暫停投遞。&lt;/p></description><content:encoded><![CDATA[<p>Unacked message 的核心概念是「broker 已投遞出去，但尚未收到 consumer ack 的訊息」。它通常代表訊息正在處理、consumer 卡住、ack 遺失或 handler 耗時過長。 可先對照 <a href="/blog/backend/knowledge-cards/unrestricted-resource-consumption/" data-link-title="Unrestricted Resource Consumption" data-link-desc="說明缺少資源限制如何讓 API 被濫用或拖垮">Unrestricted Resource Consumption</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Unacked message 是 queue health 的重要訊號。Queue depth 告訴團隊有多少訊息等著處理；unacked 則告訴團隊有多少訊息卡在 consumer 手上。 可先對照 <a href="/blog/backend/knowledge-cards/unrestricted-resource-consumption/" data-link-title="Unrestricted Resource Consumption" data-link-desc="說明缺少資源限制如何讓 API 被濫用或拖垮">Unrestricted Resource Consumption</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要追蹤 unacked 的訊號是 queue 看起來已分派，但產品結果仍然延遲。寄信 consumer 拿到大量訊息後卡在外部 SMTP API，queue ready 數不高，但 unacked 數會持續上升。</p>
<h2 id="設計責任">設計責任</h2>
<p>Unacked 告警要和 prefetch、handler timeout、consumer health 與 downstream latency 一起看。Runbook 應說明何時重啟 consumer、何時調整 prefetch、何時暫停投遞。</p>
]]></content:encoded></item><item><title>Redelivery</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/redelivery/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/redelivery/</guid><description>&lt;p>Redelivery 的核心概念是「broker 把先前投遞過的訊息再次交給 consumer」。常見原因包含 consumer crash、ack timeout、nack requeue、連線中斷或 broker failover。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/release-freeze/" data-link-title="Release Freeze" data-link-desc="說明高風險期間如何以凍結策略保護正式環境">Release Freeze&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Redelivery 是 at-least-once delivery 的正常結果。它要求 consumer 具備 idempotency、處理紀錄、狀態檢查與可觀測欄位，讓重複進入的訊息維持同一個業務結果。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/release-freeze/" data-link-title="Release Freeze" data-link-desc="說明高風險期間如何以凍結策略保護正式環境">Release Freeze&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要關注 redelivery 的訊號是同一事件被處理多次、retry count 上升或 dead-letter 增加。付款成功事件 redelivery 時，出貨 consumer 要能辨識該付款已處理。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Redelivery 指標要記錄原因、次數與事件 ID。Consumer 測試應覆蓋首次處理、處理中 crash、redelivery 後命中已處理紀錄與永久失敗進 dead-letter。&lt;/p></description><content:encoded><![CDATA[<p>Redelivery 的核心概念是「broker 把先前投遞過的訊息再次交給 consumer」。常見原因包含 consumer crash、ack timeout、nack requeue、連線中斷或 broker failover。 可先對照 <a href="/blog/backend/knowledge-cards/release-freeze/" data-link-title="Release Freeze" data-link-desc="說明高風險期間如何以凍結策略保護正式環境">Release Freeze</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Redelivery 是 at-least-once delivery 的正常結果。它要求 consumer 具備 idempotency、處理紀錄、狀態檢查與可觀測欄位，讓重複進入的訊息維持同一個業務結果。 可先對照 <a href="/blog/backend/knowledge-cards/release-freeze/" data-link-title="Release Freeze" data-link-desc="說明高風險期間如何以凍結策略保護正式環境">Release Freeze</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要關注 redelivery 的訊號是同一事件被處理多次、retry count 上升或 dead-letter 增加。付款成功事件 redelivery 時，出貨 consumer 要能辨識該付款已處理。</p>
<h2 id="設計責任">設計責任</h2>
<p>Redelivery 指標要記錄原因、次數與事件 ID。Consumer 測試應覆蓋首次處理、處理中 crash、redelivery 後命中已處理紀錄與永久失敗進 dead-letter。</p>
]]></content:encoded></item><item><title>Requeue</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/requeue/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/requeue/</guid><description>&lt;p>Requeue 的核心概念是「把未完成的訊息重新放回可投遞集合」。它讓暫時失敗的工作有機會再次被處理，但也可能造成同一訊息反覆佔用 consumer。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">Resource Limit&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Requeue 是 nack / retry 流程的一種選擇。暫時性錯誤可以 requeue；永久性錯誤應進入 dead-letter 或人工處理流程。Requeue 需要搭配次數限制與 backoff。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">Resource Limit&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要控制 requeue 的訊號是同一訊息反覆進出 queue。外部 API 權限被拒絕時，requeue 只會重複失敗；網路短暫中斷時，requeue 搭配 backoff 可能成功。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Requeue 設計要包含最大次數、錯誤分類、delay、dead-letter 條件與觀測欄位。Runbook 應能查出 requeue loop 的訊息與原因。&lt;/p></description><content:encoded><![CDATA[<p>Requeue 的核心概念是「把未完成的訊息重新放回可投遞集合」。它讓暫時失敗的工作有機會再次被處理，但也可能造成同一訊息反覆佔用 consumer。 可先對照 <a href="/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">Resource Limit</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Requeue 是 nack / retry 流程的一種選擇。暫時性錯誤可以 requeue；永久性錯誤應進入 dead-letter 或人工處理流程。Requeue 需要搭配次數限制與 backoff。 可先對照 <a href="/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">Resource Limit</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要控制 requeue 的訊號是同一訊息反覆進出 queue。外部 API 權限被拒絕時，requeue 只會重複失敗；網路短暫中斷時，requeue 搭配 backoff 可能成功。</p>
<h2 id="設計責任">設計責任</h2>
<p>Requeue 設計要包含最大次數、錯誤分類、delay、dead-letter 條件與觀測欄位。Runbook 應能查出 requeue loop 的訊息與原因。</p>
]]></content:encoded></item><item><title>Redelivery Loop</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/redelivery-loop/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/redelivery-loop/</guid><description>&lt;p>Redelivery loop 的核心概念是「同一訊息反覆被投遞、失敗、重新排回，再次被投遞」。它會消耗 consumer 容量，並讓正常訊息延遲。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/redelivery/" data-link-title="Redelivery" data-link-desc="說明 broker 重新投遞訊息時 consumer 需要承擔的重入責任">Redelivery&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Redelivery loop 是 retry policy 與 dead-letter 設計不足的訊號。它通常代表錯誤分類、最大重試次數、backoff 或 DLQ 條件缺失。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/redelivery/" data-link-title="Redelivery" data-link-desc="說明 broker 重新投遞訊息時 consumer 需要承擔的重入責任">Redelivery&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要處理 redelivery loop 的訊號是同一 message id 的 redelivery count 持續上升。某筆訂單事件 payload 缺少必要欄位時，每次處理都會失敗，應進入 dead-letter 等待修復。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>防護要包含 redelivery 次數上限、poison message 偵測、dead-letter、告警與 replay runbook。Consumer metrics 應能分辨新訊息處理量與重送訊息處理量。&lt;/p></description><content:encoded><![CDATA[<p>Redelivery loop 的核心概念是「同一訊息反覆被投遞、失敗、重新排回，再次被投遞」。它會消耗 consumer 容量，並讓正常訊息延遲。 可先對照 <a href="/blog/backend/knowledge-cards/redelivery/" data-link-title="Redelivery" data-link-desc="說明 broker 重新投遞訊息時 consumer 需要承擔的重入責任">Redelivery</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Redelivery loop 是 retry policy 與 dead-letter 設計不足的訊號。它通常代表錯誤分類、最大重試次數、backoff 或 DLQ 條件缺失。 可先對照 <a href="/blog/backend/knowledge-cards/redelivery/" data-link-title="Redelivery" data-link-desc="說明 broker 重新投遞訊息時 consumer 需要承擔的重入責任">Redelivery</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要處理 redelivery loop 的訊號是同一 message id 的 redelivery count 持續上升。某筆訂單事件 payload 缺少必要欄位時，每次處理都會失敗，應進入 dead-letter 等待修復。</p>
<h2 id="設計責任">設計責任</h2>
<p>防護要包含 redelivery 次數上限、poison message 偵測、dead-letter、告警與 replay runbook。Consumer metrics 應能分辨新訊息處理量與重送訊息處理量。</p>
]]></content:encoded></item><item><title>Poison Message</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/poison-message/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/poison-message/</guid><description>&lt;p>Poison message 的核心概念是「某一則訊息的內容會穩定造成 consumer 失敗」。它可能是格式錯誤、schema 不相容、資料狀態衝突、權限不足或程式 bug 觸發條件。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">Post-Incident Review&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Poison message 是 queue pipeline 的隔離對象。系統要把它從主要處理路徑移開，讓正常訊息繼續前進，同時保留診斷資料給人工或修復流程。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">Post-Incident Review&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 poison message 判斷的訊號是同一訊息每次投遞都失敗。新版 producer 多送一個 consumer 還不支援的 enum 值，可能讓舊版 consumer 持續失敗。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Poison message 要進入 dead-letter，並保留 payload 摘要、schema version、錯誤類型、consumer version、correlation id 與重放條件。修復後才應 replay。&lt;/p></description><content:encoded><![CDATA[<p>Poison message 的核心概念是「某一則訊息的內容會穩定造成 consumer 失敗」。它可能是格式錯誤、schema 不相容、資料狀態衝突、權限不足或程式 bug 觸發條件。 可先對照 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">Post-Incident Review</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Poison message 是 queue pipeline 的隔離對象。系統要把它從主要處理路徑移開，讓正常訊息繼續前進，同時保留診斷資料給人工或修復流程。 可先對照 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">Post-Incident Review</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 poison message 判斷的訊號是同一訊息每次投遞都失敗。新版 producer 多送一個 consumer 還不支援的 enum 值，可能讓舊版 consumer 持續失敗。</p>
<h2 id="設計責任">設計責任</h2>
<p>Poison message 要進入 dead-letter，並保留 payload 摘要、schema version、錯誤類型、consumer version、correlation id 與重放條件。修復後才應 replay。</p>
]]></content:encoded></item><item><title>Queue Depth</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/queue-depth/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/queue-depth/</guid><description>&lt;p>Queue depth 的核心概念是「queue 中等待處理的訊息數量」。它是 backlog 的直覺訊號，反映進入速度和處理速度的差距。 可先對照 &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>Queue depth 是 queue health 的入口指標。Depth 上升可能代表 producer 變快、consumer 變慢、下游變慢、重試增加或 consumer 數量不足。 可先對照 &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>系統需要 queue depth 告警的訊號是工作延遲會影響產品結果。通知 queue depth 持續上升時，使用者可能延遲收到信件；付款入帳 queue depth 上升時，帳務狀態可能延後更新。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Queue depth 要和 consumer lag、oldest message age、processing rate、error rate 與 unacked messages 一起看。只看數量容易忽略訊息重要性與處理時間差異。&lt;/p></description><content:encoded><![CDATA[<p>Queue depth 的核心概念是「queue 中等待處理的訊息數量」。它是 backlog 的直覺訊號，反映進入速度和處理速度的差距。 可先對照 <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">Queue</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Queue depth 是 queue health 的入口指標。Depth 上升可能代表 producer 變快、consumer 變慢、下游變慢、重試增加或 consumer 數量不足。 可先對照 <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">Queue</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 queue depth 告警的訊號是工作延遲會影響產品結果。通知 queue depth 持續上升時，使用者可能延遲收到信件；付款入帳 queue depth 上升時，帳務狀態可能延後更新。</p>
<h2 id="設計責任">設計責任</h2>
<p>Queue depth 要和 consumer lag、oldest message age、processing rate、error rate 與 unacked messages 一起看。只看數量容易忽略訊息重要性與處理時間差異。</p>
]]></content:encoded></item><item><title>Publisher Confirm</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/publisher-confirm/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/publisher-confirm/</guid><description>&lt;p>Publisher confirm 的核心概念是「producer 取得 broker 已接收訊息的確認」。它讓 producer 區分訊息已交給 broker，或在發送途中失敗。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue-contract/" data-link-title="Queue Contract" data-link-desc="說明佇列工作在重試、確認與重複投遞上的約定">Queue Contract&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Publisher confirm 是發布可靠性的下半段。Application 寫出事件後，仍需要確認 broker 是否承擔保存或投遞責任；若 confirm 失敗，producer 要重試、寫 outbox 或回報錯誤。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue-contract/" data-link-title="Queue Contract" data-link-desc="說明佇列工作在重試、確認與重複投遞上的約定">Queue Contract&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 publisher confirm 的訊號是事件遺失會造成後續流程漏執行。訂單付款後發布出貨事件時，producer 需要知道 broker 是否成功接收，否則倉儲服務可能永遠收不到事件。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Publisher confirm 要搭配 timeout、retry、outbox 與 idempotency。觀測上要記錄 publish attempt、confirm latency、confirm failure 與未確認事件數。&lt;/p></description><content:encoded><![CDATA[<p>Publisher confirm 的核心概念是「producer 取得 broker 已接收訊息的確認」。它讓 producer 區分訊息已交給 broker，或在發送途中失敗。 可先對照 <a href="/blog/backend/knowledge-cards/queue-contract/" data-link-title="Queue Contract" data-link-desc="說明佇列工作在重試、確認與重複投遞上的約定">Queue Contract</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Publisher confirm 是發布可靠性的下半段。Application 寫出事件後，仍需要確認 broker 是否承擔保存或投遞責任；若 confirm 失敗，producer 要重試、寫 outbox 或回報錯誤。 可先對照 <a href="/blog/backend/knowledge-cards/queue-contract/" data-link-title="Queue Contract" data-link-desc="說明佇列工作在重試、確認與重複投遞上的約定">Queue Contract</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 publisher confirm 的訊號是事件遺失會造成後續流程漏執行。訂單付款後發布出貨事件時，producer 需要知道 broker 是否成功接收，否則倉儲服務可能永遠收不到事件。</p>
<h2 id="設計責任">設計責任</h2>
<p>Publisher confirm 要搭配 timeout、retry、outbox 與 idempotency。觀測上要記錄 publish attempt、confirm latency、confirm failure 與未確認事件數。</p>
]]></content:encoded></item><item><title>Message Persistence</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/message-persistence/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/message-persistence/</guid><description>&lt;p>Message persistence 的核心概念是「訊息是否被 broker 持久化保存」。持久化訊息在 broker 重啟、節點切換或暫時故障後仍有機會被恢復；非持久化訊息則偏向低延遲與低成本。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/message-protocol/" data-link-title="Message Protocol" data-link-desc="說明 queue 或 stream message 如何對齊格式與處理語意">Message Protocol&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Persistence 是投遞保證與成本的取捨。正式訊息、付款事件、資料同步工作通常需要持久化；typing indicator、presence heartbeat 或即時狀態提示可以接受遺失。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/message-protocol/" data-link-title="Message Protocol" data-link-desc="說明 queue 或 stream message 如何對齊格式與處理語意">Message Protocol&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 message persistence 的訊號是訊息遺失會造成產品後果。訂單付款事件遺失會造成出貨、通知或對帳漏掉；聊天室正在輸入提示遺失通常可以接受。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Persistence 設計要和 queue durability、replication、retention、confirm、consumer ack 與成本一起評估。持久化降低遺失風險，也增加 IO、延遲與操作成本。&lt;/p></description><content:encoded><![CDATA[<p>Message persistence 的核心概念是「訊息是否被 broker 持久化保存」。持久化訊息在 broker 重啟、節點切換或暫時故障後仍有機會被恢復；非持久化訊息則偏向低延遲與低成本。 可先對照 <a href="/blog/backend/knowledge-cards/message-protocol/" data-link-title="Message Protocol" data-link-desc="說明 queue 或 stream message 如何對齊格式與處理語意">Message Protocol</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Persistence 是投遞保證與成本的取捨。正式訊息、付款事件、資料同步工作通常需要持久化；typing indicator、presence heartbeat 或即時狀態提示可以接受遺失。 可先對照 <a href="/blog/backend/knowledge-cards/message-protocol/" data-link-title="Message Protocol" data-link-desc="說明 queue 或 stream message 如何對齊格式與處理語意">Message Protocol</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 message persistence 的訊號是訊息遺失會造成產品後果。訂單付款事件遺失會造成出貨、通知或對帳漏掉；聊天室正在輸入提示遺失通常可以接受。</p>
<h2 id="設計責任">設計責任</h2>
<p>Persistence 設計要和 queue durability、replication、retention、confirm、consumer ack 與成本一起評估。持久化降低遺失風險，也增加 IO、延遲與操作成本。</p>
]]></content:encoded></item><item><title>Delivery Mode</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/delivery-mode/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/delivery-mode/</guid><description>&lt;p>Delivery mode 的核心概念是「訊息系統對交付行為的可靠性選擇」。它可能包含持久化、確認、重送、順序、保留期限與 consumer 分派規則。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Delivery mode 把產品語意轉成 broker 設定。正式訂單事件需要較高保證；即時狀態提示可以選擇低延遲、低保留的模式。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要討論 delivery mode 的訊號是同一系統內有不同重要性的訊息。付款成功、庫存同步、推薦刷新、typing indicator 的失敗代價不同，應各自定義可靠性設定。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Delivery mode 要由訊息語意決定，而非由 broker 預設值決定。設計文件應標出遺失、重複、延遲、順序與重放的可接受範圍。&lt;/p></description><content:encoded><![CDATA[<p>Delivery mode 的核心概念是「訊息系統對交付行為的可靠性選擇」。它可能包含持久化、確認、重送、順序、保留期限與 consumer 分派規則。 可先對照 <a href="/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">Delivery Semantics</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Delivery mode 把產品語意轉成 broker 設定。正式訂單事件需要較高保證；即時狀態提示可以選擇低延遲、低保留的模式。 可先對照 <a href="/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">Delivery Semantics</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要討論 delivery mode 的訊號是同一系統內有不同重要性的訊息。付款成功、庫存同步、推薦刷新、typing indicator 的失敗代價不同，應各自定義可靠性設定。</p>
<h2 id="設計責任">設計責任</h2>
<p>Delivery mode 要由訊息語意決定，而非由 broker 預設值決定。設計文件應標出遺失、重複、延遲、順序與重放的可接受範圍。</p>
]]></content:encoded></item><item><title>Consumer Capacity</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-capacity/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-capacity/</guid><description>&lt;p>Consumer capacity 的核心概念是「consumer 群組在穩定條件下能處理的工作量」。它取決於 consumer 數量、handler 耗時、prefetch、下游容量、錯誤率與重試量。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Consumer capacity 是 queue sizing 與容量規劃的基礎。Producer rate 高於 consumer capacity 時，queue depth 與 lag 會上升；consumer capacity 高於下游容量時，壓力會轉移到資料庫或 API。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要估算 consumer capacity 的訊號是活動前要確認 queue 能否消化尖峰。通知服務每秒進入 5,000 筆任務，而 consumer 群組只能穩定處理 2,000 筆，lag 會持續累積。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Capacity 設計要看平均耗時、p95 耗時、重試比例、下游限制與擴容速度。Runbook 應說明擴 consumer、調 prefetch、降級 producer 或暫停低優先訊息的條件。&lt;/p></description><content:encoded><![CDATA[<p>Consumer capacity 的核心概念是「consumer 群組在穩定條件下能處理的工作量」。它取決於 consumer 數量、handler 耗時、prefetch、下游容量、錯誤率與重試量。 可先對照 <a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">Consumer Group</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Consumer capacity 是 queue sizing 與容量規劃的基礎。Producer rate 高於 consumer capacity 時，queue depth 與 lag 會上升；consumer capacity 高於下游容量時，壓力會轉移到資料庫或 API。 可先對照 <a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">Consumer Group</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要估算 consumer capacity 的訊號是活動前要確認 queue 能否消化尖峰。通知服務每秒進入 5,000 筆任務，而 consumer 群組只能穩定處理 2,000 筆，lag 會持續累積。</p>
<h2 id="設計責任">設計責任</h2>
<p>Capacity 設計要看平均耗時、p95 耗時、重試比例、下游限制與擴容速度。Runbook 應說明擴 consumer、調 prefetch、降級 producer 或暫停低優先訊息的條件。</p>
]]></content:encoded></item><item><title>Competing Consumers</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/competing-consumers/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/competing-consumers/</guid><description>&lt;p>Competing consumers 的核心概念是「多個 consumer 從同一個 queue 競爭取得工作」。這個模式可以提高吞吐與可用性，但會讓單一 queue 中的處理順序更難保證。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/config-rollout/" data-link-title="Config Rollout" data-link-desc="說明設定如何安全下發到正在運作的服務實例">Config Rollout&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Competing consumers 是水平擴展 worker 的常見模式。它適合彼此獨立的工作，例如寄信、轉檔、縮圖、資料同步；對需要嚴格順序的工作，要額外設計 partition、key 或 single consumer。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/config-rollout/" data-link-title="Config Rollout" data-link-desc="說明設定如何安全下發到正在運作的服務實例">Config Rollout&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 competing consumers 的訊號是單一 worker 處理速度追不上進入速度。報表產生任務彼此獨立時，可以增加 consumer 數；同一訂單的狀態事件則可能需要按 order id 保持順序。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計要定義工作是否可並行、是否需要順序、是否具備 idempotency，以及下游容量是否足夠。擴 consumer 前要確認 bottleneck 不在資料庫、外部 API 或全域 lock。&lt;/p></description><content:encoded><![CDATA[<p>Competing consumers 的核心概念是「多個 consumer 從同一個 queue 競爭取得工作」。這個模式可以提高吞吐與可用性，但會讓單一 queue 中的處理順序更難保證。 可先對照 <a href="/blog/backend/knowledge-cards/config-rollout/" data-link-title="Config Rollout" data-link-desc="說明設定如何安全下發到正在運作的服務實例">Config Rollout</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Competing consumers 是水平擴展 worker 的常見模式。它適合彼此獨立的工作，例如寄信、轉檔、縮圖、資料同步；對需要嚴格順序的工作，要額外設計 partition、key 或 single consumer。 可先對照 <a href="/blog/backend/knowledge-cards/config-rollout/" data-link-title="Config Rollout" data-link-desc="說明設定如何安全下發到正在運作的服務實例">Config Rollout</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 competing consumers 的訊號是單一 worker 處理速度追不上進入速度。報表產生任務彼此獨立時，可以增加 consumer 數；同一訂單的狀態事件則可能需要按 order id 保持順序。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計要定義工作是否可並行、是否需要順序、是否具備 idempotency，以及下游容量是否足夠。擴 consumer 前要確認 bottleneck 不在資料庫、外部 API 或全域 lock。</p>
]]></content:encoded></item><item><title>Consumer Group</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-group/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-group/</guid><description>&lt;p>Consumer group 的核心概念是「一組 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer&lt;/a> 共同承擔某個 stream 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic&lt;/a> 的處理進度」。同一 group 內的 consumer 分攤工作（每筆訊息只被 group 內的一個 consumer 處理）；不同 group 可以各自獨立處理同一批事件，實現 &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>Consumer group 是事件流跟多服務訂閱的協調模型。分析服務、搜尋索引服務、通知服務可以用不同 group 讀同一 topic — 每個 group 有自己的 &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-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag&lt;/a>。&lt;/p>
&lt;p>在 Kafka 中，consumer group 是一級概念、由 group coordinator 管理 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition&lt;/a> 分配（rebalance）。在 Redis Streams 中對應 consumer group（XREADGROUP）。在 RabbitMQ 中沒有原生 consumer group — 多個 consumer 連到同一個 queue 就是 competing consumers、不同 queue 綁到同一個 exchange 就是 fan-out。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 consumer group 的訊號是同一事件要被多個系統各自處理。訂單事件同時給出貨、通知與報表 — 三個 consumer group 各自有自己的處理速度、錯誤率跟重放流程。&lt;/p>
&lt;p>Consumer group 的 rebalance（partition 重新分配）是 Kafka 生態的常見運維議題。Consumer 加入或離開 group 時觸發 rebalance、rebalance 期間 partition 暫時無人消費、造成短暫的處理停頓。Rebalance 時間跟 partition 數量、consumer 數量有關。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Consumer group 要設計 group 名稱（跟服務名稱對齊、方便辨識）、offset / checkpoint 策略（auto-commit vs manual commit）、rebalance 行為（cooperative vs eager）、&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/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook&lt;/a> 權限。不同 group 的失敗應分開觀測跟處理 — 通知 group 落後不應影響出貨 group 的監控判讀。&lt;/p></description><content:encoded><![CDATA[<p>Consumer group 的核心概念是「一組 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a> 共同承擔某個 stream 或 <a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic</a> 的處理進度」。同一 group 內的 consumer 分攤工作（每筆訊息只被 group 內的一個 consumer 處理）；不同 group 可以各自獨立處理同一批事件，實現 <a href="/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Consumer group 是事件流跟多服務訂閱的協調模型。分析服務、搜尋索引服務、通知服務可以用不同 group 讀同一 topic — 每個 group 有自己的 <a href="/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">offset</a> 進度跟 <a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag</a>。</p>
<p>在 Kafka 中，consumer group 是一級概念、由 group coordinator 管理 <a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition</a> 分配（rebalance）。在 Redis Streams 中對應 consumer group（XREADGROUP）。在 RabbitMQ 中沒有原生 consumer group — 多個 consumer 連到同一個 queue 就是 competing consumers、不同 queue 綁到同一個 exchange 就是 fan-out。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 consumer group 的訊號是同一事件要被多個系統各自處理。訂單事件同時給出貨、通知與報表 — 三個 consumer group 各自有自己的處理速度、錯誤率跟重放流程。</p>
<p>Consumer group 的 rebalance（partition 重新分配）是 Kafka 生態的常見運維議題。Consumer 加入或離開 group 時觸發 rebalance、rebalance 期間 partition 暫時無人消費、造成短暫的處理停頓。Rebalance 時間跟 partition 數量、consumer 數量有關。</p>
<h2 id="設計責任">設計責任</h2>
<p>Consumer group 要設計 group 名稱（跟服務名稱對齊、方便辨識）、offset / checkpoint 策略（auto-commit vs manual commit）、rebalance 行為（cooperative vs eager）、<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/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook</a> 權限。不同 group 的失敗應分開觀測跟處理 — 通知 group 落後不應影響出貨 group 的監控判讀。</p>
]]></content:encoded></item><item><title>Partition</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/partition/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/partition/</guid><description>&lt;p>Partition 的核心概念是「把事件流切分成多個可並行處理的片段」。同一 partition 內保留順序，不同 partition 可以平行處理。Partition 數量決定 consumer 的最大並行度 — 一個 &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> 中 consumer 數量不能超過 partition 數量。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Partition 是 throughput、ordering 與 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> 的關係是：topic 是邏輯分類（order events、payment events），partition 是 topic 內的物理分片。Partition key 決定同一類事件會落到哪個 partition；選錯 key 會造成 hot partition（單一 partition 過載）或讓需要順序的事件被拆散。&lt;/p>
&lt;p>在 Kafka 中 partition 是一級概念；RabbitMQ 沒有原生 partition（用多個 queue + consistent hash exchange 模擬）；SQS 沒有顯式 partition（內部自動分片）。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 partition 設計的訊號是事件量大且需要水平擴展處理能力。訂單事件可以用 order_id 作為 partition key，讓同一訂單的事件保留順序；若所有高流量商家的訂單都 hash 到同一個 partition，會形成 hot partition。&lt;/p>
&lt;p>Partition 數量也影響 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">offset&lt;/a> 管理的複雜度 — 每個 partition 有獨立的 offset，consumer group 的 rebalance 要重新分配 partition ownership。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Partition 設計要定義 partition key（通常是業務實體 ID）、partition 數量（建議初期設多一點，Kafka partition 數量只能增加不能減少）、順序需求（同 key 保序 vs 全域保序）與 lag 觀測（per-partition lag 能定位 hot partition）。重新分 partition 可能影響順序、consumer group 配置與 replay 範圍。&lt;/p></description><content:encoded><![CDATA[<p>Partition 的核心概念是「把事件流切分成多個可並行處理的片段」。同一 partition 內保留順序，不同 partition 可以平行處理。Partition 數量決定 consumer 的最大並行度 — 一個 <a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group</a> 中 consumer 數量不能超過 partition 數量。</p>
<h2 id="概念位置">概念位置</h2>
<p>Partition 是 throughput、ordering 與 hot key 之間的取捨核心。它跟 <a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic</a> 的關係是：topic 是邏輯分類（order events、payment events），partition 是 topic 內的物理分片。Partition key 決定同一類事件會落到哪個 partition；選錯 key 會造成 hot partition（單一 partition 過載）或讓需要順序的事件被拆散。</p>
<p>在 Kafka 中 partition 是一級概念；RabbitMQ 沒有原生 partition（用多個 queue + consistent hash exchange 模擬）；SQS 沒有顯式 partition（內部自動分片）。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 partition 設計的訊號是事件量大且需要水平擴展處理能力。訂單事件可以用 order_id 作為 partition key，讓同一訂單的事件保留順序；若所有高流量商家的訂單都 hash 到同一個 partition，會形成 hot partition。</p>
<p>Partition 數量也影響 <a href="/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">offset</a> 管理的複雜度 — 每個 partition 有獨立的 offset，consumer group 的 rebalance 要重新分配 partition ownership。</p>
<h2 id="設計責任">設計責任</h2>
<p>Partition 設計要定義 partition key（通常是業務實體 ID）、partition 數量（建議初期設多一點，Kafka partition 數量只能增加不能減少）、順序需求（同 key 保序 vs 全域保序）與 lag 觀測（per-partition lag 能定位 hot partition）。重新分 partition 可能影響順序、consumer group 配置與 replay 範圍。</p>
]]></content:encoded></item><item><title>Offset</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/offset/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/offset/</guid><description>&lt;p>Offset 的核心概念是「consumer 在事件流中的讀取位置」。它是 &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> 的進度記錄，讓 consumer 知道自己已經處理到哪裡，也讓系統可以從某個位置繼續或重放。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Offset 是 &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;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/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook&lt;/a> 的起點定位。在 Kafka 中，offset 是每個 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition&lt;/a> 內的遞增整數；在 Redis Streams 中是 entry ID（timestamp-sequence）；在 SQS 中沒有顯式 offset，改用 visibility timeout 控制消費進度。&lt;/p>
&lt;p>Offset 提交太早（處理前就 commit）可能造成處理遺失 — consumer crash 後從已 commit 的位置繼續，跳過未完成的訊息。提交太晚（處理完成很久才 commit）可能造成重複處理 — consumer crash 後從舊 offset 重新開始，重複處理已完成的訊息。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要理解 offset 的訊號是 consumer 重啟後需要接續處理。報表 consumer 處理到某個 offset 後 crash，重啟時要從安全位置繼續，並用 &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>Offset 也是 replay 操作的控制參數。「重設 offset 到三天前」意味著 consumer group 會從三天前的位置重新處理所有事件 — 下游需要有 idempotent 設計才能承受重播。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Offset 提交策略要和業務處理完成條件對齊。Auto-commit（定期自動提交）實作簡單但在 crash 時有遺失風險；manual commit（處理完成後手動提交）更安全但程式碼更複雜。Runbook 應說明如何查 current offset、committed offset、lag、重設 offset 的操作步驟與 replay 對下游的影響。&lt;/p></description><content:encoded><![CDATA[<p>Offset 的核心概念是「consumer 在事件流中的讀取位置」。它是 <a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group</a> 的進度記錄，讓 consumer 知道自己已經處理到哪裡，也讓系統可以從某個位置繼續或重放。</p>
<h2 id="概念位置">概念位置</h2>
<p>Offset 是 <a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group</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/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook</a> 的起點定位。在 Kafka 中，offset 是每個 <a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition</a> 內的遞增整數；在 Redis Streams 中是 entry ID（timestamp-sequence）；在 SQS 中沒有顯式 offset，改用 visibility timeout 控制消費進度。</p>
<p>Offset 提交太早（處理前就 commit）可能造成處理遺失 — consumer crash 後從已 commit 的位置繼續，跳過未完成的訊息。提交太晚（處理完成很久才 commit）可能造成重複處理 — consumer crash 後從舊 offset 重新開始，重複處理已完成的訊息。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要理解 offset 的訊號是 consumer 重啟後需要接續處理。報表 consumer 處理到某個 offset 後 crash，重啟時要從安全位置繼續，並用 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 承受可能重複的事件。</p>
<p>Offset 也是 replay 操作的控制參數。「重設 offset 到三天前」意味著 consumer group 會從三天前的位置重新處理所有事件 — 下游需要有 idempotent 設計才能承受重播。</p>
<h2 id="設計責任">設計責任</h2>
<p>Offset 提交策略要和業務處理完成條件對齊。Auto-commit（定期自動提交）實作簡單但在 crash 時有遺失風險；manual commit（處理完成後手動提交）更安全但程式碼更複雜。Runbook 應說明如何查 current offset、committed offset、lag、重設 offset 的操作步驟與 replay 對下游的影響。</p>
]]></content:encoded></item><item><title>Retention</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/retention/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/retention/</guid><description>&lt;p>Retention 的核心概念是「資料或事件在系統中保留多久」。它影響 storage cost、audit 能力、replay 能力、debug 時間窗口、合規義務與資料刪除責任，跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/storage-tiering/" data-link-title="Storage Tiering" data-link-desc="說明按資料熱度分層儲存以平衡查詢速度、儲存成本與保留完整性的機制">storage tiering&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup&lt;/a> 共同構成資料生命週期管理。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Retention 連接資料生命週期跟查詢能力。不同類型的資料需要不同保留期限 — log 的 debug 用途可能只需要 7 天、audit log 因合規要求可能需要 1 年以上、metrics 的 raw data 可能保留 15 天但 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup&lt;/a> 保留 90 天。&lt;/p>
&lt;p>Retention 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/storage-tiering/" data-link-title="Storage Tiering" data-link-desc="說明按資料熱度分層儲存以平衡查詢速度、儲存成本與保留完整性的機制">storage tiering&lt;/a> 搭配運作 — hot tier 保留最近的高精度資料、warm / cold tier 保留較舊的低精度或歸檔資料。保留期限的設定見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/cardinality-cost-governance/" data-link-title="4.7 Cardinality 治理與成本邊界" data-link-desc="把 metric / log / trace 的 cardinality 與成本作為平台一級治理議題">4.7 cardinality 與成本邊界&lt;/a> 的保留階梯段。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 retention 設計的訊號是事故排查或資料修復需要回看歷史。若 event stream 只保留 24 小時，三天前的錯誤就無法靠 replay 重建。反過來，無限保留會讓儲存成本持續成長。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Retention 要同時考慮成本（儲存 × 時間）、法規（合規要求的最短保留期跟 GDPR 要求的最長保留期可能衝突）、資安（高敏感資料保留越久風險越高）、replay 需求（MQ 的 retention 影響 consumer 的 catchup 能力）跟 debug 能力（retention 太短讓事後分析無資料可用）。不同訊號類型用不同 retention 是基本做法 — error log 保留比 debug log 長、audit log 保留比 operational log 長。&lt;/p></description><content:encoded><![CDATA[<p>Retention 的核心概念是「資料或事件在系統中保留多久」。它影響 storage cost、audit 能力、replay 能力、debug 時間窗口、合規義務與資料刪除責任，跟 <a href="/blog/backend/knowledge-cards/storage-tiering/" data-link-title="Storage Tiering" data-link-desc="說明按資料熱度分層儲存以平衡查詢速度、儲存成本與保留完整性的機制">storage tiering</a> 與 <a href="/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup</a> 共同構成資料生命週期管理。</p>
<h2 id="概念位置">概念位置</h2>
<p>Retention 連接資料生命週期跟查詢能力。不同類型的資料需要不同保留期限 — log 的 debug 用途可能只需要 7 天、audit log 因合規要求可能需要 1 年以上、metrics 的 raw data 可能保留 15 天但 <a href="/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup</a> 保留 90 天。</p>
<p>Retention 跟 <a href="/blog/backend/knowledge-cards/storage-tiering/" data-link-title="Storage Tiering" data-link-desc="說明按資料熱度分層儲存以平衡查詢速度、儲存成本與保留完整性的機制">storage tiering</a> 搭配運作 — hot tier 保留最近的高精度資料、warm / cold tier 保留較舊的低精度或歸檔資料。保留期限的設定見 <a href="/blog/backend/04-observability/cardinality-cost-governance/" data-link-title="4.7 Cardinality 治理與成本邊界" data-link-desc="把 metric / log / trace 的 cardinality 與成本作為平台一級治理議題">4.7 cardinality 與成本邊界</a> 的保留階梯段。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 retention 設計的訊號是事故排查或資料修復需要回看歷史。若 event stream 只保留 24 小時，三天前的錯誤就無法靠 replay 重建。反過來，無限保留會讓儲存成本持續成長。</p>
<h2 id="設計責任">設計責任</h2>
<p>Retention 要同時考慮成本（儲存 × 時間）、法規（合規要求的最短保留期跟 GDPR 要求的最長保留期可能衝突）、資安（高敏感資料保留越久風險越高）、replay 需求（MQ 的 retention 影響 consumer 的 catchup 能力）跟 debug 能力（retention 太短讓事後分析無資料可用）。不同訊號類型用不同 retention 是基本做法 — error log 保留比 debug log 長、audit log 保留比 operational log 長。</p>
]]></content:encoded></item><item><title>Online Migration</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/online-migration/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/online-migration/</guid><description>&lt;p>Online migration 的核心概念是「在服務持續運作期間完成資料或 schema 遷移」。它讓系統在不中斷主要服務的情況下搬移資料、改欄位、換儲存或調整索引。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Online migration 是 release、database、observability 與 rollback 的共同工程。它通常搭配 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract&lt;/a>、backfill、dual write、shadow read、cutover 與 correctness check。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 online migration 的訊號是資料量大、停機代價高或 rolling update 期間新舊版本會共存。把會員資料從舊 table 搬到新 table 時，服務仍要能註冊、登入與更新會員資料。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Online migration 要設計階段、監控、速率限制、回滾、資料比對與停止條件。每個階段都要能獨立驗證，並保留回到前一階段的路徑。&lt;/p></description><content:encoded><![CDATA[<p>Online migration 的核心概念是「在服務持續運作期間完成資料或 schema 遷移」。它讓系統在不中斷主要服務的情況下搬移資料、改欄位、換儲存或調整索引。 可先對照 <a href="/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Online migration 是 release、database、observability 與 rollback 的共同工程。它通常搭配 <a href="/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract</a>、backfill、dual write、shadow read、cutover 與 correctness check。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 online migration 的訊號是資料量大、停機代價高或 rolling update 期間新舊版本會共存。把會員資料從舊 table 搬到新 table 時，服務仍要能註冊、登入與更新會員資料。</p>
<h2 id="設計責任">設計責任</h2>
<p>Online migration 要設計階段、監控、速率限制、回滾、資料比對與停止條件。每個階段都要能獨立驗證，並保留回到前一階段的路徑。</p>
]]></content:encoded></item><item><title>Cutover / Switchover</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-switchover/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-switchover/</guid><description>&lt;p>Cutover / switchover 的核心概念是「把正式讀寫從舊路徑切到新路徑」。它是 migration 中風險最高的時刻，因為使用者流量開始依賴新資料、新服務或新設定。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">Dashboard&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cutover 連接資料正確性、部署、觀測與 rollback。切換可以一次完成，也可以用 feature flag、百分比流量、tenant 分批或讀寫分離逐步進行。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">Dashboard&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 cutover 計畫的訊號是新舊系統都已準備好，但正式流量尚未切換。把搜尋索引換到新 cluster 時，可以先 shadow read 比對結果，再分批把讀取流量切過去。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Cutover runbook 要包含前置檢查、切換步驟、觀測指標、停止條件、rollback 條件與負責人。切換後要持續監控錯誤率、延遲、資料差異與使用者回報。&lt;/p></description><content:encoded><![CDATA[<p>Cutover / switchover 的核心概念是「把正式讀寫從舊路徑切到新路徑」。它是 migration 中風險最高的時刻，因為使用者流量開始依賴新資料、新服務或新設定。 可先對照 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">Dashboard</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cutover 連接資料正確性、部署、觀測與 rollback。切換可以一次完成，也可以用 feature flag、百分比流量、tenant 分批或讀寫分離逐步進行。 可先對照 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">Dashboard</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 cutover 計畫的訊號是新舊系統都已準備好，但正式流量尚未切換。把搜尋索引換到新 cluster 時，可以先 shadow read 比對結果，再分批把讀取流量切過去。</p>
<h2 id="設計責任">設計責任</h2>
<p>Cutover runbook 要包含前置檢查、切換步驟、觀測指標、停止條件、rollback 條件與負責人。切換後要持續監控錯誤率、延遲、資料差異與使用者回報。</p>
]]></content:encoded></item><item><title>Fallback Plan</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-plan/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-plan/</guid><description>&lt;p>Fallback plan 的核心概念是「變更失敗時回到可接受狀態的計畫」。它關注 migration、發版、設定切換或服務替換失敗後的操作路徑。 可先對照 &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>Fallback plan 是 release 與 migration 的風險控制。Rollback 是回到舊版本；fallback plan 可以包含暫停流量、切回舊路徑、凍結寫入、啟動維護模式或人工處理。 可先對照 &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>系統需要 fallback plan 的訊號是變更會影響資料正確性或核心流量。新付款 provider 上線後錯誤率升高，團隊需要知道如何切回舊 provider、如何處理已送出的交易、如何對帳。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Fallback plan 要在變更前完成，並明確列出觸發條件、執行者、資料影響、外部溝通與驗證方式。高風險變更應在預備環境演練。&lt;/p></description><content:encoded><![CDATA[<p>Fallback plan 的核心概念是「變更失敗時回到可接受狀態的計畫」。它關注 migration、發版、設定切換或服務替換失敗後的操作路徑。 可先對照 <a href="/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">Fallback</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Fallback plan 是 release 與 migration 的風險控制。Rollback 是回到舊版本；fallback plan 可以包含暫停流量、切回舊路徑、凍結寫入、啟動維護模式或人工處理。 可先對照 <a href="/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">Fallback</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 fallback plan 的訊號是變更會影響資料正確性或核心流量。新付款 provider 上線後錯誤率升高，團隊需要知道如何切回舊 provider、如何處理已送出的交易、如何對帳。</p>
<h2 id="設計責任">設計責任</h2>
<p>Fallback plan 要在變更前完成，並明確列出觸發條件、執行者、資料影響、外部溝通與驗證方式。高風險變更應在預備環境演練。</p>
]]></content:encoded></item><item><title>Change Data Capture</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/</guid><description>&lt;p>Change Data Capture 的核心概念是「捕捉 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a> 變更並把變更傳送給其他系統」。CDC 可以用於同步搜尋索引、資料倉儲、cache、event stream 或新舊系統 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>CDC 是資料同步與事件化的橋樑。它通常從 database log、trigger、polling 或平台工具取得變更，再轉成可由 &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;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 CDC 的訊號是正式資料更新後，多個衍生系統都需要同步。會員資料變更後，搜尋、推薦、報表與客服系統可能都需要收到更新。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>CDC 設計要處理順序、&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>、schema 變更、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">backfill&lt;/a>、lag、&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/data-masking/" data-link-title="Data Masking" data-link-desc="說明敏感資料如何在顯示、匯出、log 與測試資料中降低暴露">data masking&lt;/a>。觀測上要看 capture lag、delivery lag、錯誤率與最舊未同步資料時間。&lt;/p></description><content:encoded><![CDATA[<p>Change Data Capture 的核心概念是「捕捉 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a> 變更並把變更傳送給其他系統」。CDC 可以用於同步搜尋索引、資料倉儲、cache、event stream 或新舊系統 <a href="/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>CDC 是資料同步與事件化的橋樑。它通常從 database log、trigger、polling 或平台工具取得變更，再轉成可由 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a> 處理的事件流。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 CDC 的訊號是正式資料更新後，多個衍生系統都需要同步。會員資料變更後，搜尋、推薦、報表與客服系統可能都需要收到更新。</p>
<h2 id="設計責任">設計責任</h2>
<p>CDC 設計要處理順序、<a href="/blog/backend/knowledge-cards/duplicate-delivery/" data-link-title="Duplicate Delivery" data-link-desc="說明同一個訊息被處理多次時如何保持結果穩定">duplicate delivery</a>、schema 變更、<a href="/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">backfill</a>、lag、<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/data-masking/" data-link-title="Data Masking" data-link-desc="說明敏感資料如何在顯示、匯出、log 與測試資料中降低暴露">data masking</a>。觀測上要看 capture lag、delivery lag、錯誤率與最舊未同步資料時間。</p>
]]></content:encoded></item><item><title>Replication Lag</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/</guid><description>&lt;p>Replication lag 的核心概念是「資料副本落後正式來源的時間或位置差距」。Replica、搜尋索引、read model、cache 與資料倉儲都可能有 lag。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Replication lag 是資料一致性與讀取路徑的風險指標。讀 replica 可以降低正式 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a> 壓力，但 lag 會讓剛寫入的資料在副本上暫時看不到。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 replication lag 觀測的訊號是使用者寫入後立刻讀取。使用者更新地址後，客服後台若讀 replica，可能短時間內仍看到舊地址；付款與出貨流程則應讀 &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;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Lag 設計要定義可接受延遲、讀取路徑、強一致需求與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">fallback&lt;/a>。觀測上要能看每個 replica、index 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">stream pipeline&lt;/a> 的 lag 與最舊未同步資料。&lt;/p></description><content:encoded><![CDATA[<p>Replication lag 的核心概念是「資料副本落後正式來源的時間或位置差距」。Replica、搜尋索引、read model、cache 與資料倉儲都可能有 lag。 可先對照 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Replication lag 是資料一致性與讀取路徑的風險指標。讀 replica 可以降低正式 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a> 壓力，但 lag 會讓剛寫入的資料在副本上暫時看不到。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 replication lag 觀測的訊號是使用者寫入後立刻讀取。使用者更新地址後，客服後台若讀 replica，可能短時間內仍看到舊地址；付款與出貨流程則應讀 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>Lag 設計要定義可接受延遲、讀取路徑、強一致需求與 <a href="/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">fallback</a>。觀測上要能看每個 replica、index 或 <a href="/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">stream pipeline</a> 的 lag 與最舊未同步資料。</p>
]]></content:encoded></item><item><title>Checkpoint</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/checkpoint/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/checkpoint/</guid><description>&lt;p>Checkpoint 的核心概念是「記錄處理流程已安全完成的位置」。它讓長時間工作、event consumer、migration、backfill 或資料同步在中斷後可以接續。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Checkpoint 是恢復能力與重放安全的基礎。它可以是 offset、時間戳、primary key、batch id、file position 或業務狀態。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 checkpoint 的訊號是工作需要分批完成或可能中途停止。Backfill 會員資料跑到第 300 萬筆時部署中斷，checkpoint 讓下一次從安全位置繼續。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Checkpoint 要和處理完成條件對齊。提交太早可能遺失工作，提交太晚可能重複處理；因此 handler 需要 idempotency 或可重入設計。&lt;/p></description><content:encoded><![CDATA[<p>Checkpoint 的核心概念是「記錄處理流程已安全完成的位置」。它讓長時間工作、event consumer、migration、backfill 或資料同步在中斷後可以接續。 可先對照 <a href="/blog/backend/knowledge-cards/ci-pipeline/" data-link-title="CI Pipeline" data-link-desc="說明持續整合流程如何在合併前驗證品質與相容性">CI Pipeline</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Checkpoint 是恢復能力與重放安全的基礎。它可以是 offset、時間戳、primary key、batch id、file position 或業務狀態。 可先對照 <a href="/blog/backend/knowledge-cards/ci-pipeline/" data-link-title="CI Pipeline" data-link-desc="說明持續整合流程如何在合併前驗證品質與相容性">CI Pipeline</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 checkpoint 的訊號是工作需要分批完成或可能中途停止。Backfill 會員資料跑到第 300 萬筆時部署中斷，checkpoint 讓下一次從安全位置繼續。</p>
<h2 id="設計責任">設計責任</h2>
<p>Checkpoint 要和處理完成條件對齊。提交太早可能遺失工作，提交太晚可能重複處理；因此 handler 需要 idempotency 或可重入設計。</p>
]]></content:encoded></item><item><title>Backfill</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/backfill/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/backfill/</guid><description>&lt;p>Backfill 的核心概念是「為既有資料補上新結構或新衍生結果」。它常出現在 migration、新功能上線、資料修復、搜尋索引重建與報表補算。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">Backpressure&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Backfill 是資料遷移的執行階段。它會消耗資料庫、cache、queue、CPU 與網路資源，因此需要速率限制、checkpoint、監控與停止條件。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">Backpressure&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 backfill 的訊號是新欄位對新資料有效，但舊資料尚未填滿。會員資料新增 &lt;code>country_code&lt;/code> 後，需要從地址或外部資料補算舊會員欄位。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Backfill 要分批執行，並記錄進度、錯誤、重試與資料差異。高風險 backfill 應先抽樣驗證，再逐步擴大範圍。&lt;/p></description><content:encoded><![CDATA[<p>Backfill 的核心概念是「為既有資料補上新結構或新衍生結果」。它常出現在 migration、新功能上線、資料修復、搜尋索引重建與報表補算。 可先對照 <a href="/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">Backpressure</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Backfill 是資料遷移的執行階段。它會消耗資料庫、cache、queue、CPU 與網路資源，因此需要速率限制、checkpoint、監控與停止條件。 可先對照 <a href="/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">Backpressure</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 backfill 的訊號是新欄位對新資料有效，但舊資料尚未填滿。會員資料新增 <code>country_code</code> 後，需要從地址或外部資料補算舊會員欄位。</p>
<h2 id="設計責任">設計責任</h2>
<p>Backfill 要分批執行，並記錄進度、錯誤、重試與資料差異。高風險 backfill 應先抽樣驗證，再逐步擴大範圍。</p>
]]></content:encoded></item><item><title>Dual Write</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/dual-write/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/dual-write/</guid><description>&lt;p>Dual write 的核心概念是「同一業務變更同時寫入兩個系統」。它常用在 migration、新舊系統並行、資料同步與服務拆分期間。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Dual write 是高風險一致性模式。兩個寫入目標很難共享同一個 transaction，因此可能出現一邊成功、一邊失敗，或兩邊順序不同。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 dual write 風險評估的訊號是 migration 期間新舊資料都要保持更新。會員資料同時寫舊資料庫與新資料庫時，任一邊 timeout 都可能造成資料分裂。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Dual write 要搭配 outbox、reconcile、correctness check、重試與 fallback plan。設計文件應說明哪一邊是 source of truth，以及不一致時如何修復。&lt;/p></description><content:encoded><![CDATA[<p>Dual write 的核心概念是「同一業務變更同時寫入兩個系統」。它常用在 migration、新舊系統並行、資料同步與服務拆分期間。 可先對照 <a href="/blog/backend/knowledge-cards/duplicate-delivery/" data-link-title="Duplicate Delivery" data-link-desc="說明同一個訊息被處理多次時如何保持結果穩定">Duplicate Delivery</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Dual write 是高風險一致性模式。兩個寫入目標很難共享同一個 transaction，因此可能出現一邊成功、一邊失敗，或兩邊順序不同。 可先對照 <a href="/blog/backend/knowledge-cards/duplicate-delivery/" data-link-title="Duplicate Delivery" data-link-desc="說明同一個訊息被處理多次時如何保持結果穩定">Duplicate Delivery</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 dual write 風險評估的訊號是 migration 期間新舊資料都要保持更新。會員資料同時寫舊資料庫與新資料庫時，任一邊 timeout 都可能造成資料分裂。</p>
<h2 id="設計責任">設計責任</h2>
<p>Dual write 要搭配 outbox、reconcile、correctness check、重試與 fallback plan。設計文件應說明哪一邊是 source of truth，以及不一致時如何修復。</p>
]]></content:encoded></item><item><title>Shadow Read</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/shadow-read/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/shadow-read/</guid><description>&lt;p>Shadow read 的核心概念是「正式結果仍使用舊路徑，同時暗中讀新路徑做比對」。它讓團隊在 cutover 前驗證新系統的正確性與延遲。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Shadow read 是 migration 與服務替換的驗證工具。它能在不影響使用者結果的前提下收集新舊差異，但會增加下游流量與資料存取成本。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 shadow read 的訊號是新讀取路徑即將接正式流量。搜尋服務換新索引前，可以用正式查詢同時查新索引，記錄結果差異但仍回傳舊索引結果。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Shadow read 要控制採樣率、timeout、資料遮罩、差異記錄與成本。它的結果應進入 correctness dashboard，並作為 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate&lt;/a> 的依據。&lt;/p></description><content:encoded><![CDATA[<p>Shadow read 的核心概念是「正式結果仍使用舊路徑，同時暗中讀新路徑做比對」。它讓團隊在 cutover 前驗證新系統的正確性與延遲。 可先對照 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Shadow read 是 migration 與服務替換的驗證工具。它能在不影響使用者結果的前提下收集新舊差異，但會增加下游流量與資料存取成本。 可先對照 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 shadow read 的訊號是新讀取路徑即將接正式流量。搜尋服務換新索引前，可以用正式查詢同時查新索引，記錄結果差異但仍回傳舊索引結果。</p>
<h2 id="設計責任">設計責任</h2>
<p>Shadow read 要控制採樣率、timeout、資料遮罩、差異記錄與成本。它的結果應進入 correctness dashboard，並作為 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate</a> 的依據。</p>
]]></content:encoded></item><item><title>Correctness Check</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/correctness-check/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/correctness-check/</guid><description>&lt;p>Correctness check 的核心概念是「用明確規則驗證新舊結果是否一致或可接受」。它不只比對字面相等，也要理解哪些差異符合預期，哪些差異代表資料錯誤。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Correctness check 是 migration、refactoring、shadow read、backfill 與 cutover 的決策依據。沒有正確性檢查，團隊只能憑錯誤率或使用者回報判斷新系統。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 correctness check 的訊號是新舊系統會並行一段時間。價格計算服務重寫後，要比對總價、折扣、稅額、幣別與 rounding 規則，而不只是比對 response 字串。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Correctness check 要定義比對欄位、容忍差異、抽樣策略、錯誤分類與停止條件。高風險差異要能追到 request id、資料版本與規則版本，並作為 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate&lt;/a> 的依據。&lt;/p></description><content:encoded><![CDATA[<p>Correctness check 的核心概念是「用明確規則驗證新舊結果是否一致或可接受」。它不只比對字面相等，也要理解哪些差異符合預期，哪些差異代表資料錯誤。 可先對照 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Correctness check 是 migration、refactoring、shadow read、backfill 與 cutover 的決策依據。沒有正確性檢查，團隊只能憑錯誤率或使用者回報判斷新系統。 可先對照 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 correctness check 的訊號是新舊系統會並行一段時間。價格計算服務重寫後，要比對總價、折扣、稅額、幣別與 rounding 規則，而不只是比對 response 字串。</p>
<h2 id="設計責任">設計責任</h2>
<p>Correctness check 要定義比對欄位、容忍差異、抽樣策略、錯誤分類與停止條件。高風險差異要能追到 request id、資料版本與規則版本，並作為 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate</a> 的依據。</p>
]]></content:encoded></item><item><title>Data Completeness</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/data-completeness/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/data-completeness/</guid><description>&lt;p>Data completeness 的核心概念是「資料是否完整到足以支持目標用途」。資料可以格式正確，但仍缺少必要筆數、欄位、時間範圍或關聯資料。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Completeness 是資料品質的一部分。Migration、backfill、報表、audit、搜尋索引與機器學習資料集都需要確認資料是否完整。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 completeness check 的訊號是資料遷移完成後仍可能缺漏。訂單資料搬遷時，除了 row count，也要確認 order items、付款紀錄、退款紀錄與狀態歷史是否完整。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Completeness 檢查要包含總量、分群、時間範圍、關聯完整性與抽樣。結果應進入 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate&lt;/a>，並留下可重跑的查詢或報表。&lt;/p></description><content:encoded><![CDATA[<p>Data completeness 的核心概念是「資料是否完整到足以支持目標用途」。資料可以格式正確，但仍缺少必要筆數、欄位、時間範圍或關聯資料。 可先對照 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Completeness 是資料品質的一部分。Migration、backfill、報表、audit、搜尋索引與機器學習資料集都需要確認資料是否完整。 可先對照 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 completeness check 的訊號是資料遷移完成後仍可能缺漏。訂單資料搬遷時，除了 row count，也要確認 order items、付款紀錄、退款紀錄與狀態歷史是否完整。</p>
<h2 id="設計責任">設計責任</h2>
<p>Completeness 檢查要包含總量、分群、時間範圍、關聯完整性與抽樣。結果應進入 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate</a>，並留下可重跑的查詢或報表。</p>
]]></content:encoded></item><item><title>Data Reconciliation</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/</guid><description>&lt;p>Data reconciliation 的核心概念是「比對多個資料來源，找出差異並修復到可接受狀態」。它常用在付款對帳、資料 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration&lt;/a>、事件漏處理、報表修復與第三方同步。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Reconciliation 是 eventual consistency 的修復流程。即使系統設計了事件、&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/outbox-pattern/" data-link-title="Outbox Pattern" data-link-desc="說明資料庫狀態變更與事件發布如何透過 outbox 維持一致">outbox pattern&lt;/a>，仍需要定期或事件後比對正式結果，修復漏送、重複或半成功。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 reconciliation 的訊號是兩個系統都聲稱有狀態，但結果可能不同。付款 provider 顯示已扣款，訂單系統顯示未付款時，需要對帳流程依 &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;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Reconciliation 要定義比對來源、優先權、差異分類、修復動作、&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;/p></description><content:encoded><![CDATA[<p>Data reconciliation 的核心概念是「比對多個資料來源，找出差異並修復到可接受狀態」。它常用在付款對帳、資料 <a href="/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration</a>、事件漏處理、報表修復與第三方同步。</p>
<h2 id="概念位置">概念位置</h2>
<p>Reconciliation 是 eventual consistency 的修復流程。即使系統設計了事件、<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/outbox-pattern/" data-link-title="Outbox Pattern" data-link-desc="說明資料庫狀態變更與事件發布如何透過 outbox 維持一致">outbox pattern</a>，仍需要定期或事件後比對正式結果，修復漏送、重複或半成功。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 reconciliation 的訊號是兩個系統都聲稱有狀態，但結果可能不同。付款 provider 顯示已扣款，訂單系統顯示未付款時，需要對帳流程依 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a> 判斷正式結果並修復訂單狀態。</p>
<h2 id="設計責任">設計責任</h2>
<p>Reconciliation 要定義比對來源、優先權、差異分類、修復動作、<a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a> 與人工介入條件。高風險資料要保留修復前後的證據。</p>
]]></content:encoded></item><item><title>Cache Hit / Miss</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-miss/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-miss/</guid><description>&lt;p>Cache hit / miss 的核心概念是「讀取是否在快取中找到可用資料」。Hit 表示快取提供結果；miss 表示 application 需要回到正式來源或其他資料路徑。 可先對照 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Hit / miss 是快取效益的基礎訊號。Hit 越高，通常表示下游讀取壓力越低；miss 上升可能來自 TTL 太短、eviction、key 設計錯誤、流量型態改變或資料剛被清除。 可先對照 &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>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要觀察 hit / miss 的訊號是快取導入後仍然沒有降低資料庫壓力。熱門商品頁若 miss rate 高，資料庫仍會承受大量查詢。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Hit / miss 指標要按 key pattern、endpoint、tenant 或資料類型切分。Runbook 應說明 miss 上升時如何檢查 TTL、eviction、cache invalidation 與 cache stampede。&lt;/p></description><content:encoded><![CDATA[<p>Cache hit / miss 的核心概念是「讀取是否在快取中找到可用資料」。Hit 表示快取提供結果；miss 表示 application 需要回到正式來源或其他資料路徑。 可先對照 <a href="/blog/backend/knowledge-cards/cache-hit-rate/" data-link-title="Cache Hit Rate" data-link-desc="說明快取命中比例如何衡量加速效果與下游保護">Cache Hit Rate</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Hit / miss 是快取效益的基礎訊號。Hit 越高，通常表示下游讀取壓力越低；miss 上升可能來自 TTL 太短、eviction、key 設計錯誤、流量型態改變或資料剛被清除。 可先對照 <a href="/blog/backend/knowledge-cards/cache-hit-rate/" data-link-title="Cache Hit Rate" data-link-desc="說明快取命中比例如何衡量加速效果與下游保護">Cache Hit Rate</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要觀察 hit / miss 的訊號是快取導入後仍然沒有降低資料庫壓力。熱門商品頁若 miss rate 高，資料庫仍會承受大量查詢。</p>
<h2 id="設計責任">設計責任</h2>
<p>Hit / miss 指標要按 key pattern、endpoint、tenant 或資料類型切分。Runbook 應說明 miss 上升時如何檢查 TTL、eviction、cache invalidation 與 cache stampede。</p>
]]></content:encoded></item><item><title>Cache Hit Rate</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-rate/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-rate/</guid><description>&lt;p>Cache hit rate 的核心概念是「快取命中次數佔總讀取次數的比例」。它用來衡量快取是否真的承擔讀取流量。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Hit rate 是容量與成本指標。低 hit rate 可能代表快取資料不適合、key 太分散、TTL 太短、資料經常失效或工作負載不重複。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 hit rate 的訊號是 Redis 成本上升但資料庫壓力仍高。若搜尋結果每次 query 都不同，快取命中率可能很低；商品詳情這類重複讀取則更適合快取。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Hit rate 要搭配 latency、下游 query count、cache size 與資料新鮮度一起看。高 hit rate 也要確認資料正確性，因為過期資料命中仍可能造成產品問題。&lt;/p></description><content:encoded><![CDATA[<p>Cache hit rate 的核心概念是「快取命中次數佔總讀取次數的比例」。它用來衡量快取是否真的承擔讀取流量。 可先對照 <a href="/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">Cache Invalidation</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Hit rate 是容量與成本指標。低 hit rate 可能代表快取資料不適合、key 太分散、TTL 太短、資料經常失效或工作負載不重複。 可先對照 <a href="/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">Cache Invalidation</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 hit rate 的訊號是 Redis 成本上升但資料庫壓力仍高。若搜尋結果每次 query 都不同，快取命中率可能很低；商品詳情這類重複讀取則更適合快取。</p>
<h2 id="設計責任">設計責任</h2>
<p>Hit rate 要搭配 latency、下游 query count、cache size 與資料新鮮度一起看。高 hit rate 也要確認資料正確性，因為過期資料命中仍可能造成產品問題。</p>
]]></content:encoded></item><item><title>Cache Warmup</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-warmup/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-warmup/</guid><description>&lt;p>Cache warmup 的核心概念是「在正式流量大量進入前預先載入快取」。它降低 cold start 與 cache miss 對下游造成的尖峰壓力。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Warmup 是快取與部署流程的交界。新 instance、Redis 清空、熱門活動開始或版本切換時，快取可能是空的；warmup 可以先建立高價值資料。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 warmup 的訊號是部署後前幾分鐘 latency 升高，或活動開始時資料庫突然被打滿。大型促銷前，可以預先載入熱門商品、價格與庫存摘要。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Warmup 要定義資料來源、載入順序、速率限制、失敗行為與 readiness 關係。Warmup 本身也會產生下游流量，因此要納入容量規劃。&lt;/p></description><content:encoded><![CDATA[<p>Cache warmup 的核心概念是「在正式流量大量進入前預先載入快取」。它降低 cold start 與 cache miss 對下游造成的尖峰壓力。 可先對照 <a href="/blog/backend/knowledge-cards/cascading-failure/" data-link-title="Cascading Failure" data-link-desc="說明局部故障如何透過等待、重試與資源耗盡擴散到整個系統">Cascading Failure</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Warmup 是快取與部署流程的交界。新 instance、Redis 清空、熱門活動開始或版本切換時，快取可能是空的；warmup 可以先建立高價值資料。 可先對照 <a href="/blog/backend/knowledge-cards/cascading-failure/" data-link-title="Cascading Failure" data-link-desc="說明局部故障如何透過等待、重試與資源耗盡擴散到整個系統">Cascading Failure</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 warmup 的訊號是部署後前幾分鐘 latency 升高，或活動開始時資料庫突然被打滿。大型促銷前，可以預先載入熱門商品、價格與庫存摘要。</p>
<h2 id="設計責任">設計責任</h2>
<p>Warmup 要定義資料來源、載入順序、速率限制、失敗行為與 readiness 關係。Warmup 本身也會產生下游流量，因此要納入容量規劃。</p>
]]></content:encoded></item><item><title>Cache Prefetching</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-prefetching/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-prefetching/</guid><description>&lt;p>Cache prefetching 的核心概念是「根據預期需求提前載入資料」。它讓 request 到來時更可能命中快取，降低使用者等待時間。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">Cache Stampede&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Prefetching 是預測型快取策略。它適合可預期的讀取，例如下一頁資料、熱門商品、使用者登入後常用設定或活動頁資源。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">Cache Stampede&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 prefetching 的訊號是使用者行為有穩定下一步。影片平台可以在使用者接近播放結束時預載下一集資訊；電商可以在活動頁預載熱門商品摘要。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Prefetching 要控制準確率、容量成本、資料新鮮度與下游壓力。預載錯誤資料會浪費 cache 空間，預載過多會擠出真正熱門資料。&lt;/p></description><content:encoded><![CDATA[<p>Cache prefetching 的核心概念是「根據預期需求提前載入資料」。它讓 request 到來時更可能命中快取，降低使用者等待時間。 可先對照 <a href="/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">Cache Stampede</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Prefetching 是預測型快取策略。它適合可預期的讀取，例如下一頁資料、熱門商品、使用者登入後常用設定或活動頁資源。 可先對照 <a href="/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">Cache Stampede</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 prefetching 的訊號是使用者行為有穩定下一步。影片平台可以在使用者接近播放結束時預載下一集資訊；電商可以在活動頁預載熱門商品摘要。</p>
<h2 id="設計責任">設計責任</h2>
<p>Prefetching 要控制準確率、容量成本、資料新鮮度與下游壓力。預載錯誤資料會浪費 cache 空間，預載過多會擠出真正熱門資料。</p>
]]></content:encoded></item><item><title>Cold Start</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cold-start/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cold-start/</guid><description>&lt;p>Cold start 的核心概念是「系統剛啟動或狀態剛清空時，尚未具備穩定運作所需的暖資料」。它可能出現在 application instance、cache、connection pool、JIT runtime、model loading 或 function runtime。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/competing-consumers/" data-link-title="Competing Consumers" data-link-desc="說明多個 consumer 共同處理同一個 queue 如何提高吞吐與影響順序">Competing Consumers&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cold start 是部署、autoscaling、cache warmup 與 readiness 的共同問題。新 instance 若尚未建立連線、載入設定或暖好 cache，就接正式流量，可能造成延遲尖峰。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/competing-consumers/" data-link-title="Competing Consumers" data-link-desc="說明多個 consumer 共同處理同一個 queue 如何提高吞吐與影響順序">Competing Consumers&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要處理 cold start 的訊號是擴容後新 instance 的 latency 明顯高於舊 instance。活動流量來臨時自動擴容，若新 instance 都在建立連線與載入 cache，可能無法立即承擔流量。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Cold start 設計要包含 readiness、warmup、連線預建、流量緩啟與觀測。Autoscaling 設定要考慮啟動到可接流量的真實時間。&lt;/p></description><content:encoded><![CDATA[<p>Cold start 的核心概念是「系統剛啟動或狀態剛清空時，尚未具備穩定運作所需的暖資料」。它可能出現在 application instance、cache、connection pool、JIT runtime、model loading 或 function runtime。 可先對照 <a href="/blog/backend/knowledge-cards/competing-consumers/" data-link-title="Competing Consumers" data-link-desc="說明多個 consumer 共同處理同一個 queue 如何提高吞吐與影響順序">Competing Consumers</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cold start 是部署、autoscaling、cache warmup 與 readiness 的共同問題。新 instance 若尚未建立連線、載入設定或暖好 cache，就接正式流量，可能造成延遲尖峰。 可先對照 <a href="/blog/backend/knowledge-cards/competing-consumers/" data-link-title="Competing Consumers" data-link-desc="說明多個 consumer 共同處理同一個 queue 如何提高吞吐與影響順序">Competing Consumers</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要處理 cold start 的訊號是擴容後新 instance 的 latency 明顯高於舊 instance。活動流量來臨時自動擴容，若新 instance 都在建立連線與載入 cache，可能無法立即承擔流量。</p>
<h2 id="設計責任">設計責任</h2>
<p>Cold start 設計要包含 readiness、warmup、連線預建、流量緩啟與觀測。Autoscaling 設定要考慮啟動到可接流量的真實時間。</p>
]]></content:encoded></item><item><title>Write-Through Cache</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/write-through-cache/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/write-through-cache/</guid><description>&lt;p>Write-through cache 的核心概念是「寫入正式來源時同步更新快取」。它讓後續讀取更容易命中新資料，降低讀取路徑遇到舊資料的機率。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/write-behind-cache/" data-link-title="Write-Behind Cache" data-link-desc="說明先寫快取再非同步寫入正式來源的風險與用途">Write-Behind Cache&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Write-through 是寫入路徑上的快取策略。它適合更新頻率可控、讀取頻繁且資料新鮮度重要的場景；寫入延遲會因同步更新快取而增加。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/write-behind-cache/" data-link-title="Write-Behind Cache" data-link-desc="說明先寫快取再非同步寫入正式來源的風險與用途">Write-Behind Cache&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 write-through 的訊號是寫入後立刻讀取很常見。使用者更新個人設定後，下一個 request 通常會立刻讀取設定摘要；同步更新快取可以降低讀到舊資料的機率。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Write-through 要定義正式來源寫入與快取寫入的錯誤處理。快取寫入失敗時，系統要決定回報失敗、刪除快取、延後修復或讓下一次讀取重建。&lt;/p></description><content:encoded><![CDATA[<p>Write-through cache 的核心概念是「寫入正式來源時同步更新快取」。它讓後續讀取更容易命中新資料，降低讀取路徑遇到舊資料的機率。 可先對照 <a href="/blog/backend/knowledge-cards/write-behind-cache/" data-link-title="Write-Behind Cache" data-link-desc="說明先寫快取再非同步寫入正式來源的風險與用途">Write-Behind Cache</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Write-through 是寫入路徑上的快取策略。它適合更新頻率可控、讀取頻繁且資料新鮮度重要的場景；寫入延遲會因同步更新快取而增加。 可先對照 <a href="/blog/backend/knowledge-cards/write-behind-cache/" data-link-title="Write-Behind Cache" data-link-desc="說明先寫快取再非同步寫入正式來源的風險與用途">Write-Behind Cache</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 write-through 的訊號是寫入後立刻讀取很常見。使用者更新個人設定後，下一個 request 通常會立刻讀取設定摘要；同步更新快取可以降低讀到舊資料的機率。</p>
<h2 id="設計責任">設計責任</h2>
<p>Write-through 要定義正式來源寫入與快取寫入的錯誤處理。快取寫入失敗時，系統要決定回報失敗、刪除快取、延後修復或讓下一次讀取重建。</p>
]]></content:encoded></item><item><title>Write-Behind Cache</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/write-behind-cache/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/write-behind-cache/</guid><description>&lt;p>Write-behind cache 的核心概念是「先把變更寫入快取或緩衝層，再非同步寫入正式來源」。它可以降低使用者等待時間，但會增加資料遺失與一致性風險。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Write-behind 是延後持久化策略。它適合可重建、可補償或低風險資料；金流、訂單正式狀態與權限資料通常需要更強保證。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要評估 write-behind 的訊號是寫入流量很高、正式來源寫入成本高，且短暫延遲可接受。使用者行為計數或 analytics event 可以先進緩衝層，再批次寫入儲存。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Write-behind 要處理 buffer durability、flush、retry、checkpoint、資料遺失、停機與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation&lt;/a>。Runbook 應能查看尚未 flush 的資料量與最舊等待時間。&lt;/p></description><content:encoded><![CDATA[<p>Write-behind cache 的核心概念是「先把變更寫入快取或緩衝層，再非同步寫入正式來源」。它可以降低使用者等待時間，但會增加資料遺失與一致性風險。 可先對照 <a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Write-behind 是延後持久化策略。它適合可重建、可補償或低風險資料；金流、訂單正式狀態與權限資料通常需要更強保證。 可先對照 <a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要評估 write-behind 的訊號是寫入流量很高、正式來源寫入成本高，且短暫延遲可接受。使用者行為計數或 analytics event 可以先進緩衝層，再批次寫入儲存。</p>
<h2 id="設計責任">設計責任</h2>
<p>Write-behind 要處理 buffer durability、flush、retry、checkpoint、資料遺失、停機與 <a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation</a>。Runbook 應能查看尚未 flush 的資料量與最舊等待時間。</p>
]]></content:encoded></item><item><title>Stale Data</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/stale-data/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/stale-data/</guid><description>&lt;p>Stale data 的核心概念是「資料已落後於正式來源，但仍被讀取或展示」。它可能來自 cache、replica、search index、read model、CDN 或前端本地狀態。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/status-page/" data-link-title="Status Page" data-link-desc="說明事故期間對外狀態頁如何承接可用性承諾">Status Page&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Stale data 是一致性與使用者體驗的交界。某些資料過期可接受，例如推薦列表；某些資料過期會造成交易或安全問題，例如價格、庫存、權限。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/status-page/" data-link-title="Status Page" data-link-desc="說明事故期間對外狀態頁如何承接可用性承諾">Status Page&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 stale data 設計的訊號是使用者在不同頁面看到不同狀態。商品列表顯示舊價格，結帳頁顯示新價格，這需要明確定義哪個頁面可以接受延遲。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Stale data 策略要定義可接受延遲、正式來源、顯示文案、強制刷新與修復流程。高風險資料應避免長時間依賴 stale 副本。&lt;/p></description><content:encoded><![CDATA[<p>Stale data 的核心概念是「資料已落後於正式來源，但仍被讀取或展示」。它可能來自 cache、replica、search index、read model、CDN 或前端本地狀態。 可先對照 <a href="/blog/backend/knowledge-cards/status-page/" data-link-title="Status Page" data-link-desc="說明事故期間對外狀態頁如何承接可用性承諾">Status Page</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Stale data 是一致性與使用者體驗的交界。某些資料過期可接受，例如推薦列表；某些資料過期會造成交易或安全問題，例如價格、庫存、權限。 可先對照 <a href="/blog/backend/knowledge-cards/status-page/" data-link-title="Status Page" data-link-desc="說明事故期間對外狀態頁如何承接可用性承諾">Status Page</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 stale data 設計的訊號是使用者在不同頁面看到不同狀態。商品列表顯示舊價格，結帳頁顯示新價格，這需要明確定義哪個頁面可以接受延遲。</p>
<h2 id="設計責任">設計責任</h2>
<p>Stale data 策略要定義可接受延遲、正式來源、顯示文案、強制刷新與修復流程。高風險資料應避免長時間依賴 stale 副本。</p>
]]></content:encoded></item><item><title>Soft TTL</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/soft-ttl/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/soft-ttl/</guid><description>&lt;p>Soft TTL 的核心概念是「資料過了建議刷新時間後仍可短暫使用，同時觸發背景刷新」。它讓系統在資料需要更新時仍保留可用結果，降低 cache stampede 風險。 可先對照 &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;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Soft TTL 把過期分成可用刷新期與硬過期點。資料進入刷新期後仍可回應部分 request，並由背景流程重建；到達硬過期點後則停止使用該副本。 可先對照 &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;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 soft TTL 的訊號是熱門資料過期時大量 request 同時打向正式來源。熱門排行榜可以在 soft TTL 到期後先回傳舊榜單，同時觸發背景刷新。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Soft TTL 要定義最大 stale 時間、刷新 owner、失敗重試與使用者可接受程度。觀測上要看 stale response 次數、刷新耗時與刷新失敗率。&lt;/p></description><content:encoded><![CDATA[<p>Soft TTL 的核心概念是「資料過了建議刷新時間後仍可短暫使用，同時觸發背景刷新」。它讓系統在資料需要更新時仍保留可用結果，降低 cache stampede 風險。 可先對照 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">Source of Truth</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Soft TTL 把過期分成可用刷新期與硬過期點。資料進入刷新期後仍可回應部分 request，並由背景流程重建；到達硬過期點後則停止使用該副本。 可先對照 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">Source of Truth</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 soft TTL 的訊號是熱門資料過期時大量 request 同時打向正式來源。熱門排行榜可以在 soft TTL 到期後先回傳舊榜單，同時觸發背景刷新。</p>
<h2 id="設計責任">設計責任</h2>
<p>Soft TTL 要定義最大 stale 時間、刷新 owner、失敗重試與使用者可接受程度。觀測上要看 stale response 次數、刷新耗時與刷新失敗率。</p>
]]></content:encoded></item><item><title>Singleflight</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/singleflight/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/singleflight/</guid><description>&lt;p>Singleflight 的核心概念是「相同 key 的並發工作只讓一個執行者真正打下游，其餘等待同一份結果」。它用來降低 cache miss、重建資料或初始化時的重複下游壓力。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Singleflight 是 cache stampede 與 thundering herd 的防護工具。它適合相同 key、相同結果、短時間內大量重複請求的場景。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 singleflight 的訊號是熱門 key 過期後，同時有大量 request 查同一筆資料。商品詳情 cache miss 時，只需要一個 request 回資料庫查詢，其他 request 等待同一結果。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Singleflight 要定義 key、等待 timeout、錯誤分享策略與結果快取方式。若下游查詢失敗，系統要決定所有等待者都失敗，或部分使用 stale data。&lt;/p></description><content:encoded><![CDATA[<p>Singleflight 的核心概念是「相同 key 的並發工作只讓一個執行者真正打下游，其餘等待同一份結果」。它用來降低 cache miss、重建資料或初始化時的重複下游壓力。 可先對照 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI / SLO</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Singleflight 是 cache stampede 與 thundering herd 的防護工具。它適合相同 key、相同結果、短時間內大量重複請求的場景。 可先對照 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI / SLO</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 singleflight 的訊號是熱門 key 過期後，同時有大量 request 查同一筆資料。商品詳情 cache miss 時，只需要一個 request 回資料庫查詢，其他 request 等待同一結果。</p>
<h2 id="設計責任">設計責任</h2>
<p>Singleflight 要定義 key、等待 timeout、錯誤分享策略與結果快取方式。若下游查詢失敗，系統要決定所有等待者都失敗，或部分使用 stale data。</p>
]]></content:encoded></item><item><title>Histogram</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/histogram/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/histogram/</guid><description>&lt;p>Histogram 的核心概念是「把觀測值分到多個 bucket，記錄每個範圍的累積數量」。它是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics&lt;/a> 中描述分布的工具，常用來觀察 latency、request size、payload size、queue wait time 與處理耗時，支援 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/percentile/" data-link-title="Percentile" data-link-desc="說明 p95 與 p99 如何描述長尾延遲與使用者體驗">percentile&lt;/a> 計算。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Histogram 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics&lt;/a> 中描述分布的工具，跟 counter（計數）跟 gauge（瞬間值）互補。Average 只能說明中心趨勢；histogram 可以支援 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/percentile/" data-link-title="Percentile" data-link-desc="說明 p95 與 p99 如何描述長尾延遲與使用者體驗">percentile&lt;/a>（p95 / p99）、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI&lt;/a> 計算跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">burn rate&lt;/a> 判斷。&lt;/p>
&lt;p>Prometheus 的 histogram 用累積 bucket（&lt;code>le&lt;/code> label）實作 — 每個 bucket 記錄「值 &amp;lt;= le 的觀測次數」。PromQL 的 &lt;code>histogram_quantile()&lt;/code> 從 bucket 資料估算 percentile。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 histogram 的訊號是少數慢 request 會影響使用者體驗但 average 看不出來。Checkout 平均延遲 100ms 看起來良好，但 p99 若超過 3 秒，1% 的使用者體驗極差。Histogram 讓這個長尾可見。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Histogram bucket boundary 要依 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLO&lt;/a> 閾值跟實際延遲範圍設計。Bucket 太粗（只有 100ms / 500ms / 1s）會讓 percentile 估計跳躍式變化；太細會增加 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">cardinality&lt;/a>（每個 bucket 是一條 time series）。常見做法是在 SLO 閾值附近密集、在兩端稀疏。詳見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">4.2 metrics basics&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Histogram 的核心概念是「把觀測值分到多個 bucket，記錄每個範圍的累積數量」。它是 <a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics</a> 中描述分布的工具，常用來觀察 latency、request size、payload size、queue wait time 與處理耗時，支援 <a href="/blog/backend/knowledge-cards/percentile/" data-link-title="Percentile" data-link-desc="說明 p95 與 p99 如何描述長尾延遲與使用者體驗">percentile</a> 計算。</p>
<h2 id="概念位置">概念位置</h2>
<p>Histogram 是 <a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics</a> 中描述分布的工具，跟 counter（計數）跟 gauge（瞬間值）互補。Average 只能說明中心趨勢；histogram 可以支援 <a href="/blog/backend/knowledge-cards/percentile/" data-link-title="Percentile" data-link-desc="說明 p95 與 p99 如何描述長尾延遲與使用者體驗">percentile</a>（p95 / p99）、<a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI</a> 計算跟 <a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">burn rate</a> 判斷。</p>
<p>Prometheus 的 histogram 用累積 bucket（<code>le</code> label）實作 — 每個 bucket 記錄「值 &lt;= le 的觀測次數」。PromQL 的 <code>histogram_quantile()</code> 從 bucket 資料估算 percentile。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 histogram 的訊號是少數慢 request 會影響使用者體驗但 average 看不出來。Checkout 平均延遲 100ms 看起來良好，但 p99 若超過 3 秒，1% 的使用者體驗極差。Histogram 讓這個長尾可見。</p>
<h2 id="設計責任">設計責任</h2>
<p>Histogram bucket boundary 要依 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLO</a> 閾值跟實際延遲範圍設計。Bucket 太粗（只有 100ms / 500ms / 1s）會讓 percentile 估計跳躍式變化；太細會增加 <a href="/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">cardinality</a>（每個 bucket 是一條 time series）。常見做法是在 SLO 閾值附近密集、在兩端稀疏。詳見 <a href="/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">4.2 metrics basics</a>。</p>
]]></content:encoded></item><item><title>Bucket</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/bucket/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/bucket/</guid><description>&lt;p>Bucket 的核心概念是「histogram 中用來統計觀測值範圍的界線」。每個 bucket 代表小於等於某個上限的觀測值累積數。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">Buffer&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Bucket 是 histogram 可用性的關鍵。Bucket 應圍繞 SLO 門檻與常見延遲分布設計；錯誤 bucket 會讓 dashboard 看起來有資料，卻回答不了服務是否達標。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">Buffer&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要調整 bucket 的訊號是 p95 / p99 查詢不穩，或 SLO 門檻附近缺乏解析度。若 checkout SLO 是 300ms，bucket 應在 100ms、200ms、300ms、500ms 附近提供足夠區分。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Bucket 設計要平衡解析度與 cardinality。不同 endpoint 或任務類型可能需要不同 bucket，但過多自訂 bucket 會增加儲存與查詢成本。&lt;/p></description><content:encoded><![CDATA[<p>Bucket 的核心概念是「histogram 中用來統計觀測值範圍的界線」。每個 bucket 代表小於等於某個上限的觀測值累積數。 可先對照 <a href="/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">Buffer</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Bucket 是 histogram 可用性的關鍵。Bucket 應圍繞 SLO 門檻與常見延遲分布設計；錯誤 bucket 會讓 dashboard 看起來有資料，卻回答不了服務是否達標。 可先對照 <a href="/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">Buffer</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要調整 bucket 的訊號是 p95 / p99 查詢不穩，或 SLO 門檻附近缺乏解析度。若 checkout SLO 是 300ms，bucket 應在 100ms、200ms、300ms、500ms 附近提供足夠區分。</p>
<h2 id="設計責任">設計責任</h2>
<p>Bucket 設計要平衡解析度與 cardinality。不同 endpoint 或任務類型可能需要不同 bucket，但過多自訂 bucket 會增加儲存與查詢成本。</p>
]]></content:encoded></item><item><title>Percentile</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/percentile/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/percentile/</guid><description>&lt;p>Percentile 的核心概念是「某比例的觀測值低於某個門檻」。p95 latency 表示 95% 的 request 延遲低於該值；p99 觀察更長尾的慢請求。Percentile 描述的是分布的尾端，從 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/histogram/" data-link-title="Histogram" data-link-desc="說明 histogram 如何用分桶統計延遲、大小與分布">histogram&lt;/a> 資料計算而來，用來捕捉 average 掩蓋的使用者體驗問題。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Percentile 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/histogram/" data-link-title="Histogram" data-link-desc="說明 histogram 如何用分桶統計延遲、大小與分布">histogram&lt;/a> 搭配使用。Histogram 記錄延遲分布（哪些 bucket 收到多少 request），percentile 從 histogram 資料計算（&lt;code>histogram_quantile&lt;/code> in PromQL）。Average latency 看不到長尾 — 平均 80ms 但 p99 是 2 秒，代表 1% 的使用者體驗極差。&lt;/p>
&lt;p>Percentile 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI&lt;/a> 的常見型別 — latency SLI 用「p99 &amp;lt; 500ms 的 request 佔比」量化使用者體驗。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 percentile 的訊號是 average latency 穩定但使用者仍回報卡頓。搜尋 API 平均 80ms、p99 2 秒，表示少數 request 走到慢查詢或下游 timeout。高流量服務的 1%（p99 以外）可能代表數千個使用者。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Percentile 要搭配 histogram bucket 設計 — bucket boundary 決定 percentile 計算的精度。Bucket 太少（只有 100ms / 500ms / 1s）會讓 p99 的估計跳躍式變化。Bucket 太多會增加 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">cardinality&lt;/a>。低流量服務的高 percentile 容易受少量樣本影響，alert 閾值要考慮統計穩定性。詳見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">4.2 metrics basics&lt;/a> 跟 &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.6 SLI/SLO 訊號設計&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Percentile 的核心概念是「某比例的觀測值低於某個門檻」。p95 latency 表示 95% 的 request 延遲低於該值；p99 觀察更長尾的慢請求。Percentile 描述的是分布的尾端，從 <a href="/blog/backend/knowledge-cards/histogram/" data-link-title="Histogram" data-link-desc="說明 histogram 如何用分桶統計延遲、大小與分布">histogram</a> 資料計算而來，用來捕捉 average 掩蓋的使用者體驗問題。</p>
<h2 id="概念位置">概念位置</h2>
<p>Percentile 跟 <a href="/blog/backend/knowledge-cards/histogram/" data-link-title="Histogram" data-link-desc="說明 histogram 如何用分桶統計延遲、大小與分布">histogram</a> 搭配使用。Histogram 記錄延遲分布（哪些 bucket 收到多少 request），percentile 從 histogram 資料計算（<code>histogram_quantile</code> in PromQL）。Average latency 看不到長尾 — 平均 80ms 但 p99 是 2 秒，代表 1% 的使用者體驗極差。</p>
<p>Percentile 是 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI</a> 的常見型別 — latency SLI 用「p99 &lt; 500ms 的 request 佔比」量化使用者體驗。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 percentile 的訊號是 average latency 穩定但使用者仍回報卡頓。搜尋 API 平均 80ms、p99 2 秒，表示少數 request 走到慢查詢或下游 timeout。高流量服務的 1%（p99 以外）可能代表數千個使用者。</p>
<h2 id="設計責任">設計責任</h2>
<p>Percentile 要搭配 histogram bucket 設計 — bucket boundary 決定 percentile 計算的精度。Bucket 太少（只有 100ms / 500ms / 1s）會讓 p99 的估計跳躍式變化。Bucket 太多會增加 <a href="/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">cardinality</a>。低流量服務的高 percentile 容易受少量樣本影響，alert 閾值要考慮統計穩定性。詳見 <a href="/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">4.2 metrics basics</a> 跟 <a href="/blog/backend/04-observability/sli-slo-signal/" data-link-title="4.6 SLI 量測與 SLO 訊號設計" data-link-desc="把可靠性目標的訊號從 metric 端設計好、餵給 6.6 SLO 政策">4.6 SLI/SLO 訊號設計</a>。</p>
]]></content:encoded></item><item><title>Error Budget</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/error-budget/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/error-budget/</guid><description>&lt;p>Error budget 的核心概念是「&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLO&lt;/a> 允許的失敗額度」。SLO = 99.9% 代表 30 天內允許 0.1% 的 request 失敗；這 0.1% 就是 error budget，用來平衡功能交付速度與可靠性改善投入。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Error budget 把可靠性討論轉成可量化的決策語言。Budget 消耗過快時，團隊應暫停高風險變更、優先修可靠性；budget 充足時，可以承擔更多變更風險跟 experiment。&lt;/p>
&lt;p>Error budget 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">burn rate&lt;/a> alerting 的基礎 — burn rate 量化的是 error budget 被消耗的速度。Error budget 接近耗盡時，進入 &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> 的 freeze 條件。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 error budget 的訊號是發版速度與事故風險需要共同管理。Checkout 服務本月多次 timeout，若 error budget 已接近耗盡，團隊應暫停高風險變更直到 budget 恢復。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Error budget 的 metric 結構需要 rolling window 的 total requests 跟 failed requests（見 &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.6 SLI/SLO 訊號設計&lt;/a>）。Budget remaining 作為 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a> panel 跟 release gate 的輸入 — 用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule&lt;/a> 維護 rolling window 計算，避免每次查詢掃描 30 天的 raw data。&lt;/p></description><content:encoded><![CDATA[<p>Error budget 的核心概念是「<a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLO</a> 允許的失敗額度」。SLO = 99.9% 代表 30 天內允許 0.1% 的 request 失敗；這 0.1% 就是 error budget，用來平衡功能交付速度與可靠性改善投入。</p>
<h2 id="概念位置">概念位置</h2>
<p>Error budget 把可靠性討論轉成可量化的決策語言。Budget 消耗過快時，團隊應暫停高風險變更、優先修可靠性；budget 充足時，可以承擔更多變更風險跟 experiment。</p>
<p>Error budget 是 <a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">burn rate</a> alerting 的基礎 — burn rate 量化的是 error budget 被消耗的速度。Error budget 接近耗盡時，進入 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">release gate</a> 的 freeze 條件。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 error budget 的訊號是發版速度與事故風險需要共同管理。Checkout 服務本月多次 timeout，若 error budget 已接近耗盡，團隊應暫停高風險變更直到 budget 恢復。</p>
<h2 id="設計責任">設計責任</h2>
<p>Error budget 的 metric 結構需要 rolling window 的 total requests 跟 failed requests（見 <a href="/blog/backend/04-observability/sli-slo-signal/" data-link-title="4.6 SLI 量測與 SLO 訊號設計" data-link-desc="把可靠性目標的訊號從 metric 端設計好、餵給 6.6 SLO 政策">4.6 SLI/SLO 訊號設計</a>）。Budget remaining 作為 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> panel 跟 release gate 的輸入 — 用 <a href="/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule</a> 維護 rolling window 計算，避免每次查詢掃描 30 天的 raw data。</p>
]]></content:encoded></item><item><title>Burn Rate</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/burn-rate/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/burn-rate/</guid><description>&lt;p>Burn rate 的核心概念是「&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> 被消耗的速度」。Burn rate = 1 代表按 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLO&lt;/a> 允許的速度正常消耗；burn rate = 10 代表消耗速度是允許值的 10 倍 — 如果持續下去，error budget 會在 SLO 週期的 1/10 內耗盡。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Burn rate 是 SLO alerting 的核心機制，把 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI&lt;/a> 的 error ratio 轉成可行動的嚴重度判斷。短時間高 burn rate（14x、5 分鐘窗口）代表急性事故；長時間中等 burn rate（1x、數小時窗口）代表慢性可靠性退化。&lt;/p>
&lt;p>Burn rate alerting 比固定閾值 alert 更能反映使用者影響 — 低流量時段的幾筆 error 可能 burn rate 很低（對 error budget 影響小），高流量時段的相同 error rate 可能 burn rate 很高（影響大量使用者）。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 burn rate 的訊號是固定閾值 alert（error rate &amp;gt; 1%）在不同流量時段的表現不穩定 — 低流量時 false alarm、高流量時漏報。Burn rate 自動適應流量基線。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Burn rate alerting 用 multi-window 策略：短窗口（5min）抓急性 + 長窗口（1hr）做確認，兩個窗口都超過閾值才觸發。Recording rule 預計算各窗口的 error ratio，讓 alert evaluate 讀預計算結果而非重算 raw series。完整設計見 &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.6 SLI/SLO 訊號設計&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Burn rate 的核心概念是「<a href="/blog/backend/knowledge-cards/error-budget/" data-link-title="Error Budget" data-link-desc="說明 SLO 允許的失敗額度如何影響發版與可靠性投入">error budget</a> 被消耗的速度」。Burn rate = 1 代表按 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLO</a> 允許的速度正常消耗；burn rate = 10 代表消耗速度是允許值的 10 倍 — 如果持續下去，error budget 會在 SLO 週期的 1/10 內耗盡。</p>
<h2 id="概念位置">概念位置</h2>
<p>Burn rate 是 SLO alerting 的核心機制，把 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI</a> 的 error ratio 轉成可行動的嚴重度判斷。短時間高 burn rate（14x、5 分鐘窗口）代表急性事故；長時間中等 burn rate（1x、數小時窗口）代表慢性可靠性退化。</p>
<p>Burn rate alerting 比固定閾值 alert 更能反映使用者影響 — 低流量時段的幾筆 error 可能 burn rate 很低（對 error budget 影響小），高流量時段的相同 error rate 可能 burn rate 很高（影響大量使用者）。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 burn rate 的訊號是固定閾值 alert（error rate &gt; 1%）在不同流量時段的表現不穩定 — 低流量時 false alarm、高流量時漏報。Burn rate 自動適應流量基線。</p>
<h2 id="設計責任">設計責任</h2>
<p>Burn rate alerting 用 multi-window 策略：短窗口（5min）抓急性 + 長窗口（1hr）做確認，兩個窗口都超過閾值才觸發。Recording rule 預計算各窗口的 error ratio，讓 alert evaluate 讀預計算結果而非重算 raw series。完整設計見 <a href="/blog/backend/04-observability/sli-slo-signal/" data-link-title="4.6 SLI 量測與 SLO 訊號設計" data-link-desc="把可靠性目標的訊號從 metric 端設計好、餵給 6.6 SLO 政策">4.6 SLI/SLO 訊號設計</a>。</p>
]]></content:encoded></item><item><title>Sampling</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/sampling/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/sampling/</guid><description>&lt;p>Sampling 的核心概念是「只保留部分觀測資料」。高流量系統若收集所有 log、trace 或事件，成本與查詢壓力可能快速上升；sampling 用代表性資料保留診斷能力。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">Schema Migration&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Sampling 是觀測成本控制工具。它可以是固定比例、依錯誤保留、依延遲保留、依 tenant 保留或 adaptive sampling。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">Schema Migration&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 sampling 的訊號是 trace 或 log 成本隨流量快速成長。Checkout 成功 request 可低比例採樣，錯誤與高延遲 request 則應提高保留率。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Sampling 要定義保留規則、偏差、查詢限制與事故期間調整方式。抽樣後的資料適合診斷趨勢，但某些 audit 或法規資料需要完整保留。&lt;/p>
&lt;p>監控 SDK 中靜態取樣和動態取樣（背壓觸發）的具體實作見 &lt;a href="https://tarrragon.github.io/blog/monitoring/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="在事件產生階段按比例丟棄部分事件降低管線負載 — 分靜態取樣（config 固定比例）和動態取樣（背壓觸發自動降低）">監控知識卡：Sampling&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Sampling 的核心概念是「只保留部分觀測資料」。高流量系統若收集所有 log、trace 或事件，成本與查詢壓力可能快速上升；sampling 用代表性資料保留診斷能力。 可先對照 <a href="/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">Schema Migration</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Sampling 是觀測成本控制工具。它可以是固定比例、依錯誤保留、依延遲保留、依 tenant 保留或 adaptive sampling。 可先對照 <a href="/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">Schema Migration</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 sampling 的訊號是 trace 或 log 成本隨流量快速成長。Checkout 成功 request 可低比例採樣，錯誤與高延遲 request 則應提高保留率。</p>
<h2 id="設計責任">設計責任</h2>
<p>Sampling 要定義保留規則、偏差、查詢限制與事故期間調整方式。抽樣後的資料適合診斷趨勢，但某些 audit 或法規資料需要完整保留。</p>
<p>監控 SDK 中靜態取樣和動態取樣（背壓觸發）的具體實作見 <a href="/blog/monitoring/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="在事件產生階段按比例丟棄部分事件降低管線負載 — 分靜態取樣（config 固定比例）和動態取樣（背壓觸發自動降低）">監控知識卡：Sampling</a>。</p>
]]></content:encoded></item><item><title>Correlation ID</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/correlation-id/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/correlation-id/</guid><description>&lt;p>Correlation ID 的核心概念是「把同一個業務流程中的多筆紀錄關聯起來的識別碼」。它是 &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> 的核心欄位，可以跨 request、queue message、background job、log、trace 與外部 API 呼叫。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Correlation ID 跟 &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> 的定位不同。Trace id 偏向一次技術呼叫路徑（一個 HTTP request 經過多個服務）；correlation ID 可以代表更長的業務流程（一筆訂單從建立到付款到出貨，跨越多個獨立 request）。&lt;/p>
&lt;p>Correlation ID 是 &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> 的核心欄位。Log 帶 correlation ID 時，跨服務跟跨 async 邊界的事件可以用同一個 ID 查出完整業務流程。見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/log-schema/" data-link-title="4.1 log schema 與搜尋規劃" data-link-desc="整理 log 欄位、索引與搜尋策略">4.1 log schema&lt;/a>。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 correlation ID 的訊號是事故排查需要跨同步與非同步邊界。訂單建立 request、付款事件、寄信 job 與出貨事件共享同一 correlation ID，讓客服跟工程師追到完整流程。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Correlation ID 要在入口（API gateway 或 first service）建立或從 upstream 接收，並傳遞到 log、message header、trace context 與外部呼叫。欄位名稱要穩定（跨服務一致，避免 &lt;code>request_id&lt;/code> vs &lt;code>req_id&lt;/code> vs &lt;code>requestId&lt;/code> 的漂移），避免把敏感資料當成 ID。&lt;/p></description><content:encoded><![CDATA[<p>Correlation ID 的核心概念是「把同一個業務流程中的多筆紀錄關聯起來的識別碼」。它是 <a href="/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">log schema</a> 的核心欄位，可以跨 request、queue message、background job、log、trace 與外部 API 呼叫。</p>
<h2 id="概念位置">概念位置</h2>
<p>Correlation ID 跟 <a href="/blog/backend/knowledge-cards/trace-id/" data-link-title="Trace ID" data-link-desc="說明分散式追蹤中同一條呼叫路徑的識別碼">trace id</a> 的定位不同。Trace id 偏向一次技術呼叫路徑（一個 HTTP request 經過多個服務）；correlation ID 可以代表更長的業務流程（一筆訂單從建立到付款到出貨，跨越多個獨立 request）。</p>
<p>Correlation ID 是 <a href="/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">log schema</a> 的核心欄位。Log 帶 correlation ID 時，跨服務跟跨 async 邊界的事件可以用同一個 ID 查出完整業務流程。見 <a href="/blog/backend/04-observability/log-schema/" data-link-title="4.1 log schema 與搜尋規劃" data-link-desc="整理 log 欄位、索引與搜尋策略">4.1 log schema</a>。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 correlation ID 的訊號是事故排查需要跨同步與非同步邊界。訂單建立 request、付款事件、寄信 job 與出貨事件共享同一 correlation ID，讓客服跟工程師追到完整流程。</p>
<h2 id="設計責任">設計責任</h2>
<p>Correlation ID 要在入口（API gateway 或 first service）建立或從 upstream 接收，並傳遞到 log、message header、trace context 與外部呼叫。欄位名稱要穩定（跨服務一致，避免 <code>request_id</code> vs <code>req_id</code> vs <code>requestId</code> 的漂移），避免把敏感資料當成 ID。</p>
]]></content:encoded></item><item><title>Request ID</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/request-id/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/request-id/</guid><description>&lt;p>Request ID 的核心概念是「識別單次 request 的 ID」。它讓同一個 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>、application、database log 與 error response 之間可以被追蹤。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Request ID 是同步 request 診斷的基本欄位。它通常比 trace 簡單，適合放在 log、response header 與客服查詢流程中。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 request ID 的訊號是使用者回報錯誤時，工程師需要快速找到對應 log。錯誤頁顯示 request ID，客服可以把 ID 交給工程師查完整處理路徑。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Request ID 要在入口統一產生或接受可信上游傳入，並在 response、log、trace 與下游呼叫中保留。安全設計要避免讓外部可控 ID 汙染內部查詢或造成 spoofing。&lt;/p></description><content:encoded><![CDATA[<p>Request ID 的核心概念是「識別單次 request 的 ID」。它讓同一個 request 在 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>、application、database log 與 error response 之間可以被追蹤。</p>
<h2 id="概念位置">概念位置</h2>
<p>Request ID 是同步 request 診斷的基本欄位。它通常比 trace 簡單，適合放在 log、response header 與客服查詢流程中。 可先對照 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 request ID 的訊號是使用者回報錯誤時，工程師需要快速找到對應 log。錯誤頁顯示 request ID，客服可以把 ID 交給工程師查完整處理路徑。</p>
<h2 id="設計責任">設計責任</h2>
<p>Request ID 要在入口統一產生或接受可信上游傳入，並在 response、log、trace 與下游呼叫中保留。安全設計要避免讓外部可控 ID 汙染內部查詢或造成 spoofing。</p>
]]></content:encoded></item><item><title>Trace ID</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/trace-id/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/trace-id/</guid><description>&lt;p>Trace ID 的核心概念是「分散式追蹤中同一條呼叫路徑的全域識別碼」。一個 &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/span/" data-link-title="Span" data-link-desc="說明 trace 中一段工作如何記錄耗時、狀態與關聯">span&lt;/a> 組成，trace ID 讓 tracing 系統把散落在不同服務的 span 聚合成同一次操作的完整路徑。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Trace ID 是 tracing 的頂層關聯欄位。W3C Trace Context 標準使用 128-bit 隨機值（32 hex chars）；部分 vendor 使用 64-bit（Datadog 舊版、Zipkin v1）。混用不同長度時需要在 collector 層做 ID 轉換或 padding。&lt;/p>
&lt;p>Trace 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> 的定位不同：request id 是單一服務內的請求識別碼（通常由 API gateway 或 load balancer 產生），trace id 是跨服務的追蹤識別碼（由第一個 instrumented service 產生）。兩者可以共存在同一筆 log 的不同欄位，各自服務不同的查詢需求。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>Trace ID 的診斷價值是「拿到一個 ID 就能看到整條 request 路徑」。事故中從 error log 拿到 trace ID，貼進 tracing UI（Jaeger、Grafana Tempo、Datadog APM），直接看 waterfall view 定位瓶頸。&lt;/p>
&lt;p>Trace ID 也是 log / metric / trace 三者的關聯樞紐。Log 的結構化欄位帶 trace ID 時，debug 工作流可以從 log → trace 或 trace → log 雙向跳轉。Metric 的 exemplar 帶 trace ID 時，可以從 dashboard 的 latency spike 跳到具體的高延遲 trace。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Trace ID 要透過 &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> 在 HTTP header、queue message header、thread context 上傳遞。Log 層面，trace ID 應作為必要欄位寫入 structured log（見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/log-schema/" data-link-title="4.1 log schema 與搜尋規劃" data-link-desc="整理 log 欄位、索引與搜尋策略">4.1 log schema&lt;/a>）。Sampling 策略要確保錯誤與高延遲 trace 有足夠保留率，避免事故時 trace ID 存在於 log 但對應的 trace 資料已被 sampling 丟棄。&lt;/p></description><content:encoded><![CDATA[<p>Trace ID 的核心概念是「分散式追蹤中同一條呼叫路徑的全域識別碼」。一個 <a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a> 由多個 <a href="/blog/backend/knowledge-cards/span/" data-link-title="Span" data-link-desc="說明 trace 中一段工作如何記錄耗時、狀態與關聯">span</a> 組成，trace ID 讓 tracing 系統把散落在不同服務的 span 聚合成同一次操作的完整路徑。</p>
<h2 id="概念位置">概念位置</h2>
<p>Trace ID 是 tracing 的頂層關聯欄位。W3C Trace Context 標準使用 128-bit 隨機值（32 hex chars）；部分 vendor 使用 64-bit（Datadog 舊版、Zipkin v1）。混用不同長度時需要在 collector 層做 ID 轉換或 padding。</p>
<p>Trace ID 跟 <a href="/blog/backend/knowledge-cards/request-id/" data-link-title="Request ID" data-link-desc="說明單次 request 的識別碼如何支援 log 搜尋與問題定位">request id</a> 的定位不同：request id 是單一服務內的請求識別碼（通常由 API gateway 或 load balancer 產生），trace id 是跨服務的追蹤識別碼（由第一個 instrumented service 產生）。兩者可以共存在同一筆 log 的不同欄位，各自服務不同的查詢需求。</p>
<h2 id="使用情境">使用情境</h2>
<p>Trace ID 的診斷價值是「拿到一個 ID 就能看到整條 request 路徑」。事故中從 error log 拿到 trace ID，貼進 tracing UI（Jaeger、Grafana Tempo、Datadog APM），直接看 waterfall view 定位瓶頸。</p>
<p>Trace ID 也是 log / metric / trace 三者的關聯樞紐。Log 的結構化欄位帶 trace ID 時，debug 工作流可以從 log → trace 或 trace → log 雙向跳轉。Metric 的 exemplar 帶 trace ID 時，可以從 dashboard 的 latency spike 跳到具體的高延遲 trace。</p>
<h2 id="設計責任">設計責任</h2>
<p>Trace ID 要透過 <a href="/blog/backend/knowledge-cards/trace-context/" data-link-title="Trace Context" data-link-desc="說明跨服務 request 如何用 trace context 串起路徑與耗時">trace context</a> 在 HTTP header、queue message header、thread context 上傳遞。Log 層面，trace ID 應作為必要欄位寫入 structured log（見 <a href="/blog/backend/04-observability/log-schema/" data-link-title="4.1 log schema 與搜尋規劃" data-link-desc="整理 log 欄位、索引與搜尋策略">4.1 log schema</a>）。Sampling 策略要確保錯誤與高延遲 trace 有足夠保留率，避免事故時 trace ID 存在於 log 但對應的 trace 資料已被 sampling 丟棄。</p>
]]></content:encoded></item><item><title>Span</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/span/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/span/</guid><description>&lt;p>Span 的核心概念是「&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace&lt;/a> 中的一段有起止時間的工作」。每個 span 記錄操作名稱、開始與結束時間、狀態（OK / Error）、屬性（service name、http.status_code、db.statement）與事件（exception message）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Span 是 tracing 的基本單位。HTTP handler、database query、cache call、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a> publish、consumer handle 與外部 API 呼叫都可以形成 span。Span 之間透過 parent-child 關係組成 tree — 共享同一個 &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> 的所有 span 構成一條完整的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace&lt;/a>。&lt;/p>
&lt;p>Span 有四種 kind：&lt;code>CLIENT&lt;/code>（發起呼叫）、&lt;code>SERVER&lt;/code>（接收呼叫）、&lt;code>PRODUCER&lt;/code>（投遞訊息）、&lt;code>CONSUMER&lt;/code>（消費訊息）。Kind 影響 trace backend 怎麼計算 service-to-service 的延遲跟依賴方向。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 span 的訊號是單一 request 裡有多個步驟，需要知道哪一步變慢或出錯。Checkout trace 中 payment span 佔 80% 時間，問題焦點就落在付款依賴或其網路路徑。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Span 設計要控制名稱粒度、屬性選擇、錯誤狀態與敏感資料。Span 名稱太粗（所有 HTTP call 都叫 &lt;code>HTTP&lt;/code>）會看不出瓶頸；太細（每個 URL path parameter 都獨立命名）會讓 span 名稱成為無界維度、影響 trace backend 的聚合效能。&lt;/p>
&lt;p>屬性要帶足夠的診斷資訊但避免敏感資料。&lt;code>http.url&lt;/code> 帶完整 URL 可能含 query parameter 裡的 token；&lt;code>db.statement&lt;/code> 帶完整 SQL 可能含使用者資料。需要在 SDK 或 collector 層做 redaction。&lt;/p></description><content:encoded><![CDATA[<p>Span 的核心概念是「<a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a> 中的一段有起止時間的工作」。每個 span 記錄操作名稱、開始與結束時間、狀態（OK / Error）、屬性（service name、http.status_code、db.statement）與事件（exception message）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Span 是 tracing 的基本單位。HTTP handler、database query、cache call、<a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> publish、consumer handle 與外部 API 呼叫都可以形成 span。Span 之間透過 parent-child 關係組成 tree — 共享同一個 <a href="/blog/backend/knowledge-cards/trace-id/" data-link-title="Trace ID" data-link-desc="說明分散式追蹤中同一條呼叫路徑的識別碼">trace id</a> 的所有 span 構成一條完整的 <a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a>。</p>
<p>Span 有四種 kind：<code>CLIENT</code>（發起呼叫）、<code>SERVER</code>（接收呼叫）、<code>PRODUCER</code>（投遞訊息）、<code>CONSUMER</code>（消費訊息）。Kind 影響 trace backend 怎麼計算 service-to-service 的延遲跟依賴方向。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 span 的訊號是單一 request 裡有多個步驟，需要知道哪一步變慢或出錯。Checkout trace 中 payment span 佔 80% 時間，問題焦點就落在付款依賴或其網路路徑。</p>
<h2 id="設計責任">設計責任</h2>
<p>Span 設計要控制名稱粒度、屬性選擇、錯誤狀態與敏感資料。Span 名稱太粗（所有 HTTP call 都叫 <code>HTTP</code>）會看不出瓶頸；太細（每個 URL path parameter 都獨立命名）會讓 span 名稱成為無界維度、影響 trace backend 的聚合效能。</p>
<p>屬性要帶足夠的診斷資訊但避免敏感資料。<code>http.url</code> 帶完整 URL 可能含 query parameter 裡的 token；<code>db.statement</code> 帶完整 SQL 可能含使用者資料。需要在 SDK 或 collector 層做 redaction。</p>
]]></content:encoded></item><item><title>Symptom-Based Alert</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/symptom-based-alert/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/symptom-based-alert/</guid><description>&lt;p>Symptom-based alert 的核心概念是「&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;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Symptom-based alert 跟 cause-based alert 分工不同。CPU 高、&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> 高、GC 頻繁是可能的原因；checkout 失敗率升高才是直接的產品症狀。Symptom-based 適合 critical severity（page &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>），cause-based 適合 warning severity（工作時間排入 task）。&lt;/p>
&lt;p>Symptom-based alert 是 &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 與容量趨勢">4.4 dashboard-alert&lt;/a> 建議的 alert 設計起點 — 先確認使用者是否受影響、再看系統原因。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 symptom-based alert 的訊號是 on-call 被大量低層訊號吵醒，但無法判斷使用者是否受影響。付款成功率下降應立即告警；單台 instance CPU 高則可先進 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a> 觀察或走自動修復流程。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Symptom-based alert 要連到 &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/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a> 與影響判斷。SLO-based alerting 用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">burn rate&lt;/a> 量化症狀嚴重度 — 「error budget 消耗速度是允許值的 14 倍」比「error rate &amp;gt; 1%」更能反映使用者影響規模。完整設計見 &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.6 SLI/SLO 訊號設計&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Symptom-based alert 的核心概念是「<a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 優先偵測使用者或產品可感知的症狀」。症狀包括錯誤率、延遲、可用性、資料延遲、付款失敗與訊息未送達。</p>
<h2 id="概念位置">概念位置</h2>
<p>Symptom-based alert 跟 cause-based alert 分工不同。CPU 高、<a href="/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">queue depth</a> 高、GC 頻繁是可能的原因；checkout 失敗率升高才是直接的產品症狀。Symptom-based 適合 critical severity（page <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a>），cause-based 適合 warning severity（工作時間排入 task）。</p>
<p>Symptom-based alert 是 <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> 建議的 alert 設計起點 — 先確認使用者是否受影響、再看系統原因。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 symptom-based alert 的訊號是 on-call 被大量低層訊號吵醒，但無法判斷使用者是否受影響。付款成功率下降應立即告警；單台 instance CPU 高則可先進 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> 觀察或走自動修復流程。</p>
<h2 id="設計責任">設計責任</h2>
<p>Symptom-based alert 要連到 <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/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 與影響判斷。SLO-based alerting 用 <a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">burn rate</a> 量化症狀嚴重度 — 「error budget 消耗速度是允許值的 14 倍」比「error rate &gt; 1%」更能反映使用者影響規模。完整設計見 <a href="/blog/backend/04-observability/sli-slo-signal/" data-link-title="4.6 SLI 量測與 SLO 訊號設計" data-link-desc="把可靠性目標的訊號從 metric 端設計好、餵給 6.6 SLO 政策">4.6 SLI/SLO 訊號設計</a>。</p>
]]></content:encoded></item><item><title>Runbook Link</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/runbook-link/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/runbook-link/</guid><description>&lt;p>Runbook link 的核心概念是「&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/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a> 直接連到對應處理流程」。它讓 on-call 從訊號直接進入可執行步驟，並降低對搜尋文件或個人記憶的依賴。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Runbook link 是 observability UX 的一部分。它把 alert、dashboard、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&lt;/a> query、rollback、擴容、停用 feature 與升級聯絡方式串起來。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 runbook link 的訊號是告警發出後，處理者仍要在聊天紀錄或文件庫中找下一步。&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> 告警應直接連到 lag dashboard、&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;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;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Runbook link 要保持有效、可搜尋、版本化。每次事故後應確認連結是否真的支援當次處理，並補上缺少的查詢與判斷條件。&lt;/p></description><content:encoded><![CDATA[<p>Runbook link 的核心概念是「<a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 或 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> 直接連到對應處理流程」。它讓 on-call 從訊號直接進入可執行步驟，並降低對搜尋文件或個人記憶的依賴。</p>
<h2 id="概念位置">概念位置</h2>
<p>Runbook link 是 observability UX 的一部分。它把 alert、dashboard、<a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a> query、rollback、擴容、停用 feature 與升級聯絡方式串起來。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 runbook link 的訊號是告警發出後，處理者仍要在聊天紀錄或文件庫中找下一步。<a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">Consumer lag</a> 告警應直接連到 lag dashboard、<a href="/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">DLQ</a> 查詢、擴容指令與 <a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook</a> 注意事項。</p>
<h2 id="設計責任">設計責任</h2>
<p>Runbook link 要保持有效、可搜尋、版本化。每次事故後應確認連結是否真的支援當次處理，並補上缺少的查詢與判斷條件。</p>
]]></content:encoded></item><item><title>Alert Fatigue</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/alert-fatigue/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/alert-fatigue/</guid><description>&lt;p>Alert fatigue 的核心概念是「過多低品質告警讓處理者對告警失去敏感度」。當告警常常沒有使用者影響、沒有行動步驟或頻繁自動恢復，&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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Alert fatigue 是可觀測性設計的失敗模式，跟 &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/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a>、ticket、報表或自動修復流程。&lt;/p>
&lt;p>常見的 fatigue 來源：false positive（條件觸發但實際沒問題）、redundant alert（同一問題觸發多個 alert）、stale alert（條件已不適用但 rule 沒更新）。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要治理 alert fatigue 的訊號是 noise rate &amp;gt; 30%（超過三成的 alert 不需要行動），或 on-call 工程師反應「收到 alert 先 ack 再看、有時直接 resolve 不看」。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Alert fatigue 的治理包括：追蹤 noise rate（on-call ack 時標記 actionable / noise）、定期審視高 noise 的 alert rule（調整閾值、改 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/symptom-based-alert/" data-link-title="Symptom-Based Alert" data-link-desc="說明告警應優先偵測使用者可感知症狀">symptom-based&lt;/a>、加 inhibition、或刪除）、用 grouping 跟 inhibition 減少同一問題的重複通知。治理節奏跟 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/signal-governance-loop/" data-link-title="4.8 訊號治理閉環" data-link-desc="把 postmortem 揭露的偵測缺口回寫成新訊號、讓觀測能力隨事故學習成長">4.8 訊號治理閉環&lt;/a> 整合。&lt;/p></description><content:encoded><![CDATA[<p>Alert fatigue 的核心概念是「過多低品質告警讓處理者對告警失去敏感度」。當告警常常沒有使用者影響、沒有行動步驟或頻繁自動恢復，<a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a> 會開始忽略訊號 — 包括真正需要處理的那些。</p>
<h2 id="概念位置">概念位置</h2>
<p>Alert fatigue 是可觀測性設計的失敗模式，跟 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 的品質治理直接相關。告警應代表需要人介入的產品風險；其他訊號可以進 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a>、ticket、報表或自動修復流程。</p>
<p>常見的 fatigue 來源：false positive（條件觸發但實際沒問題）、redundant alert（同一問題觸發多個 alert）、stale alert（條件已不適用但 rule 沒更新）。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要治理 alert fatigue 的訊號是 noise rate &gt; 30%（超過三成的 alert 不需要行動），或 on-call 工程師反應「收到 alert 先 ack 再看、有時直接 resolve 不看」。</p>
<h2 id="設計責任">設計責任</h2>
<p>Alert fatigue 的治理包括：追蹤 noise rate（on-call ack 時標記 actionable / noise）、定期審視高 noise 的 alert rule（調整閾值、改 <a href="/blog/backend/knowledge-cards/symptom-based-alert/" data-link-title="Symptom-Based Alert" data-link-desc="說明告警應優先偵測使用者可感知症狀">symptom-based</a>、加 inhibition、或刪除）、用 grouping 跟 inhibition 減少同一問題的重複通知。治理節奏跟 <a href="/blog/backend/04-observability/signal-governance-loop/" data-link-title="4.8 訊號治理閉環" data-link-desc="把 postmortem 揭露的偵測缺口回寫成新訊號、讓觀測能力隨事故學習成長">4.8 訊號治理閉環</a> 整合。</p>
]]></content:encoded></item><item><title>Authentication</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/</guid><description>&lt;p>Authentication 的核心概念是「確認呼叫者是誰」。它可以透過 password、session、token、OAuth、certificate、API key 或 workload identity 完成。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Authentication 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">authorization&lt;/a> 的前置條件。系統先確認身份，再判斷該身份能否操作某個資源。身份確認失敗時，後續權限判斷缺少可靠基礎。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 authentication 設計的訊號是服務需要區分使用者、管理員、service account 或第三方系統。Webhook 進站可以用 signature 驗證來源；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> 或 workload identity。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Authentication 要處理 credential 保存、過期、撤銷、輪替、錯誤回應、登入風險與 &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>。安全事件後要能追查是哪個身份與 credential 被使用。&lt;/p></description><content:encoded><![CDATA[<p>Authentication 的核心概念是「確認呼叫者是誰」。它可以透過 password、session、token、OAuth、certificate、API key 或 workload identity 完成。 可先對照 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Authentication 是 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">authorization</a> 的前置條件。系統先確認身份，再判斷該身份能否操作某個資源。身份確認失敗時，後續權限判斷缺少可靠基礎。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 authentication 設計的訊號是服務需要區分使用者、管理員、service account 或第三方系統。Webhook 進站可以用 signature 驗證來源；service-to-service 可以用 <a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">mTLS</a> 或 workload identity。</p>
<h2 id="設計責任">設計責任</h2>
<p>Authentication 要處理 credential 保存、過期、撤銷、輪替、錯誤回應、登入風險與 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a>。安全事件後要能追查是哪個身份與 credential 被使用。</p>
]]></content:encoded></item><item><title>BOLA / IDOR</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/bola-idor/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/bola-idor/</guid><description>&lt;p>BOLA / IDOR 的核心概念是「使用者透過修改物件 ID 存取未授權資源」。BOLA 是 Broken Object Level Authorization；IDOR 是 Insecure Direct Object Reference。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/bopla/" data-link-title="BOPLA" data-link-desc="說明屬性層授權缺失如何讓使用者讀寫不該暴露的欄位">BOPLA&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>BOLA 是 API 安全中常見的授權問題。Authentication 只能確認呼叫者身份；每次讀寫訂單、檔案、帳戶、發票或 tenant 資源時，仍要檢查該身份是否能操作該物件。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/bopla/" data-link-title="BOPLA" data-link-desc="說明屬性層授權缺失如何讓使用者讀寫不該暴露的欄位">BOPLA&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 BOLA 防護的訊號是 API path 或 body 中包含資源 ID。使用者把 &lt;code>/orders/1001&lt;/code> 改成 &lt;code>/orders/1002&lt;/code> 時，系統必須確認 1002 是否屬於該使用者或其 tenant。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>BOLA 防護要在 usecase 或 policy 層檢查 resource ownership、tenant boundary 與角色權限。測試要覆蓋跨使用者、跨 tenant、低權限操作與猜測 ID。&lt;/p></description><content:encoded><![CDATA[<p>BOLA / IDOR 的核心概念是「使用者透過修改物件 ID 存取未授權資源」。BOLA 是 Broken Object Level Authorization；IDOR 是 Insecure Direct Object Reference。 可先對照 <a href="/blog/backend/knowledge-cards/bopla/" data-link-title="BOPLA" data-link-desc="說明屬性層授權缺失如何讓使用者讀寫不該暴露的欄位">BOPLA</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>BOLA 是 API 安全中常見的授權問題。Authentication 只能確認呼叫者身份；每次讀寫訂單、檔案、帳戶、發票或 tenant 資源時，仍要檢查該身份是否能操作該物件。 可先對照 <a href="/blog/backend/knowledge-cards/bopla/" data-link-title="BOPLA" data-link-desc="說明屬性層授權缺失如何讓使用者讀寫不該暴露的欄位">BOPLA</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 BOLA 防護的訊號是 API path 或 body 中包含資源 ID。使用者把 <code>/orders/1001</code> 改成 <code>/orders/1002</code> 時，系統必須確認 1002 是否屬於該使用者或其 tenant。</p>
<h2 id="設計責任">設計責任</h2>
<p>BOLA 防護要在 usecase 或 policy 層檢查 resource ownership、tenant boundary 與角色權限。測試要覆蓋跨使用者、跨 tenant、低權限操作與猜測 ID。</p>
]]></content:encoded></item><item><title>BOPLA</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/bopla/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/bopla/</guid><description>&lt;p>BOPLA 的核心概念是「物件屬性層級的授權缺失」。即使使用者可以存取某個物件，也不代表可以讀取或修改該物件的所有欄位。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>BOPLA 是 field-level policy 的安全問題。訂單物件可以讓使用者查看商品與金額，但內部風控欄位、成本、客服註記或權限欄位需要更高權限。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 BOPLA 防護的訊號是 API 回傳完整資料模型，或允許 client 送入任意欄位。使用者更新個人資料時，外部輸入欄位應排除 &lt;code>role&lt;/code>、&lt;code>is_admin&lt;/code> 或 &lt;code>credit_limit&lt;/code>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>BOPLA 防護要定義欄位分級、輸入白名單、輸出 schema、遮罩與測試。公開 API DTO 應和內部資料模型分開。&lt;/p></description><content:encoded><![CDATA[<p>BOPLA 的核心概念是「物件屬性層級的授權缺失」。即使使用者可以存取某個物件，也不代表可以讀取或修改該物件的所有欄位。 可先對照 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>BOPLA 是 field-level policy 的安全問題。訂單物件可以讓使用者查看商品與金額，但內部風控欄位、成本、客服註記或權限欄位需要更高權限。 可先對照 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 BOPLA 防護的訊號是 API 回傳完整資料模型，或允許 client 送入任意欄位。使用者更新個人資料時，外部輸入欄位應排除 <code>role</code>、<code>is_admin</code> 或 <code>credit_limit</code>。</p>
<h2 id="設計責任">設計責任</h2>
<p>BOPLA 防護要定義欄位分級、輸入白名單、輸出 schema、遮罩與測試。公開 API DTO 應和內部資料模型分開。</p>
]]></content:encoded></item><item><title>Mass Assignment</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/mass-assignment/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/mass-assignment/</guid><description>&lt;p>Mass assignment 的核心概念是「框架或程式把 request 欄位自動寫入資料模型」。若沒有輸入白名單，client 可能送入不該由外部控制的欄位。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Mass assignment 是 API 輸入邊界問題。它常出現在直接把 JSON body bind 到 ORM model、domain model 或 persistence model 的程式碼中。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要防 mass assignment 的訊號是 request body 可以包含內部欄位。註冊 API 若直接綁定 &lt;code>User&lt;/code> model，攻擊者可能加入 &lt;code>role: admin&lt;/code> 或 &lt;code>email_verified: true&lt;/code>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>防護要使用輸入 DTO、欄位白名單、policy validation 與測試。外部 request schema 應只包含該操作允許修改的欄位。&lt;/p></description><content:encoded><![CDATA[<p>Mass assignment 的核心概念是「框架或程式把 request 欄位自動寫入資料模型」。若沒有輸入白名單，client 可能送入不該由外部控制的欄位。 可先對照 <a href="/blog/backend/knowledge-cards/message-persistence/" data-link-title="Message Persistence" data-link-desc="說明訊息是否落盤保存，以及 broker 重啟後能否恢復">Message Persistence</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Mass assignment 是 API 輸入邊界問題。它常出現在直接把 JSON body bind 到 ORM model、domain model 或 persistence model 的程式碼中。 可先對照 <a href="/blog/backend/knowledge-cards/message-persistence/" data-link-title="Message Persistence" data-link-desc="說明訊息是否落盤保存，以及 broker 重啟後能否恢復">Message Persistence</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要防 mass assignment 的訊號是 request body 可以包含內部欄位。註冊 API 若直接綁定 <code>User</code> model，攻擊者可能加入 <code>role: admin</code> 或 <code>email_verified: true</code>。</p>
<h2 id="設計責任">設計責任</h2>
<p>防護要使用輸入 DTO、欄位白名單、policy validation 與測試。外部 request schema 應只包含該操作允許修改的欄位。</p>
]]></content:encoded></item><item><title>Excessive Data Exposure</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/excessive-data-exposure/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/excessive-data-exposure/</guid><description>&lt;p>Excessive data exposure 的核心概念是「API 回傳超出呼叫者需要的資料」。即使前端沒有顯示，資料仍然已經離開後端邊界。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>資料暴露是輸出邊界問題。API response 應依用途設計 DTO、欄位遮罩與角色權限，內部資料模型應留在服務邊界內。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要防 excessive data exposure 的訊號是 response 包含敏感欄位、內部狀態或其他角色才需要的資料。客服 API 可以看部分電話；一般使用者訂單 API 則應只回傳使用者完成操作所需欄位。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>防護要包含 response schema、欄位分級、data masking、contract test 與 log 檢查。資料一旦回傳給 client，就應視為已暴露。&lt;/p></description><content:encoded><![CDATA[<p>Excessive data exposure 的核心概念是「API 回傳超出呼叫者需要的資料」。即使前端沒有顯示，資料仍然已經離開後端邊界。 可先對照 <a href="/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>資料暴露是輸出邊界問題。API response 應依用途設計 DTO、欄位遮罩與角色權限，內部資料模型應留在服務邊界內。 可先對照 <a href="/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要防 excessive data exposure 的訊號是 response 包含敏感欄位、內部狀態或其他角色才需要的資料。客服 API 可以看部分電話；一般使用者訂單 API 則應只回傳使用者完成操作所需欄位。</p>
<h2 id="設計責任">設計責任</h2>
<p>防護要包含 response schema、欄位分級、data masking、contract test 與 log 檢查。資料一旦回傳給 client，就應視為已暴露。</p>
]]></content:encoded></item><item><title>Unrestricted Resource Consumption</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/unrestricted-resource-consumption/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/unrestricted-resource-consumption/</guid><description>&lt;p>Unrestricted resource consumption 的核心概念是「API 沒有對資源使用量設定足夠限制」。攻擊者或錯誤 client 可以用大量 request、大型 payload、昂貴查詢或大量匯出耗盡系統資源。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/validation-middleware/" data-link-title="Validation Middleware" data-link-desc="說明請求進入 handler 前如何完成共通驗證">Validation Middleware&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>資源消耗限制連接 rate limit、payload limit、timeout、pagination、query cost、queue quota 與 tenant quota。它同時是可靠性與資安問題。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/validation-middleware/" data-link-title="Validation Middleware" data-link-desc="說明請求進入 handler 前如何完成共通驗證">Validation Middleware&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要資源消耗限制的訊號是 API 支援搜尋、匯出、上傳、批次操作或複雜 filter。未限制日期範圍的報表匯出，可能讓單一 request 掃描多年資料。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>防護要定義大小限制、速率限制、分頁、查詢成本、timeout、租戶配額與告警。錯誤回應應告訴 client 如何縮小請求。&lt;/p></description><content:encoded><![CDATA[<p>Unrestricted resource consumption 的核心概念是「API 沒有對資源使用量設定足夠限制」。攻擊者或錯誤 client 可以用大量 request、大型 payload、昂貴查詢或大量匯出耗盡系統資源。 可先對照 <a href="/blog/backend/knowledge-cards/validation-middleware/" data-link-title="Validation Middleware" data-link-desc="說明請求進入 handler 前如何完成共通驗證">Validation Middleware</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>資源消耗限制連接 rate limit、payload limit、timeout、pagination、query cost、queue quota 與 tenant quota。它同時是可靠性與資安問題。 可先對照 <a href="/blog/backend/knowledge-cards/validation-middleware/" data-link-title="Validation Middleware" data-link-desc="說明請求進入 handler 前如何完成共通驗證">Validation Middleware</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要資源消耗限制的訊號是 API 支援搜尋、匯出、上傳、批次操作或複雜 filter。未限制日期範圍的報表匯出，可能讓單一 request 掃描多年資料。</p>
<h2 id="設計責任">設計責任</h2>
<p>防護要定義大小限制、速率限制、分頁、查詢成本、timeout、租戶配額與告警。錯誤回應應告訴 client 如何縮小請求。</p>
]]></content:encoded></item><item><title>Function-Level Authorization</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/function-level-authorization/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/function-level-authorization/</guid><description>&lt;p>Function-level authorization 的核心概念是「某個功能或操作本身需要權限」。使用者即使能讀取某個資源，也不一定能匯出、刪除、退款、停用或調整權限。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fuzz-test/" data-link-title="Fuzz Test" data-link-desc="說明用隨機與變異輸入驗證解析器與邊界處理健壯性">Fuzz Test&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Function-level authorization 和 object-level authorization 互補。Object-level 檢查資源歸屬；function-level 檢查操作能力與角色責任。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fuzz-test/" data-link-title="Fuzz Test" data-link-desc="說明用隨機與變異輸入驗證解析器與邊界處理健壯性">Fuzz Test&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 function-level authorization 的訊號是同一資源上有高風險操作。客服可以查看訂單，但退款、補發點數、修改收件資訊需要額外權限與 audit。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>授權設計要把 action 納入 policy，例如 &lt;code>order.read&lt;/code>、&lt;code>order.refund&lt;/code>、&lt;code>user.export&lt;/code>。測試要覆蓋低權限使用者直接呼叫高風險 endpoint 的情境。&lt;/p></description><content:encoded><![CDATA[<p>Function-level authorization 的核心概念是「某個功能或操作本身需要權限」。使用者即使能讀取某個資源，也不一定能匯出、刪除、退款、停用或調整權限。 可先對照 <a href="/blog/backend/knowledge-cards/fuzz-test/" data-link-title="Fuzz Test" data-link-desc="說明用隨機與變異輸入驗證解析器與邊界處理健壯性">Fuzz Test</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Function-level authorization 和 object-level authorization 互補。Object-level 檢查資源歸屬；function-level 檢查操作能力與角色責任。 可先對照 <a href="/blog/backend/knowledge-cards/fuzz-test/" data-link-title="Fuzz Test" data-link-desc="說明用隨機與變異輸入驗證解析器與邊界處理健壯性">Fuzz Test</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 function-level authorization 的訊號是同一資源上有高風險操作。客服可以查看訂單，但退款、補發點數、修改收件資訊需要額外權限與 audit。</p>
<h2 id="設計責任">設計責任</h2>
<p>授權設計要把 action 納入 policy，例如 <code>order.read</code>、<code>order.refund</code>、<code>user.export</code>。測試要覆蓋低權限使用者直接呼叫高風險 endpoint 的情境。</p>
]]></content:encoded></item><item><title>Tenant Boundary</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/tenant-boundary/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/tenant-boundary/</guid><description>&lt;p>Tenant boundary 的核心概念是「隔離不同客戶、組織或租戶的資料與資源」。多租戶系統中，使用者身份之外還要判斷他屬於哪個 tenant，以及能否跨 tenant 操作。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/throughput/" data-link-title="Throughput" data-link-desc="整理系統單位時間內可處理的工作量">Throughput&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Tenant boundary 是 authorization、data partition、rate limit、audit 與 billing 的共同邊界。它可以落在資料庫欄位、schema、database、queue、cache key、storage path 或 network policy。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/throughput/" data-link-title="Throughput" data-link-desc="整理系統單位時間內可處理的工作量">Throughput&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 tenant boundary 的訊號是同一服務處理多個企業或組織。A 公司管理員只能看到 A 公司訂單；A 公司的大量匯出也應使用自己的查詢配額，保留 B 公司的正常容量。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Tenant boundary 要在 query、cache key、message、log、audit、rate limit 與測試中保持一致。測試要覆蓋跨 tenant IDOR、資料匯出與背景 job。&lt;/p></description><content:encoded><![CDATA[<p>Tenant boundary 的核心概念是「隔離不同客戶、組織或租戶的資料與資源」。多租戶系統中，使用者身份之外還要判斷他屬於哪個 tenant，以及能否跨 tenant 操作。 可先對照 <a href="/blog/backend/knowledge-cards/throughput/" data-link-title="Throughput" data-link-desc="整理系統單位時間內可處理的工作量">Throughput</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Tenant boundary 是 authorization、data partition、rate limit、audit 與 billing 的共同邊界。它可以落在資料庫欄位、schema、database、queue、cache key、storage path 或 network policy。 可先對照 <a href="/blog/backend/knowledge-cards/throughput/" data-link-title="Throughput" data-link-desc="整理系統單位時間內可處理的工作量">Throughput</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 tenant boundary 的訊號是同一服務處理多個企業或組織。A 公司管理員只能看到 A 公司訂單；A 公司的大量匯出也應使用自己的查詢配額，保留 B 公司的正常容量。</p>
<h2 id="設計責任">設計責任</h2>
<p>Tenant boundary 要在 query、cache key、message、log、audit、rate limit 與測試中保持一致。測試要覆蓋跨 tenant IDOR、資料匯出與背景 job。</p>
]]></content:encoded></item><item><title>Least Privilege</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/least-privilege/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/least-privilege/</guid><description>&lt;p>Least privilege 的核心概念是「每個身份只取得完成工作所需的最小權限」。身份可以是使用者、管理員、service account、CI job、database user 或第三方 integration。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/load-balancer-contract/" data-link-title="Load Balancer Contract" data-link-desc="說明服務與負載平衡器之間的流量與健康檢查約定">Load Balancer Contract&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Least privilege 是權限模型與事故限縮工具。權限越大，credential 洩漏、程式 bug 或人為操作的影響範圍越大。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/load-balancer-contract/" data-link-title="Load Balancer Contract" data-link-desc="說明服務與負載平衡器之間的流量與健康檢查約定">Load Balancer Contract&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 least privilege 的訊號是多個服務共用同一把高權限 credential。報表服務只需要讀取訂單摘要時，應使用專門的唯讀資料庫帳號。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>權限設計要分角色、分服務、分環境、分資源。Runbook 應包含權限審查、credential rotation、撤銷流程與異常操作 audit。&lt;/p></description><content:encoded><![CDATA[<p>Least privilege 的核心概念是「每個身份只取得完成工作所需的最小權限」。身份可以是使用者、管理員、service account、CI job、database user 或第三方 integration。 可先對照 <a href="/blog/backend/knowledge-cards/load-balancer-contract/" data-link-title="Load Balancer Contract" data-link-desc="說明服務與負載平衡器之間的流量與健康檢查約定">Load Balancer Contract</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Least privilege 是權限模型與事故限縮工具。權限越大，credential 洩漏、程式 bug 或人為操作的影響範圍越大。 可先對照 <a href="/blog/backend/knowledge-cards/load-balancer-contract/" data-link-title="Load Balancer Contract" data-link-desc="說明服務與負載平衡器之間的流量與健康檢查約定">Load Balancer Contract</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 least privilege 的訊號是多個服務共用同一把高權限 credential。報表服務只需要讀取訂單摘要時，應使用專門的唯讀資料庫帳號。</p>
<h2 id="設計責任">設計責任</h2>
<p>權限設計要分角色、分服務、分環境、分資源。Runbook 應包含權限審查、credential rotation、撤銷流程與異常操作 audit。</p>
]]></content:encoded></item><item><title>IAM</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/iam/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/iam/</guid><description>&lt;p>IAM 的核心概念是「集中管理誰是誰，以及誰能做什麼」。它通常負責使用者、服務帳號、角色、群組、policy 與權限委派，並為 application 提供登入、授權與稽核的共同基礎。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>IAM 位在 authentication、authorization 與組織治理之間。它常與 &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> 一起出現，也會影響 tenant boundary 與 service account 管理。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 IAM 的訊號是團隊、產品或租戶數量增加，且權限規則開始無法靠單一 application hard-code 維護。企業 SaaS、內部管理後台與雲端資源操作通常都需要 IAM 來統一角色與 policy。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>IAM 設計要定義身分來源、角色模型、權限授予、撤銷流程與稽核記錄。實作時要避免把高風險權限散落在各個 service，否則會讓權限審查、換人與事故處置變得困難。&lt;/p></description><content:encoded><![CDATA[<p>IAM 的核心概念是「集中管理誰是誰，以及誰能做什麼」。它通常負責使用者、服務帳號、角色、群組、policy 與權限委派，並為 application 提供登入、授權與稽核的共同基礎。 可先對照 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>IAM 位在 authentication、authorization 與組織治理之間。它常與 <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> 一起出現，也會影響 tenant boundary 與 service account 管理。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 IAM 的訊號是團隊、產品或租戶數量增加，且權限規則開始無法靠單一 application hard-code 維護。企業 SaaS、內部管理後台與雲端資源操作通常都需要 IAM 來統一角色與 policy。</p>
<h2 id="設計責任">設計責任</h2>
<p>IAM 設計要定義身分來源、角色模型、權限授予、撤銷流程與稽核記錄。實作時要避免把高風險權限散落在各個 service，否則會讓權限審查、換人與事故處置變得困難。</p>
]]></content:encoded></item><item><title>Security Misconfiguration</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/security-misconfiguration/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/security-misconfiguration/</guid><description>&lt;p>Security misconfiguration 的核心概念是「系統設定讓安全控制失效或暴露不該公開的能力」。它可能出現在 CORS、TLS、debug endpoint、admin route、bucket permission、default password、WAF rule 或 error detail。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Security misconfiguration 是部署與操作層面的安全風險。程式邏輯正確仍可能因環境設定、預設值或部署流程錯誤而暴露資料或功能。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要設定檢查的訊號是服務有多個環境、公開入口或雲端資源。Debug endpoint 在 staging 可用，但若同設定進 production，可能暴露 runtime、config 或內部資料。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>防護要包含 baseline config、環境差異審查、secret scan、IaC review、security test 與 drift detection。高風險設定應進入 &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;/p></description><content:encoded><![CDATA[<p>Security misconfiguration 的核心概念是「系統設定讓安全控制失效或暴露不該公開的能力」。它可能出現在 CORS、TLS、debug endpoint、admin route、bucket permission、default password、WAF rule 或 error detail。 可先對照 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Security misconfiguration 是部署與操作層面的安全風險。程式邏輯正確仍可能因環境設定、預設值或部署流程錯誤而暴露資料或功能。 可先對照 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要設定檢查的訊號是服務有多個環境、公開入口或雲端資源。Debug endpoint 在 staging 可用，但若同設定進 production，可能暴露 runtime、config 或內部資料。</p>
<h2 id="設計責任">設計責任</h2>
<p>防護要包含 baseline config、環境差異審查、secret scan、IaC review、security test 與 drift detection。高風險設定應進入 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a>。</p>
]]></content:encoded></item><item><title>Input Validation</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/input-validation/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/input-validation/</guid><description>&lt;p>Input validation 的核心概念是「資料進入系統時先檢查格式、範圍與語意」。它保護後續 business logic、database、queue、parser 與外部 API。 可先對照 &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;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Input validation 是 API 邊界與安全邊界的第一層。它不取代 authorization、business rule 或 database constraint，但能提早拒絕無效資料並產生清楚錯誤。 可先對照 &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;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 input validation 的訊號是 API 接收 JSON、檔案、URL、查詢條件或 webhook payload。日期範圍、email 格式、檔案大小、enum 值與 ID 格式都應在入口被驗證。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Validation 要分層：格式檢查在入口，業務規則在 usecase，資料完整性由 database constraint 保底。錯誤回應要清楚但避免洩漏內部細節。&lt;/p></description><content:encoded><![CDATA[<p>Input validation 的核心概念是「資料進入系統時先檢查格式、範圍與語意」。它保護後續 business logic、database、queue、parser 與外部 API。 可先對照 <a href="/blog/backend/knowledge-cards/internal-endpoint/" data-link-title="Internal Endpoint" data-link-desc="說明服務內部通訊入口如何配合網路邊界與服務發現">Internal Endpoint</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Input validation 是 API 邊界與安全邊界的第一層。它不取代 authorization、business rule 或 database constraint，但能提早拒絕無效資料並產生清楚錯誤。 可先對照 <a href="/blog/backend/knowledge-cards/internal-endpoint/" data-link-title="Internal Endpoint" data-link-desc="說明服務內部通訊入口如何配合網路邊界與服務發現">Internal Endpoint</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 input validation 的訊號是 API 接收 JSON、檔案、URL、查詢條件或 webhook payload。日期範圍、email 格式、檔案大小、enum 值與 ID 格式都應在入口被驗證。</p>
<h2 id="設計責任">設計責任</h2>
<p>Validation 要分層：格式檢查在入口，業務規則在 usecase，資料完整性由 database constraint 保底。錯誤回應要清楚但避免洩漏內部細節。</p>
]]></content:encoded></item><item><title>WAF</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/waf/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/waf/</guid><description>&lt;p>WAF 的核心概念是「在流量進入 application 之前，先用規則擋掉明顯惡意或高風險的 request」。它通常部署在 edge、load balancer、reverse proxy 或 CDN 前後，用來保護公開入口與高暴露面功能。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>WAF 位在流量入口與 application 之間。它適合處理 SQL injection、XSS、惡意 bot、異常 payload、重放型濫用與明顯不符合路徑語意的 request。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 WAF 的訊號是攻擊流量、濫用流量或掃描流量開始增加。公開 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>、file upload 與 webhook 入口如果暴露在網際網路上，通常需要額外的 WAF 規則與例外管理。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>WAF 設計要定義規則更新、誤殺處理、觀測指標、例外放行與回應流程。它不應取代 application 層的輸入驗證、授權或速率限制，而是作為第一層防護與風險降噪。&lt;/p></description><content:encoded><![CDATA[<p>WAF 的核心概念是「在流量進入 application 之前，先用規則擋掉明顯惡意或高風險的 request」。它通常部署在 edge、load balancer、reverse proxy 或 CDN 前後，用來保護公開入口與高暴露面功能。 可先對照 <a href="/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>WAF 位在流量入口與 application 之間。它適合處理 SQL injection、XSS、惡意 bot、異常 payload、重放型濫用與明顯不符合路徑語意的 request。 可先對照 <a href="/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 WAF 的訊號是攻擊流量、濫用流量或掃描流量開始增加。公開 API、<a href="/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint</a>、file upload 與 webhook 入口如果暴露在網際網路上，通常需要額外的 WAF 規則與例外管理。</p>
<h2 id="設計責任">設計責任</h2>
<p>WAF 設計要定義規則更新、誤殺處理、觀測指標、例外放行與回應流程。它不應取代 application 層的輸入驗證、授權或速率限制，而是作為第一層防護與風險降噪。</p>
]]></content:encoded></item><item><title>SSRF</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/ssrf/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/ssrf/</guid><description>&lt;p>SSRF 的核心概念是「攻擊者讓伺服器替他發出未授權的網路請求」。如果 API 接收 URL 並由後端抓取內容，攻擊者可能指向內部服務、metadata endpoint 或管理介面。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stakeholder-mapping/" data-link-title="Stakeholder Mapping" data-link-desc="說明事故期間如何把通報對象分層與對應 owner">Stakeholder Mapping&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SSRF 是伺服器端輸入驗證與網路出口控制問題。它常出現在 webhook 測試、圖片抓取、URL preview、匯入工具、PDF 產生與代理服務。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stakeholder-mapping/" data-link-title="Stakeholder Mapping" data-link-desc="說明事故期間如何把通報對象分層與對應 owner">Stakeholder Mapping&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 SSRF 防護的訊號是使用者可以控制後端要連到的 URL。圖片上傳功能若支援「貼 URL 匯入」，後端必須限制可連線網域、IP range、scheme 與 redirect。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>防護要包含 allowlist、DNS/IP 檢查、禁止內網位址、限制 redirect、timeout、response size limit 與 egress policy。Log 要記錄目標 host 與拒絕原因。&lt;/p></description><content:encoded><![CDATA[<p>SSRF 的核心概念是「攻擊者讓伺服器替他發出未授權的網路請求」。如果 API 接收 URL 並由後端抓取內容，攻擊者可能指向內部服務、metadata endpoint 或管理介面。 可先對照 <a href="/blog/backend/knowledge-cards/stakeholder-mapping/" data-link-title="Stakeholder Mapping" data-link-desc="說明事故期間如何把通報對象分層與對應 owner">Stakeholder Mapping</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>SSRF 是伺服器端輸入驗證與網路出口控制問題。它常出現在 webhook 測試、圖片抓取、URL preview、匯入工具、PDF 產生與代理服務。 可先對照 <a href="/blog/backend/knowledge-cards/stakeholder-mapping/" data-link-title="Stakeholder Mapping" data-link-desc="說明事故期間如何把通報對象分層與對應 owner">Stakeholder Mapping</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 SSRF 防護的訊號是使用者可以控制後端要連到的 URL。圖片上傳功能若支援「貼 URL 匯入」，後端必須限制可連線網域、IP range、scheme 與 redirect。</p>
<h2 id="設計責任">設計責任</h2>
<p>防護要包含 allowlist、DNS/IP 檢查、禁止內網位址、限制 redirect、timeout、response size limit 與 egress policy。Log 要記錄目標 host 與拒絕原因。</p>
]]></content:encoded></item><item><title>Attack Surface</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/attack-surface/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/attack-surface/</guid><description>&lt;p>Attack surface 的核心概念是「攻擊者能先看見並嘗試互動的所有暴露面」。它不只包括 public API，也包括 admin route、webhook、diagnostic endpoint、upload path、debug flag、雲端資源與任何能被外部觸及的入口。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/public-api-endpoint/" data-link-title="Public API Endpoint" data-link-desc="說明面向外部 client 的穩定 API 入口如何被管理">Public API Endpoint&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Attack surface 是紅隊分析的起點。它回答「哪裡先被看到」，因此會和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/public-api-endpoint/" data-link-title="Public API Endpoint" data-link-desc="說明面向外部 client 的穩定 API 入口如何被管理">Public API&lt;/a>、&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/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;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/security-misconfiguration/" data-link-title="Security Misconfiguration" data-link-desc="說明錯誤設定如何讓安全控制失效或暴露內部能力">Security Misconfiguration&lt;/a> 一起被檢查。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統只要有多種入口、不同權限等級、可枚舉資源或可回傳診斷資訊，就需要明確盤點 attack surface。若某個 endpoint 可以被猜路徑、透過錯誤訊息推回內部結構，或因預設設定而暴露額外能力，這個 surface 就應該被優先標記。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>暴露面管理要把入口用途、來源限制、資料回應與日誌責任分開定義。對外公開的 surface 需要比內部 surface 更嚴格的驗證、速率控制與回應最小化。&lt;/p></description><content:encoded><![CDATA[<p>Attack surface 的核心概念是「攻擊者能先看見並嘗試互動的所有暴露面」。它不只包括 public API，也包括 admin route、webhook、diagnostic endpoint、upload path、debug flag、雲端資源與任何能被外部觸及的入口。 可先對照 <a href="/blog/backend/knowledge-cards/public-api-endpoint/" data-link-title="Public API Endpoint" data-link-desc="說明面向外部 client 的穩定 API 入口如何被管理">Public API Endpoint</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Attack surface 是紅隊分析的起點。它回答「哪裡先被看到」，因此會和 <a href="/blog/backend/knowledge-cards/public-api-endpoint/" data-link-title="Public API Endpoint" data-link-desc="說明面向外部 client 的穩定 API 入口如何被管理">Public API</a>、<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/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>、<a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">webhook</a> 與 <a href="/blog/backend/knowledge-cards/security-misconfiguration/" data-link-title="Security Misconfiguration" data-link-desc="說明錯誤設定如何讓安全控制失效或暴露內部能力">Security Misconfiguration</a> 一起被檢查。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統只要有多種入口、不同權限等級、可枚舉資源或可回傳診斷資訊，就需要明確盤點 attack surface。若某個 endpoint 可以被猜路徑、透過錯誤訊息推回內部結構，或因預設設定而暴露額外能力，這個 surface 就應該被優先標記。</p>
<h2 id="設計責任">設計責任</h2>
<p>暴露面管理要把入口用途、來源限制、資料回應與日誌責任分開定義。對外公開的 surface 需要比內部 surface 更嚴格的驗證、速率控制與回應最小化。</p>
]]></content:encoded></item><item><title>PII</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/pii/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/pii/</guid><description>&lt;p>PII 的核心概念是「可識別特定個人的資料」。姓名、電話、email、地址、身份證號、裝置 ID、付款資訊與某些組合資料都可能成為 PII。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>PII 是 &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/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/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention&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> 與資料匯出的核心分類。資料是否為 PII 會直接改變系統的存取控制與操作成本。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 PII 分級的訊號是服務保存會員、訂單、付款、客服或行為資料。客服查詢電話需要遮罩；資料匯出需要核准與 audit log；&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&lt;/a> 應控制 PII 欄位。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>PII 設計要標出欄位分類、存取角色、遮罩規則、保留期限、匯出流程與刪除流程。測試資料也需要匿名化或合成資料策略，並和 &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></description><content:encoded><![CDATA[<p>PII 的核心概念是「可識別特定個人的資料」。姓名、電話、email、地址、身份證號、裝置 ID、付款資訊與某些組合資料都可能成為 PII。 可先對照 <a href="/blog/backend/knowledge-cards/data-classification/" data-link-title="Data Classification" data-link-desc="說明資料分級如何決定保護、存取、保留與匯出規則">Data Classification</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>PII 是 <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/data-masking/" data-link-title="Data Masking" data-link-desc="說明敏感資料如何在顯示、匯出、log 與測試資料中降低暴露">data masking</a>、權限、<a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention</a>、<a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a> 與資料匯出的核心分類。資料是否為 PII 會直接改變系統的存取控制與操作成本。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 PII 分級的訊號是服務保存會員、訂單、付款、客服或行為資料。客服查詢電話需要遮罩；資料匯出需要核准與 audit log；<a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a> 應控制 PII 欄位。</p>
<h2 id="設計責任">設計責任</h2>
<p>PII 設計要標出欄位分類、存取角色、遮罩規則、保留期限、匯出流程與刪除流程。測試資料也需要匿名化或合成資料策略，並和 <a href="/blog/backend/knowledge-cards/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">secret management</a> 分開管理。</p>
]]></content:encoded></item><item><title>Trust Boundary</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/trust-boundary/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/trust-boundary/</guid><description>&lt;p>Trust boundary 的核心概念是「信任假設在哪裡開始不再成立」。紅隊會特別關注這些切換點，因為只要邊界不清楚，權限、稽核、遮罩與防護都可能只在局部成立。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Trust boundary 會出現在 &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/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">tenant boundary&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/ssrf/" data-link-title="SSRF" data-link-desc="說明伺服器端請求被濫用時如何存取內部網路或 metadata 服務">SSRF&lt;/a> 與 network policy 交界。它是描述「哪裡開始需要重新驗證」的分析框架，涵蓋範圍超過任何單一防護措施。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>一個系統只要跨越 client、service、queue、storage、tenant 或第三方整合，就會產生 trust boundary。當邊界跨得越多，紅隊越會檢查訊號是否真的有被重新驗證，而不是延用前一段的假設。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>邊界管理要能說清楚誰信任誰、信任到哪裡、何時失效。若某段流程會跨越身份、租戶、網路或資料層邊界，就要在那一點重新定義驗證、授權與完整性檢查。&lt;/p></description><content:encoded><![CDATA[<p>Trust boundary 的核心概念是「信任假設在哪裡開始不再成立」。紅隊會特別關注這些切換點，因為只要邊界不清楚，權限、稽核、遮罩與防護都可能只在局部成立。 可先對照 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Trust boundary 會出現在 <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/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">tenant boundary</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/ssrf/" data-link-title="SSRF" data-link-desc="說明伺服器端請求被濫用時如何存取內部網路或 metadata 服務">SSRF</a> 與 network policy 交界。它是描述「哪裡開始需要重新驗證」的分析框架，涵蓋範圍超過任何單一防護措施。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>一個系統只要跨越 client、service、queue、storage、tenant 或第三方整合，就會產生 trust boundary。當邊界跨得越多，紅隊越會檢查訊號是否真的有被重新驗證，而不是延用前一段的假設。</p>
<h2 id="設計責任">設計責任</h2>
<p>邊界管理要能說清楚誰信任誰、信任到哪裡、何時失效。若某段流程會跨越身份、租戶、網路或資料層邊界，就要在那一點重新定義驗證、授權與完整性檢查。</p>
]]></content:encoded></item><item><title>Data Classification</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/data-classification/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/data-classification/</guid><description>&lt;p>Data classification 的核心概念是「依敏感度與風險把資料分級」。常見分級包括公開資料、內部資料、敏感資料、個資、金流資料、機密資料與合規資料。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-completeness/" data-link-title="Data Completeness" data-link-desc="說明資料是否完整到足以支持查詢、遷移與決策">Data Completeness&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>資料分級是資安設計的上游。Authorization、data masking、TLS、secret management、audit log、retention 與 backup policy 都需要依資料等級調整。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-completeness/" data-link-title="Data Completeness" data-link-desc="說明資料是否完整到足以支持查詢、遷移與決策">Data Completeness&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 data classification 的訊號是同一服務處理多種風險資料。商品名稱可能是公開資料，使用者地址是 PII，付款 token 是高敏感資料，管理員操作紀錄是 audit 資料。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>資料分級要落到欄位、表、事件、log、匯出與測試資料。每個等級應定義存取條件、遮罩、加密、保留期限、audit 與事故處理要求。&lt;/p></description><content:encoded><![CDATA[<p>Data classification 的核心概念是「依敏感度與風險把資料分級」。常見分級包括公開資料、內部資料、敏感資料、個資、金流資料、機密資料與合規資料。 可先對照 <a href="/blog/backend/knowledge-cards/data-completeness/" data-link-title="Data Completeness" data-link-desc="說明資料是否完整到足以支持查詢、遷移與決策">Data Completeness</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>資料分級是資安設計的上游。Authorization、data masking、TLS、secret management、audit log、retention 與 backup policy 都需要依資料等級調整。 可先對照 <a href="/blog/backend/knowledge-cards/data-completeness/" data-link-title="Data Completeness" data-link-desc="說明資料是否完整到足以支持查詢、遷移與決策">Data Completeness</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 data classification 的訊號是同一服務處理多種風險資料。商品名稱可能是公開資料，使用者地址是 PII，付款 token 是高敏感資料，管理員操作紀錄是 audit 資料。</p>
<h2 id="設計責任">設計責任</h2>
<p>資料分級要落到欄位、表、事件、log、匯出與測試資料。每個等級應定義存取條件、遮罩、加密、保留期限、audit 與事故處理要求。</p>
]]></content:encoded></item><item><title>Abuse Case</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/abuse-case/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/abuse-case/</guid><description>&lt;p>Abuse case 的核心概念是「功能本來合法，但可能被攻擊者重新組合成非預期用途」。它和 threat model 的差別在於，abuse case 更關心具體的惡意使用情境，而不是抽象風險分類。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Abuse case 會落在 &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/bola-idor/" data-link-title="BOLA / IDOR" data-link-desc="說明物件層授權缺失如何讓使用者存取不屬於自己的資料">BOLA / IDOR&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/function-level-authorization/" data-link-title="Function-Level Authorization" data-link-desc="說明功能操作本身也需要授權，不只資源 ID 需要授權">Function-Level 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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">Tenant Boundary&lt;/a> 的交界。常見場景包含 export、invite、reset、approval、trial、switch、share 與 automation。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>如果一個功能有很多例外分支、角色切換或長流程，紅隊就會把它視為可濫用面。像是匯出功能被用來批量蒐集資料、邀請流程被用來擴張不該有的存取、重設流程被用來接管帳號，這些都是 abuse case。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>防護要能回答三件事：正常目的為何、可能被怎麼濫用、濫用時要在哪一層攔下來。若流程本身包含權限跳轉、狀態切換或代理操作，這些地方就應該優先被列為 abuse case。&lt;/p></description><content:encoded><![CDATA[<p>Abuse case 的核心概念是「功能本來合法，但可能被攻擊者重新組合成非預期用途」。它和 threat model 的差別在於，abuse case 更關心具體的惡意使用情境，而不是抽象風險分類。 可先對照 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Abuse case 會落在 <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/bola-idor/" data-link-title="BOLA / IDOR" data-link-desc="說明物件層授權缺失如何讓使用者存取不屬於自己的資料">BOLA / IDOR</a>、<a href="/blog/backend/knowledge-cards/function-level-authorization/" data-link-title="Function-Level Authorization" data-link-desc="說明功能操作本身也需要授權，不只資源 ID 需要授權">Function-Level Authorization</a>、<a href="/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">Least Privilege</a> 與 <a href="/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">Tenant Boundary</a> 的交界。常見場景包含 export、invite、reset、approval、trial、switch、share 與 automation。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>如果一個功能有很多例外分支、角色切換或長流程，紅隊就會把它視為可濫用面。像是匯出功能被用來批量蒐集資料、邀請流程被用來擴張不該有的存取、重設流程被用來接管帳號，這些都是 abuse case。</p>
<h2 id="設計責任">設計責任</h2>
<p>防護要能回答三件事：正常目的為何、可能被怎麼濫用、濫用時要在哪一層攔下來。若流程本身包含權限跳轉、狀態切換或代理操作，這些地方就應該優先被列為 abuse case。</p>
]]></content:encoded></item><item><title>In-Process Channel</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/in-process-channel/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/in-process-channel/</guid><description>&lt;p>In-process channel 的核心概念是「單一 process 內用來傳遞工作或訊號的通道」。它可以是語言內建 channel、blocking queue、async queue、actor mailbox 或 framework 提供的本地 queue abstraction。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>In-process channel 屬於 application 內部協調機制。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker&lt;/a> 跨 process 保存與投遞訊息；in-process channel 只在目前 process 存活期間承擔資料傳遞與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 in-process channel 的訊號是同一個服務內部有 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer&lt;/a> 與 worker 需要解耦。HTTP handler 接到工作後，可以先放進本地 queue，由 &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> 處理；process 重啟後，尚未處理的本地工作通常會消失。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>In-process channel 要定義 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">buffer&lt;/a> 大小、阻塞行為、關閉流程、drop policy、shutdown 與觀測欄位。需要跨 process 保存、重試或 &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/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a> 或 durable queue。&lt;/p></description><content:encoded><![CDATA[<p>In-process channel 的核心概念是「單一 process 內用來傳遞工作或訊號的通道」。它可以是語言內建 channel、blocking queue、async queue、actor mailbox 或 framework 提供的本地 queue abstraction。 可先對照 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>In-process channel 屬於 application 內部協調機制。<a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker</a> 跨 process 保存與投遞訊息；in-process channel 只在目前 process 存活期間承擔資料傳遞與 <a href="/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 in-process channel 的訊號是同一個服務內部有 <a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer</a> 與 worker 需要解耦。HTTP handler 接到工作後，可以先放進本地 queue，由 <a href="/blog/backend/knowledge-cards/worker-pool/" data-link-title="Worker Pool" data-link-desc="說明一組 worker 如何限制同時處理量並保護下游資源">worker pool</a> 處理；process 重啟後，尚未處理的本地工作通常會消失。</p>
<h2 id="設計責任">設計責任</h2>
<p>In-process channel 要定義 <a href="/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">buffer</a> 大小、阻塞行為、關閉流程、drop policy、shutdown 與觀測欄位。需要跨 process 保存、重試或 <a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay</a> 的工作應升級到 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> 或 durable queue。</p>
]]></content:encoded></item><item><title>Service Endpoint</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/endpoint/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/endpoint/</guid><description>&lt;p>Service Endpoint 的核心概念是「外部請求進入服務的明確位置」。它是網路流量進入應用程式邊界的地址、路徑或命名位置。 可先對照 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Service Endpoint 位在 client、load balancer、WAF 與 application 之間，是服務對外暴露能力的入口界面，常與 &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> 一起決定流量如何進入。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 service endpoint 分級的訊號是不同入口承擔的風險不同。公開 API、管理入口、診斷入口與內部入口的流量來源、權限要求與失敗後果都不一樣。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>公開 API 需要穩定的 request/response 合約；&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/public-api-endpoint/" data-link-title="Public API Endpoint" data-link-desc="說明面向外部 client 的穩定 API 入口如何被管理">Public API Endpoint&lt;/a> 需要更高的相容性與文件品質；&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/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> 需要搭配 service discovery 與內部網路邊界。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要先定義 service endpoint 的用途、可達範圍、授權層級與錯誤回應策略。更細的入口語意應拆成專門卡片，而不是把所有 HTTP 路徑都當成同一種入口。&lt;/p></description><content:encoded><![CDATA[<p>Service Endpoint 的核心概念是「外部請求進入服務的明確位置」。它是網路流量進入應用程式邊界的地址、路徑或命名位置。 可先對照 <a href="/blog/backend/knowledge-cards/request-routing/" data-link-title="Request Routing" data-link-desc="說明入口流量如何依規則被導向不同服務或處理路徑">Request Routing</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Service Endpoint 位在 client、load balancer、WAF 與 application 之間，是服務對外暴露能力的入口界面，常與 <a href="/blog/backend/knowledge-cards/request-routing/" data-link-title="Request Routing" data-link-desc="說明入口流量如何依規則被導向不同服務或處理路徑">Request Routing</a> 一起決定流量如何進入。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 service endpoint 分級的訊號是不同入口承擔的風險不同。公開 API、管理入口、診斷入口與內部入口的流量來源、權限要求與失敗後果都不一樣。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>公開 API 需要穩定的 request/response 合約；<a href="/blog/backend/knowledge-cards/public-api-endpoint/" data-link-title="Public API Endpoint" data-link-desc="說明面向外部 client 的穩定 API 入口如何被管理">Public API Endpoint</a> 需要更高的相容性與文件品質；<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/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> 需要搭配 service discovery 與內部網路邊界。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要先定義 service endpoint 的用途、可達範圍、授權層級與錯誤回應策略。更細的入口語意應拆成專門卡片，而不是把所有 HTTP 路徑都當成同一種入口。</p>
]]></content:encoded></item><item><title>Worker Pool</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/worker-pool/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/worker-pool/</guid><description>&lt;p>Worker pool 的核心概念是「用固定或可控數量的 worker 處理工作」。它讓系統限制同時執行量，避免每個 request 或 message 都直接建立無界工作。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Worker pool 是 application 內部的容量控制工具。它常和 &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/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/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/bulkhead/" data-link-title="Bulkhead" data-link-desc="說明 bulkhead 如何用資源分艙限制故障擴散">bulkhead&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dependency-isolation/" data-link-title="Dependency Isolation" data-link-desc="說明如何隔離下游依賴，避免單一依賴耗盡共享資源">dependency isolation&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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 worker pool 的訊號是工作可以排隊，但同時執行量需要受控。圖片縮圖、匯出報表、外部 API 同步與 webhook retry 都可以用 worker pool 限制 CPU、連線或下游 API 壓力。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Worker pool 要定義 worker 數量、queue 長度、等待期限、錯誤回報、shutdown、重試與觀測欄位。擴大 worker 數前要先確認瓶頸位置：可能在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP client&lt;/a> pool 或外部 API quota。&lt;/p></description><content:encoded><![CDATA[<p>Worker pool 的核心概念是「用固定或可控數量的 worker 處理工作」。它讓系統限制同時執行量，避免每個 request 或 message 都直接建立無界工作。 可先對照 <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>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Worker pool 是 application 內部的容量控制工具。它常和 <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/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">queue depth</a>、<a href="/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure</a>、<a href="/blog/backend/knowledge-cards/bulkhead/" data-link-title="Bulkhead" data-link-desc="說明 bulkhead 如何用資源分艙限制故障擴散">bulkhead</a>、<a href="/blog/backend/knowledge-cards/dependency-isolation/" data-link-title="Dependency Isolation" data-link-desc="說明如何隔離下游依賴，避免單一依賴耗盡共享資源">dependency isolation</a> 與 <a href="/blog/backend/knowledge-cards/graceful-shutdown/" data-link-title="Graceful Shutdown" data-link-desc="說明服務停止前如何排空流量、完成工作與保存狀態">graceful shutdown</a> 一起使用。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 worker pool 的訊號是工作可以排隊，但同時執行量需要受控。圖片縮圖、匯出報表、外部 API 同步與 webhook retry 都可以用 worker pool 限制 CPU、連線或下游 API 壓力。</p>
<h2 id="設計責任">設計責任</h2>
<p>Worker pool 要定義 worker 數量、queue 長度、等待期限、錯誤回報、shutdown、重試與觀測欄位。擴大 worker 數前要先確認瓶頸位置：可能在 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a>、<a href="/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP client</a> pool 或外部 API quota。</p>
]]></content:encoded></item><item><title>Communication Protocol</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/protocol/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/protocol/</guid><description>&lt;p>Communication Protocol 的核心概念是「雙方對資料格式、順序、錯誤與互動方式達成一致的規則」。它描述的是通訊雙方如何交換資料，以及在失敗時如何解讀結果。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Communication Protocol 位在 application、client、broker、&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> 或 service 之間，決定兩端如何交換資料與解讀狀態。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 communication protocol 明確化的訊號是多個元件開始共用同一種資料交換方式。若格式不穩定，錯誤就會出現在解析、版本相容、重試語意或欄位命名上。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>請求/回應型通訊、queue message schema、webhook payload 與簽章驗證，都屬於 communication protocol 問題。這類約定需要被拆到更具體的子卡，才能維持原子性。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義版本相容、錯誤處理、欄位演進與測試方式。Communication Protocol 的目標是讓雙方知道哪些行為是約定的一部分，格式複雜度應盡量收斂。&lt;/p></description><content:encoded><![CDATA[<p>Communication Protocol 的核心概念是「雙方對資料格式、順序、錯誤與互動方式達成一致的規則」。它描述的是通訊雙方如何交換資料，以及在失敗時如何解讀結果。 可先對照 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Communication Protocol 位在 application、client、broker、<a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a> 或 service 之間，決定兩端如何交換資料與解讀狀態。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 communication protocol 明確化的訊號是多個元件開始共用同一種資料交換方式。若格式不穩定，錯誤就會出現在解析、版本相容、重試語意或欄位命名上。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>請求/回應型通訊、queue message schema、webhook payload 與簽章驗證，都屬於 communication protocol 問題。這類約定需要被拆到更具體的子卡，才能維持原子性。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義版本相容、錯誤處理、欄位演進與測試方式。Communication Protocol 的目標是讓雙方知道哪些行為是約定的一部分，格式複雜度應盡量收斂。</p>
]]></content:encoded></item><item><title>HTTP Client</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/http-client/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/http-client/</guid><description>&lt;p>HTTP client 的核心概念是「application 對外部 HTTP 服務發出 request 的呼叫邊界」。這個邊界需要管理 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&lt;/a>、&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/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS&lt;/a>、錯誤分類與觀測欄位。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>HTTP client 是常見下游依賴入口。它可能呼叫付款、通知、搜尋、身份驗證、第三方 API 或內部微服務；每個 client 都會把外部延遲與失敗帶回 application。 可先對照 &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;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要整理 HTTP client 的訊號是下游 API 變慢後，上游 request latency 與 worker 等待同步上升。付款 API timeout 時，checkout 要能快速分類錯誤、限制重試並保留使用者流程。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>HTTP client 要定義連線池、timeout、&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/exponential-backoff/" data-link-title="Exponential Backoff" data-link-desc="說明重試間隔如何逐步拉長以降低下游壓力">backoff&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/jitter/" data-link-title="Jitter" data-link-desc="說明重試或排程加入隨機偏移如何降低同步尖峰">jitter&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">authentication&lt;/a>、TLS 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">log&lt;/a> / &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-context/" data-link-title="Trace Context" data-link-desc="說明跨服務 request 如何用 trace context 串起路徑與耗時">trace&lt;/a> 欄位。不同下游應有獨立設定與觀測名稱。&lt;/p></description><content:encoded><![CDATA[<p>HTTP client 的核心概念是「application 對外部 HTTP 服務發出 request 的呼叫邊界」。這個邊界需要管理 <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>、<a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a>、<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/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS</a>、錯誤分類與觀測欄位。</p>
<h2 id="概念位置">概念位置</h2>
<p>HTTP client 是常見下游依賴入口。它可能呼叫付款、通知、搜尋、身份驗證、第三方 API 或內部微服務；每個 client 都會把外部延遲與失敗帶回 application。 可先對照 <a href="/blog/backend/knowledge-cards/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">Timeout</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要整理 HTTP client 的訊號是下游 API 變慢後，上游 request latency 與 worker 等待同步上升。付款 API timeout 時，checkout 要能快速分類錯誤、限制重試並保留使用者流程。</p>
<h2 id="設計責任">設計責任</h2>
<p>HTTP client 要定義連線池、timeout、<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/exponential-backoff/" data-link-title="Exponential Backoff" data-link-desc="說明重試間隔如何逐步拉長以降低下游壓力">backoff</a>、<a href="/blog/backend/knowledge-cards/jitter/" data-link-title="Jitter" data-link-desc="說明重試或排程加入隨機偏移如何降低同步尖峰">jitter</a>、<a href="/blog/backend/knowledge-cards/circuit-breaker/" data-link-title="Circuit Breaker" data-link-desc="說明下游持續失敗時如何暫停呼叫並保護系統">circuit breaker</a>、<a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">authentication</a>、TLS 與 <a href="/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">log</a> / <a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics</a> / <a href="/blog/backend/knowledge-cards/trace-context/" data-link-title="Trace Context" data-link-desc="說明跨服務 request 如何用 trace context 串起路徑與耗時">trace</a> 欄位。不同下游應有獨立設定與觀測名稱。</p>
]]></content:encoded></item><item><title>Container</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/container/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/container/</guid><description>&lt;p>Container 的核心概念是「把應用程式與執行環境封裝成可交付單位」。它通常承載 application binary、runtime 依賴、config 與啟動命令。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">Resource Limit&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Container 位在 build、deploy、runtime 與 platform 之間，是服務交付與資源限制的基本單位。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">Resource Limit&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 container 化的訊號是服務需要一致的啟動方式、相同的 runtime 環境、可複製的部署流程，或多個 instance 要共用同一套交付模型。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>當服務要被放進 Kubernetes、CI pipeline 或 VM 上的標準化部署流程時，container 可以把 binary、system dependency 與啟動參數打包成固定形狀，降低環境差異。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義 image 內容、啟動命令、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">resource limit&lt;/a> 與環境變數來源。Container 是讓服務交付、擴容與回滾更一致的手段，目的在服務層面。&lt;/p></description><content:encoded><![CDATA[<p>Container 的核心概念是「把應用程式與執行環境封裝成可交付單位」。它通常承載 application binary、runtime 依賴、config 與啟動命令。 可先對照 <a href="/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">Resource Limit</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Container 位在 build、deploy、runtime 與 platform 之間，是服務交付與資源限制的基本單位。 可先對照 <a href="/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">Resource Limit</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 container 化的訊號是服務需要一致的啟動方式、相同的 runtime 環境、可複製的部署流程，或多個 instance 要共用同一套交付模型。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>當服務要被放進 Kubernetes、CI pipeline 或 VM 上的標準化部署流程時，container 可以把 binary、system dependency 與啟動參數打包成固定形狀，降低環境差異。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義 image 內容、啟動命令、<a href="/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">resource limit</a> 與環境變數來源。Container 是讓服務交付、擴容與回滾更一致的手段，目的在服務層面。</p>
]]></content:encoded></item><item><title>Stream Pipeline</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/stream-pipeline/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/stream-pipeline/</guid><description>&lt;p>Stream pipeline 的核心概念是「資料連續流經多個處理階段」。每個階段讀取輸入、處理資料、送到下一階段；整體吞吐取決於最慢階段與階段之間的 buffer。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Stream pipeline 常出現在 event stream、log processing、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">CDC&lt;/a>、ETL、即時分析、IoT readings 與訊息轉換流程。它需要處理 ordering、&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/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間處理流程如何記錄可恢復進度">checkpoint&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">retry&lt;/a> 與資料完整性。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 stream pipeline 設計的訊號是資料會持續進入，且需要多步驟加工。訂單事件先做清洗，再寫入搜尋索引與報表系統；任一階段變慢，都會讓上游 lag 擴大。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Stream pipeline 要定義階段邊界、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">buffer&lt;/a>、checkpoint、錯誤隔離、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">重放&lt;/a>、lag 指標與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/correctness-check/" data-link-title="Correctness Check" data-link-desc="說明遷移或重構期間如何驗證新舊結果是否符合規則">correctness check&lt;/a>。每個階段都要能被單獨觀測與限速。&lt;/p></description><content:encoded><![CDATA[<p>Stream pipeline 的核心概念是「資料連續流經多個處理階段」。每個階段讀取輸入、處理資料、送到下一階段；整體吞吐取決於最慢階段與階段之間的 buffer。 可先對照 <a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Stream pipeline 常出現在 event stream、log processing、<a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">CDC</a>、ETL、即時分析、IoT readings 與訊息轉換流程。它需要處理 ordering、<a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition</a>、<a href="/blog/backend/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間處理流程如何記錄可恢復進度">checkpoint</a>、<a href="/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure</a>、<a href="/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">retry</a> 與資料完整性。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 stream pipeline 設計的訊號是資料會持續進入，且需要多步驟加工。訂單事件先做清洗，再寫入搜尋索引與報表系統；任一階段變慢，都會讓上游 lag 擴大。</p>
<h2 id="設計責任">設計責任</h2>
<p>Stream pipeline 要定義階段邊界、<a href="/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">buffer</a>、checkpoint、錯誤隔離、<a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">重放</a>、lag 指標與 <a href="/blog/backend/knowledge-cards/correctness-check/" data-link-title="Correctness Check" data-link-desc="說明遷移或重構期間如何驗證新舊結果是否符合規則">correctness check</a>。每個階段都要能被單獨觀測與限速。</p>
]]></content:encoded></item><item><title>Buffer</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/buffer/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/buffer/</guid><description>&lt;p>Buffer 的核心概念是「用暫存空間吸收 &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/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer&lt;/a> 之間的短暫速度差」。Buffer 可以存在於 &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/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/socket/" data-link-title="Socket" data-link-desc="說明 network socket 如何成為 application 與網路之間的資料傳輸邊界">socket&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP client&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">stream pipeline&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/write-behind-cache/" data-link-title="Write-Behind Cache" data-link-desc="說明先寫快取再非同步寫入正式來源的風險與用途">write-behind cache&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Buffer 是平滑尖峰的工具，也是延遲與記憶體風險來源。Buffer 太小會讓 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer&lt;/a> 很快被阻塞或拒絕；buffer 太大會累積延遲、記憶體壓力與過期工作。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 buffer 設計的訊號是流量有短暫 burst，但下游平均容量足夠。通知服務可以用小型 buffer 吸收幾秒尖峰；長時間進入速度高於處理速度時，buffer 只會把問題延後。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Buffer 要定義容量、等待期限、溢出策略、drop policy、觀測欄位與 shutdown 行為。觀測上要看 fill ratio、oldest item age、drop count 與處理耗時。&lt;/p></description><content:encoded><![CDATA[<p>Buffer 的核心概念是「用暫存空間吸收 <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> 之間的短暫速度差」。Buffer 可以存在於 <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/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a>、<a href="/blog/backend/knowledge-cards/socket/" data-link-title="Socket" data-link-desc="說明 network socket 如何成為 application 與網路之間的資料傳輸邊界">socket</a>、<a href="/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP client</a>、<a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a>、<a href="/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">stream pipeline</a> 或 <a href="/blog/backend/knowledge-cards/write-behind-cache/" data-link-title="Write-Behind Cache" data-link-desc="說明先寫快取再非同步寫入正式來源的風險與用途">write-behind cache</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Buffer 是平滑尖峰的工具，也是延遲與記憶體風險來源。Buffer 太小會讓 <a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer</a> 很快被阻塞或拒絕；buffer 太大會累積延遲、記憶體壓力與過期工作。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 buffer 設計的訊號是流量有短暫 burst，但下游平均容量足夠。通知服務可以用小型 buffer 吸收幾秒尖峰；長時間進入速度高於處理速度時，buffer 只會把問題延後。</p>
<h2 id="設計責任">設計責任</h2>
<p>Buffer 要定義容量、等待期限、溢出策略、drop policy、觀測欄位與 shutdown 行為。觀測上要看 fill ratio、oldest item age、drop count 與處理耗時。</p>
]]></content:encoded></item><item><title>Load Balancer</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/load-balancer/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/load-balancer/</guid><description>&lt;p>Load balancer 的核心概念是「把進來的流量導到合適的服務實例」。它常處理分流、健康檢查、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sticky-session/" data-link-title="Sticky Session" data-link-desc="說明同一 client 如何在一段時間內持續命中同一個後端實例">sticky session&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">idle timeout&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Load balancer 位在 client 與 application instances 之間，是服務接流量與停止接流量的入口控制層，常與 &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> 搭配使用。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 load balancer 的訊號是服務有多個 instance、要做 rolling update、需要平滑擴容，或必須在故障時把流量移開。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>Kubernetes service、edge proxy、&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> 或雲端 LB 都會把 request 導到健康節點。長連線服務也常依賴 load balancer 做 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining&lt;/a>，避免關閉中的 instance 繼續接新流量，也會透過 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">idle timeout&lt;/a> 回收空閒連線。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義健康條件、移除條件、回切條件與排空時間。Load balancer 本身不處理業務邏輯，但它直接影響可用性、切換速度與連線體驗。&lt;/p></description><content:encoded><![CDATA[<p>Load balancer 的核心概念是「把進來的流量導到合適的服務實例」。它常處理分流、健康檢查、<a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining</a>、<a href="/blog/backend/knowledge-cards/sticky-session/" data-link-title="Sticky Session" data-link-desc="說明同一 client 如何在一段時間內持續命中同一個後端實例">sticky session</a> 與 <a href="/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">idle timeout</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Load balancer 位在 client 與 application instances 之間，是服務接流量與停止接流量的入口控制層，常與 <a href="/blog/backend/knowledge-cards/request-routing/" data-link-title="Request Routing" data-link-desc="說明入口流量如何依規則被導向不同服務或處理路徑">Request Routing</a> 搭配使用。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 load balancer 的訊號是服務有多個 instance、要做 rolling update、需要平滑擴容，或必須在故障時把流量移開。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>Kubernetes service、edge proxy、<a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a> 或雲端 LB 都會把 request 導到健康節點。長連線服務也常依賴 load balancer 做 <a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining</a>，避免關閉中的 instance 繼續接新流量，也會透過 <a href="/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">idle timeout</a> 回收空閒連線。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義健康條件、移除條件、回切條件與排空時間。Load balancer 本身不處理業務邏輯，但它直接影響可用性、切換速度與連線體驗。</p>
]]></content:encoded></item><item><title>Queue</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/queue/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/queue/</guid><description>&lt;p>Queue 的核心概念是「把等待處理的工作依序放入一個可觀測的等待區」。它讓 &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/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer&lt;/a> 在時間上解耦，也讓系統可以用等待長度、等待時間與處理速率評估容量壓力。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Queue 可以存在於 application 內部（&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a>、database table 或 stream platform 提供。Application 內部的 queue 隨 process 生命週期消失；跨 process、需要保存與重放的 queue 通常需要 &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> 或 broker。&lt;/p>
&lt;p>Queue 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic&lt;/a> 的差異：queue 的語意通常是「一筆訊息被一個 consumer 處理」（competing consumers），topic 的語意是「一筆訊息可以被多個 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out&lt;/a>）。但不同 broker 的術語定義不同 — RabbitMQ 的 queue 跟 Kafka 的 partition 在消費語意上有本質差異。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 queue 的訊號是進入速度跟處理速度會短暫不一致。寄信、報表匯出、圖片轉檔、訂單狀態同步都適合先排入 queue，再由 consumer 依照容量處理。&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> 跟 oldest item age 會反映延遲壓力 — queue depth 持續增長代表 consumer 來不及消化，需要擴展 consumer 或降低進入速率。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Queue 要定義容量上限、排序語意（FIFO / priority / delay）、保存期限（&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention&lt;/a>）、消費模式（pull vs push）、失敗處理（&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure&lt;/a> 策略（滿了怎麼辦 — block / drop / reject）與觀測欄位。設計上要區分「等待可以接受」跟「等待會傷害產品結果」— 付款入帳能短暫排隊，互動式 API response 通常需要更短的等待期限與更明確的拒絕策略。&lt;/p></description><content:encoded><![CDATA[<p>Queue 的核心概念是「把等待處理的工作依序放入一個可觀測的等待區」。它讓 <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> 在時間上解耦，也讓系統可以用等待長度、等待時間與處理速率評估容量壓力。</p>
<h2 id="概念位置">概念位置</h2>
<p>Queue 可以存在於 application 內部（<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>），也可以由 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a>、database table 或 stream platform 提供。Application 內部的 queue 隨 process 生命週期消失；跨 process、需要保存與重放的 queue 通常需要 <a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue</a> 或 broker。</p>
<p>Queue 跟 <a href="/blog/backend/knowledge-cards/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic</a> 的差異：queue 的語意通常是「一筆訊息被一個 consumer 處理」（competing consumers），topic 的語意是「一筆訊息可以被多個 <a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group</a> 各自處理」（<a href="/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out</a>）。但不同 broker 的術語定義不同 — RabbitMQ 的 queue 跟 Kafka 的 partition 在消費語意上有本質差異。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 queue 的訊號是進入速度跟處理速度會短暫不一致。寄信、報表匯出、圖片轉檔、訂單狀態同步都適合先排入 queue，再由 consumer 依照容量處理。<a href="/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">Queue depth</a> 跟 oldest item age 會反映延遲壓力 — queue depth 持續增長代表 consumer 來不及消化，需要擴展 consumer 或降低進入速率。</p>
<h2 id="設計責任">設計責任</h2>
<p>Queue 要定義容量上限、排序語意（FIFO / priority / delay）、保存期限（<a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention</a>）、消費模式（pull vs push）、失敗處理（<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>）、<a href="/blog/backend/knowledge-cards/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure</a> 策略（滿了怎麼辦 — block / drop / reject）與觀測欄位。設計上要區分「等待可以接受」跟「等待會傷害產品結果」— 付款入帳能短暫排隊，互動式 API response 通常需要更短的等待期限與更明確的拒絕策略。</p>
]]></content:encoded></item><item><title>Sticky Session</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/sticky-session/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/sticky-session/</guid><description>&lt;p>Sticky Session 的核心概念是「讓同一個 client、session 或 connection 在一段時間內持續命中同一個服務實例」。它是一種負載平衡策略，常用來維持本機狀態、暫存資料或未外部化 session 的可用性。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">Stream Pipeline&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Sticky Session 位在 client、load balancer、application instances 與 session state 之間。它改變的是流量分派規則，不是應用邏輯本身。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">Stream Pipeline&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 sticky session 的訊號是：&lt;/p>
&lt;ul>
&lt;li>服務仍保存本機狀態，短期內不容易外部化&lt;/li>
&lt;li>多步驟互動需要維持同一個後端實例&lt;/li>
&lt;li>session state 還沒移到共享儲存或快取&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>聊天室、即時遊戲、某些登入流程、需要本機暫存的舊系統，常會要求同一個使用者在 session 期間保持 sticky routing。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義黏著的判斷鍵、有效時間、失效後怎麼重新導向、以及單一 instance 故障時如何處理 session 遷移。Sticky Session 會讓負載分佈變得不均，因此要清楚知道它是權宜策略，不是預設最佳解。&lt;/p></description><content:encoded><![CDATA[<p>Sticky Session 的核心概念是「讓同一個 client、session 或 connection 在一段時間內持續命中同一個服務實例」。它是一種負載平衡策略，常用來維持本機狀態、暫存資料或未外部化 session 的可用性。 可先對照 <a href="/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">Stream Pipeline</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Sticky Session 位在 client、load balancer、application instances 與 session state 之間。它改變的是流量分派規則，不是應用邏輯本身。 可先對照 <a href="/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">Stream Pipeline</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 sticky session 的訊號是：</p>
<ul>
<li>服務仍保存本機狀態，短期內不容易外部化</li>
<li>多步驟互動需要維持同一個後端實例</li>
<li>session state 還沒移到共享儲存或快取</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>聊天室、即時遊戲、某些登入流程、需要本機暫存的舊系統，常會要求同一個使用者在 session 期間保持 sticky routing。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義黏著的判斷鍵、有效時間、失效後怎麼重新導向、以及單一 instance 故障時如何處理 session 遷移。Sticky Session 會讓負載分佈變得不均，因此要清楚知道它是權宜策略，不是預設最佳解。</p>
]]></content:encoded></item><item><title>Probe</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/probe/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/probe/</guid><description>&lt;p>Probe 的核心概念是「平台主動探測服務狀態的訊號」。它常見於 readiness probe 與 liveness probe，也可能擴展到 startup probe。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">Producer&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Probe 位在 platform 與 application 之間，讓調度系統知道 instance 是否可接流量、是否仍存活，或是否仍在啟動中。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">Producer&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 probe 的訊號是啟動、擴容、故障、健康檢查與回收流程需要自動化判斷。沒有 probe，平台只能用硬編碼規則猜測服務狀態。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>Kubernetes 會用 probe 決定 instance 是否加入流量池。Readiness probe 檢查能否接流量；liveness probe 檢查 process 是否卡死；startup probe 則可保護啟動較慢的服務。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要讓 probe 簡單、快速、穩定，並且只反映它自己的責任範圍。Probe 不應該做昂貴查詢或深度業務判斷，否則平台訊號會不穩定。&lt;/p></description><content:encoded><![CDATA[<p>Probe 的核心概念是「平台主動探測服務狀態的訊號」。它常見於 readiness probe 與 liveness probe，也可能擴展到 startup probe。 可先對照 <a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">Producer</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Probe 位在 platform 與 application 之間，讓調度系統知道 instance 是否可接流量、是否仍存活，或是否仍在啟動中。 可先對照 <a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">Producer</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 probe 的訊號是啟動、擴容、故障、健康檢查與回收流程需要自動化判斷。沒有 probe，平台只能用硬編碼規則猜測服務狀態。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>Kubernetes 會用 probe 決定 instance 是否加入流量池。Readiness probe 檢查能否接流量；liveness probe 檢查 process 是否卡死；startup probe 則可保護啟動較慢的服務。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要讓 probe 簡單、快速、穩定，並且只反映它自己的責任範圍。Probe 不應該做昂貴查詢或深度業務判斷，否則平台訊號會不穩定。</p>
]]></content:encoded></item><item><title>Startup Probe</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/startup-probe/</link><pubDate>Tue, 23 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/startup-probe/</guid><description>&lt;p>Startup probe 的核心概念是「在服務啟動期間持續探測、確認初始化完成後再交棒給 liveness 與 readiness &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/probe/" data-link-title="Probe" data-link-desc="說明平台如何透過 probe 判斷服務狀態與接流量條件">probe&lt;/a>」。它保護啟動時間長的服務（JVM warmup、大量依賴連線建立）不被 liveness 在初始化期間判定失敗而反覆重啟。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/probe/" data-link-title="Probe" data-link-desc="說明平台如何透過 probe 判斷服務狀態與接流量條件">Probe&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Startup probe 位在 container 啟動與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness&lt;/a> / liveness 之間。startup probe 成功前，liveness 和 readiness 不會啟動。startup probe 一旦成功就永久停用，由 liveness 和 readiness 接手。可先對照 &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;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 startup probe 的訊號是「服務啟動時間超過 liveness 的預設容忍窗口」。典型場景：JVM 服務 warmup 需 30-60 秒、依賴多的服務需要等資料庫連線池和 cache 連線建立。沒有 startup probe 時，liveness 會在初始化期間把健康的服務判定為壞掉，觸發 restart loop。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>startup probe 的總容忍時間 = &lt;code>failureThreshold × periodSeconds&lt;/code>。設計時先量測服務在最差情境下的啟動時間（冷啟動 + image pull + 依賴連線），再加 headroom。startup probe 跟 &lt;code>initialDelaySeconds&lt;/code> 解決同一個問題，但 startup probe 在啟動期間持續探測（能偵測啟動失敗），&lt;code>initialDelaySeconds&lt;/code> 是盲等（無法觀測啟動進度）。&lt;/p></description><content:encoded><![CDATA[<p>Startup probe 的核心概念是「在服務啟動期間持續探測、確認初始化完成後再交棒給 liveness 與 readiness <a href="/blog/backend/knowledge-cards/probe/" data-link-title="Probe" data-link-desc="說明平台如何透過 probe 判斷服務狀態與接流量條件">probe</a>」。它保護啟動時間長的服務（JVM warmup、大量依賴連線建立）不被 liveness 在初始化期間判定失敗而反覆重啟。可先對照 <a href="/blog/backend/knowledge-cards/probe/" data-link-title="Probe" data-link-desc="說明平台如何透過 probe 判斷服務狀態與接流量條件">Probe</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Startup probe 位在 container 啟動與 <a href="/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness</a> / liveness 之間。startup probe 成功前，liveness 和 readiness 不會啟動。startup probe 一旦成功就永久停用，由 liveness 和 readiness 接手。可先對照 <a href="/blog/backend/knowledge-cards/graceful-shutdown/" data-link-title="Graceful Shutdown" data-link-desc="說明服務停止前如何排空流量、完成工作與保存狀態">Graceful Shutdown</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 startup probe 的訊號是「服務啟動時間超過 liveness 的預設容忍窗口」。典型場景：JVM 服務 warmup 需 30-60 秒、依賴多的服務需要等資料庫連線池和 cache 連線建立。沒有 startup probe 時，liveness 會在初始化期間把健康的服務判定為壞掉，觸發 restart loop。</p>
<h2 id="設計責任">設計責任</h2>
<p>startup probe 的總容忍時間 = <code>failureThreshold × periodSeconds</code>。設計時先量測服務在最差情境下的啟動時間（冷啟動 + image pull + 依賴連線），再加 headroom。startup probe 跟 <code>initialDelaySeconds</code> 解決同一個問題，但 startup probe 在啟動期間持續探測（能偵測啟動失敗），<code>initialDelaySeconds</code> 是盲等（無法觀測啟動進度）。</p>
]]></content:encoded></item><item><title>API Gateway</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/api-gateway/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/api-gateway/</guid><description>&lt;p>API Gateway 的核心概念是「把對外流量先收斂到一層可集中控制的入口」。它負責把 client 的 request 轉成後端可處理的路由與共同政策，常見責任包括路由、身份驗證、節流、標頭補寫、版本切換與觀測欄位傳遞。 可先對照 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>API Gateway 位在 client 與多個 backend service 之間，通常介於 load balancer 和 application 之間，作為外部入口的統一控制點，並常與 &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> 一起決定流量要導向哪個後端。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 API Gateway 的訊號是：&lt;/p>
&lt;ul>
&lt;li>多個服務共享同一個對外入口&lt;/li>
&lt;li>想把 auth、rate limit、request id、&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> 集中處理&lt;/li>
&lt;li>希望在不改每個 service 的情況下調整入口行為&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>公共 API、行動 app、合作夥伴整合或多租戶入口常會先經過 API Gateway，再導向對應 service、internal endpoint 或特定版本路由。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要明確定義 gateway 能做與不能做的事。它應承擔流量入口治理，而不應塞入核心業務邏輯，否則會變成難以維護的分散型控制層。&lt;/p></description><content:encoded><![CDATA[<p>API Gateway 的核心概念是「把對外流量先收斂到一層可集中控制的入口」。它負責把 client 的 request 轉成後端可處理的路由與共同政策，常見責任包括路由、身份驗證、節流、標頭補寫、版本切換與觀測欄位傳遞。 可先對照 <a href="/blog/backend/knowledge-cards/request-routing/" data-link-title="Request Routing" data-link-desc="說明入口流量如何依規則被導向不同服務或處理路徑">Request Routing</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>API Gateway 位在 client 與多個 backend service 之間，通常介於 load balancer 和 application 之間，作為外部入口的統一控制點，並常與 <a href="/blog/backend/knowledge-cards/request-routing/" data-link-title="Request Routing" data-link-desc="說明入口流量如何依規則被導向不同服務或處理路徑">Request Routing</a> 一起決定流量要導向哪個後端。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 API Gateway 的訊號是：</p>
<ul>
<li>多個服務共享同一個對外入口</li>
<li>想把 auth、rate limit、request id、<a href="/blog/backend/knowledge-cards/request-routing/" data-link-title="Request Routing" data-link-desc="說明入口流量如何依規則被導向不同服務或處理路徑">Request Routing</a> 集中處理</li>
<li>希望在不改每個 service 的情況下調整入口行為</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>公共 API、行動 app、合作夥伴整合或多租戶入口常會先經過 API Gateway，再導向對應 service、internal endpoint 或特定版本路由。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要明確定義 gateway 能做與不能做的事。它應承擔流量入口治理，而不應塞入核心業務邏輯，否則會變成難以維護的分散型控制層。</p>
]]></content:encoded></item><item><title>Draining</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/draining/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/draining/</guid><description>&lt;p>Draining 的核心概念是「先把新的 request 停掉，再讓已經進來的工作在期限內完成或交回」。它是負載切換與停止流程中的保護動作，常出現在 rolling update、縮容、故障切換與 graceful shutdown。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">Dual Write&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Draining 位在 load balancer、deployment platform、application 與 in-flight work 之間。它介於流量入口與工作完成之間，目標是避免切換瞬間把正在處理的請求硬切掉。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">Dual Write&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 draining 的訊號是：&lt;/p>
&lt;ul>
&lt;li>instance 要下線或被替換&lt;/li>
&lt;li>長連線或背景工作不能被直接中斷&lt;/li>
&lt;li>切流時需要避免新請求進入舊實例&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>Kubernetes rolling update 前先讓 instance 進入 draining、load balancer 在切流前停止導入新連線、worker 停止接收新 job 但完成目前處理，都是 draining 的應用。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義何時開始 draining、draining 多久、超時後怎麼強制終止，以及如何觀察 in-flight request、consumer ack 與長連線狀態。Draining 的目的是把切換風險壓到可接受範圍，無限等待反而製造新風險。&lt;/p></description><content:encoded><![CDATA[<p>Draining 的核心概念是「先把新的 request 停掉，再讓已經進來的工作在期限內完成或交回」。它是負載切換與停止流程中的保護動作，常出現在 rolling update、縮容、故障切換與 graceful shutdown。 可先對照 <a href="/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">Dual Write</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Draining 位在 load balancer、deployment platform、application 與 in-flight work 之間。它介於流量入口與工作完成之間，目標是避免切換瞬間把正在處理的請求硬切掉。 可先對照 <a href="/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">Dual Write</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 draining 的訊號是：</p>
<ul>
<li>instance 要下線或被替換</li>
<li>長連線或背景工作不能被直接中斷</li>
<li>切流時需要避免新請求進入舊實例</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>Kubernetes rolling update 前先讓 instance 進入 draining、load balancer 在切流前停止導入新連線、worker 停止接收新 job 但完成目前處理，都是 draining 的應用。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義何時開始 draining、draining 多久、超時後怎麼強制終止，以及如何觀察 in-flight request、consumer ack 與長連線狀態。Draining 的目的是把切換風險壓到可接受範圍，無限等待反而製造新風險。</p>
]]></content:encoded></item><item><title>Socket</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/socket/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/socket/</guid><description>&lt;p>Socket 的核心概念是「application 和網路連線之間的資料讀寫端點」。HTTP、database driver、broker client 與自訂 TCP protocol 最後都會透過 socket 讀寫資料，因此 socket 行為會影響 timeout、連線池、buffer 與資源耗盡風險。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP Client&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Socket 位在 application runtime、作業系統與網路之間。上層通常看到的是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP client&lt;/a>、database client 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a> client；底層則由 socket 負責連線、讀取、寫入與關閉。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要理解 socket 的訊號是外部依賴變慢時，application 的連線數、等待時間與資源使用同步上升。付款 API response 變慢時，HTTP client 可能佔住更多 socket；如果 timeout 太長，worker 會把時間花在等待網路回應。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Socket 相關設計要定義連線數上限、read / write timeout、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">idle timeout&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">buffer&lt;/a> 大小與關閉流程。操作上要觀察連線數、timeout、reset、重連次數與下游 latency，避免網路等待耗盡 application 的 worker 或檔案描述符。&lt;/p></description><content:encoded><![CDATA[<p>Socket 的核心概念是「application 和網路連線之間的資料讀寫端點」。HTTP、database driver、broker client 與自訂 TCP protocol 最後都會透過 socket 讀寫資料，因此 socket 行為會影響 timeout、連線池、buffer 與資源耗盡風險。 可先對照 <a href="/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP Client</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Socket 位在 application runtime、作業系統與網路之間。上層通常看到的是 <a href="/blog/backend/knowledge-cards/http-client/" data-link-title="HTTP Client" data-link-desc="說明服務呼叫外部 HTTP 依賴時需要管理 timeout、連線與重試">HTTP client</a>、database client 或 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> client；底層則由 socket 負責連線、讀取、寫入與關閉。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要理解 socket 的訊號是外部依賴變慢時，application 的連線數、等待時間與資源使用同步上升。付款 API response 變慢時，HTTP client 可能佔住更多 socket；如果 timeout 太長，worker 會把時間花在等待網路回應。</p>
<h2 id="設計責任">設計責任</h2>
<p>Socket 相關設計要定義連線數上限、read / write timeout、<a href="/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">idle timeout</a>、<a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a>、<a href="/blog/backend/knowledge-cards/buffer/" data-link-title="Buffer" data-link-desc="說明系統如何用暫存空間吸收短暫速度差與尖峰流量">buffer</a> 大小與關閉流程。操作上要觀察連線數、timeout、reset、重連次數與下游 latency，避免網路等待耗盡 application 的 worker 或檔案描述符。</p>
]]></content:encoded></item><item><title>Idle Timeout</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/idle-timeout/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/idle-timeout/</guid><description>&lt;p>Idle Timeout 的核心概念是「一段時間沒有活動就關閉連線或回收會話」。它和一般 request timeout 不同，重點是避免空閒連線長時間佔住資源，跟等待單次操作完成的 request timeout 不同。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/impact-scope/" data-link-title="Impact Scope" data-link-desc="說明事故中如何盤點受影響範圍，支持通報、回復與責任判讀">Impact Scope&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Idle Timeout 位在 socket、load balancer、proxy、application 與 connection pool 之間。它常用來保護連線資源，避免長時間閒置造成檔案描述符、memory 或 session state 浪費。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/impact-scope/" data-link-title="Impact Scope" data-link-desc="說明事故中如何盤點受影響範圍，支持通報、回復與責任判讀">Impact Scope&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 idle timeout 的訊號是：&lt;/p>
&lt;ul>
&lt;li>長連線長時間沒有資料交換&lt;/li>
&lt;li>空閒連線數量持續累積&lt;/li>
&lt;li>load balancer 或 proxy 需要回收無效連線&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>WebSocket 連線、HTTP keep-alive、反向代理連線池或 application 內部 socket pool，常會透過 idle timeout 回收不再使用的連線。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義閒置判定條件、關閉前通知、重連策略與是否允許不同層級使用不同 timeout。Idle Timeout 應該和 read/write timeout、request timeout 區分開來，避免把不同問題混在一起。&lt;/p></description><content:encoded><![CDATA[<p>Idle Timeout 的核心概念是「一段時間沒有活動就關閉連線或回收會話」。它和一般 request timeout 不同，重點是避免空閒連線長時間佔住資源，跟等待單次操作完成的 request timeout 不同。 可先對照 <a href="/blog/backend/knowledge-cards/impact-scope/" data-link-title="Impact Scope" data-link-desc="說明事故中如何盤點受影響範圍，支持通報、回復與責任判讀">Impact Scope</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Idle Timeout 位在 socket、load balancer、proxy、application 與 connection pool 之間。它常用來保護連線資源，避免長時間閒置造成檔案描述符、memory 或 session state 浪費。 可先對照 <a href="/blog/backend/knowledge-cards/impact-scope/" data-link-title="Impact Scope" data-link-desc="說明事故中如何盤點受影響範圍，支持通報、回復與責任判讀">Impact Scope</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 idle timeout 的訊號是：</p>
<ul>
<li>長連線長時間沒有資料交換</li>
<li>空閒連線數量持續累積</li>
<li>load balancer 或 proxy 需要回收無效連線</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>WebSocket 連線、HTTP keep-alive、反向代理連線池或 application 內部 socket pool，常會透過 idle timeout 回收不再使用的連線。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義閒置判定條件、關閉前通知、重連策略與是否允許不同層級使用不同 timeout。Idle Timeout 應該和 read/write timeout、request timeout 區分開來，避免把不同問題混在一起。</p>
]]></content:encoded></item><item><title>Request Routing</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/request-routing/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/request-routing/</guid><description>&lt;p>Request Routing 的核心概念是「根據 request 的特徵，決定它應該被送到哪個服務或哪條處理路徑」。它處理的是入口層的分派規則，而不是訊息 broker 內部的 routing rule。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Request Routing 位在 client、&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/load-balancer/" data-link-title="Load Balancer" data-link-desc="說明流量如何分散、排空與導向健康節點">Load Balancer&lt;/a> 與 application 之間。它通常依 host、path、header、method、tenant、版本或地區決定流量走向。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 request routing 的訊號是：&lt;/p>
&lt;ul>
&lt;li>同一個對外入口要支援多個服務或版本&lt;/li>
&lt;li>不同路徑需要不同安全政策、觀測欄位或後端處理&lt;/li>
&lt;li>需要在不改 client 的情況下調整入口分派&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>&lt;code>/api/v1&lt;/code> 與 &lt;code>/api/v2&lt;/code> 導向不同版本服務、依 tenant 送到不同區域、依 path 導向不同內部服務，或把健康流量從一組 instance 切到另一組，都屬於 request routing。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義匹配條件、優先順序、預設路徑與回復方式。Request Routing 本身不應承擔業務邏輯，只應負責把入口流量穩定送到正確目標。&lt;/p></description><content:encoded><![CDATA[<p>Request Routing 的核心概念是「根據 request 的特徵，決定它應該被送到哪個服務或哪條處理路徑」。它處理的是入口層的分派規則，而不是訊息 broker 內部的 routing rule。 可先對照 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Request Routing 位在 client、<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/load-balancer/" data-link-title="Load Balancer" data-link-desc="說明流量如何分散、排空與導向健康節點">Load Balancer</a> 與 application 之間。它通常依 host、path、header、method、tenant、版本或地區決定流量走向。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 request routing 的訊號是：</p>
<ul>
<li>同一個對外入口要支援多個服務或版本</li>
<li>不同路徑需要不同安全政策、觀測欄位或後端處理</li>
<li>需要在不改 client 的情況下調整入口分派</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p><code>/api/v1</code> 與 <code>/api/v2</code> 導向不同版本服務、依 tenant 送到不同區域、依 path 導向不同內部服務，或把健康流量從一組 instance 切到另一組，都屬於 request routing。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義匹配條件、優先順序、預設路徑與回復方式。Request Routing 本身不應承擔業務邏輯，只應負責把入口流量穩定送到正確目標。</p>
]]></content:encoded></item><item><title>Producer</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/producer/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/producer/</guid><description>&lt;p>Producer 的核心概念是「產生工作、事件或資料並送入後續處理路徑的角色」。它可以是 API handler、排程任務、database change capture、外部 webhook 或任何把資料放進 &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/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">stream pipeline&lt;/a> 的元件。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Producer 位在資料流的上游。它的送入速度、資料品質與錯誤處理會直接影響 &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/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/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure&lt;/a> 與下游成本。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要辨識 producer 的訊號是同一個處理路徑有多個資料來源。訂單建立 API、批次匯入工具與第三方 webhook 都可能產生訂單事件；如果每個 producer 的資料格式與重試策略不同，consumer 會承擔更多判斷成本。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Producer 要定義送入條件、資料格式、唯一識別碼、&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-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">retry policy&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> 與觀測欄位。操作上要能按 producer 來源查看進入速率、錯誤率、payload 大小與被拒絕數量，才能在尖峰或資料異常時定位來源。&lt;/p></description><content:encoded><![CDATA[<p>Producer 的核心概念是「產生工作、事件或資料並送入後續處理路徑的角色」。它可以是 API handler、排程任務、database change capture、外部 webhook 或任何把資料放進 <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a>、<a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> 與 <a href="/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">stream pipeline</a> 的元件。</p>
<h2 id="概念位置">概念位置</h2>
<p>Producer 位在資料流的上游。它的送入速度、資料品質與錯誤處理會直接影響 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</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/backpressure/" data-link-title="Backpressure" data-link-desc="說明下游處理速度不足時系統如何讓上游依下游能力送出工作">backpressure</a> 與下游成本。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要辨識 producer 的訊號是同一個處理路徑有多個資料來源。訂單建立 API、批次匯入工具與第三方 webhook 都可能產生訂單事件；如果每個 producer 的資料格式與重試策略不同，consumer 會承擔更多判斷成本。</p>
<h2 id="設計責任">設計責任</h2>
<p>Producer 要定義送入條件、資料格式、唯一識別碼、<a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a>、<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/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">rate limit</a> 與觀測欄位。操作上要能按 producer 來源查看進入速率、錯誤率、payload 大小與被拒絕數量，才能在尖峰或資料異常時定位來源。</p>
]]></content:encoded></item><item><title>WebSocket</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/websocket/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/websocket/</guid><description>&lt;p>WebSocket 的核心概念是「在單一連線上維持雙向即時資料交換」。它通常從 HTTP upgrade 開始，之後以長連線承載訊息推送、狀態同步與即時互動。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/socket/" data-link-title="Socket" data-link-desc="說明 network socket 如何成為 application 與網路之間的資料傳輸邊界">Socket&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>WebSocket 位在 application 與網路連線之間，常用於聊天、協作編輯、presence、即時通知與 dashboard 更新。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/socket/" data-link-title="Socket" data-link-desc="說明 network socket 如何成為 application 與網路之間的資料傳輸邊界">socket&lt;/a> 不同的是，WebSocket 是上層通訊協定與互動模式，而 socket 是底層連線抽象。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 WebSocket 的訊號是 client 需要持續收到變化，且單純 request / response 太慢或太重。多人聊天室、即時客服、任務進度與連線狀態同步都常見 WebSocket。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>WebSocket 設計要定義連線生命週期、heartbeat、reconnect、訊息順序、disconnect 處理與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">offline catch-up&lt;/a>。若訊息不能遺失，通常還要搭配 &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;/p></description><content:encoded><![CDATA[<p>WebSocket 的核心概念是「在單一連線上維持雙向即時資料交換」。它通常從 HTTP upgrade 開始，之後以長連線承載訊息推送、狀態同步與即時互動。 可先對照 <a href="/blog/backend/knowledge-cards/socket/" data-link-title="Socket" data-link-desc="說明 network socket 如何成為 application 與網路之間的資料傳輸邊界">Socket</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>WebSocket 位在 application 與網路連線之間，常用於聊天、協作編輯、presence、即時通知與 dashboard 更新。它和 <a href="/blog/backend/knowledge-cards/socket/" data-link-title="Socket" data-link-desc="說明 network socket 如何成為 application 與網路之間的資料傳輸邊界">socket</a> 不同的是，WebSocket 是上層通訊協定與互動模式，而 socket 是底層連線抽象。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 WebSocket 的訊號是 client 需要持續收到變化，且單純 request / response 太慢或太重。多人聊天室、即時客服、任務進度與連線狀態同步都常見 WebSocket。</p>
<h2 id="設計責任">設計責任</h2>
<p>WebSocket 設計要定義連線生命週期、heartbeat、reconnect、訊息順序、disconnect 處理與 <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>
]]></content:encoded></item><item><title>Consumer</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/consumer/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/consumer/</guid><description>&lt;p>Consumer 的核心概念是「從等待區取得工作、事件或資料並執行處理的角色」。它可以從 &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/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">stream pipeline&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a> table 或 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Consumer 位在資料流的下游。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer&lt;/a> 構成 MQ 的基本角色對 — producer 負責把工作送進等待區，consumer 負責取出並處理。&lt;/p>
&lt;p>多個 consumer 組成 &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> 來分攤處理負載。Consumer 的處理速度跟錯誤行為直接影響 &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;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要辨識 consumer 的訊號是資料已經送入系統但產品結果還沒完成。付款事件送入後，入帳 consumer 要更新帳務狀態；通知事件送入後，寄信 consumer 要呼叫郵件服務。兩者都要清楚記錄處理成功、暫時失敗與永久拒絕。&lt;/p>
&lt;p>Consumer 的處理模式影響系統的可靠性保證。&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency&lt;/a> 決定「重複收到同一筆訊息時是否會產生副作用」。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Consumer 要定義併發數、&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> 條件、錯誤分類（暫時性 vs 永久性）、&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-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">retry policy&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;/p>
&lt;p>操作面要能觀測：處理速率（messages/sec）、失敗類型分布、oldest unprocessed message age、&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> 累積量與下游 dependency latency。Consumer lag 持續增長是容量不足的 leading indicator。&lt;/p></description><content:encoded><![CDATA[<p>Consumer 的核心概念是「從等待區取得工作、事件或資料並執行處理的角色」。它可以從 <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a>、<a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a>、<a href="/blog/backend/knowledge-cards/stream-pipeline/" data-link-title="Stream Pipeline" data-link-desc="說明連續資料流經多個處理階段時如何管理吞吐、順序與 backpressure ">stream pipeline</a>、<a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a> table 或 <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> 取得資料，再更新狀態、呼叫外部服務或產生衍生資料。</p>
<h2 id="概念位置">概念位置</h2>
<p>Consumer 位在資料流的下游。它跟 <a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer</a> 構成 MQ 的基本角色對 — producer 負責把工作送進等待區，consumer 負責取出並處理。</p>
<p>多個 consumer 組成 <a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group</a> 來分攤處理負載。Consumer 的處理速度跟錯誤行為直接影響 <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>（無法處理的訊息去處）。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要辨識 consumer 的訊號是資料已經送入系統但產品結果還沒完成。付款事件送入後，入帳 consumer 要更新帳務狀態；通知事件送入後，寄信 consumer 要呼叫郵件服務。兩者都要清楚記錄處理成功、暫時失敗與永久拒絕。</p>
<p>Consumer 的處理模式影響系統的可靠性保證。<a href="/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">Ack / nack</a> 的時機決定「訊息什麼時候算處理完成」；<a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 決定「重複收到同一筆訊息時是否會產生副作用」。</p>
<h2 id="設計責任">設計責任</h2>
<p>Consumer 要定義併發數、<a href="/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">ack / nack</a> 條件、錯誤分類（暫時性 vs 永久性）、<a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a>、<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/graceful-shutdown/" data-link-title="Graceful Shutdown" data-link-desc="說明服務停止前如何排空流量、完成工作與保存狀態">graceful shutdown</a> 與觀測欄位。</p>
<p>操作面要能觀測：處理速率（messages/sec）、失敗類型分布、oldest unprocessed message age、<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> 累積量與下游 dependency latency。Consumer lag 持續增長是容量不足的 leading indicator。</p>
]]></content:encoded></item><item><title>Health Check</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/health-check/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/health-check/</guid><description>&lt;p>Health Check 的核心概念是「讓平台用一個簡單回應判斷服務是否值得接流量或是否需要介入」。它是狀態判斷的入口語意，不等於 readiness、liveness 或 diagnostic endpoint 本身。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/histogram/" data-link-title="Histogram" data-link-desc="說明 histogram 如何用分桶統計延遲、大小與分布">Histogram&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Health Check 位在 load balancer、platform、diagnostic endpoint 與 application 之間。平台會依這個回應決定是否導流、是否重啟，或是否需要進一步檢查。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/histogram/" data-link-title="Histogram" data-link-desc="說明 histogram 如何用分桶統計延遲、大小與分布">Histogram&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 health check 的訊號是服務需要一個快速、低成本、可自動化的狀態回應，讓平台不用靠猜測判斷是否正常。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>Load balancer 以 health check 判斷 instance 能否接新流量；運維工具以 health check 快速確認服務是否仍回應；Kubernetes 會把 health check 的責任拆到 readiness / liveness / startup probe。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要讓 health check 保持簡單、穩定、低成本，並且只反映它被設計要回答的問題。更細的流量條件交給 readiness，更細的存活條件交給 liveness，更完整的操作介面交給 diagnostic endpoint。&lt;/p></description><content:encoded><![CDATA[<p>Health Check 的核心概念是「讓平台用一個簡單回應判斷服務是否值得接流量或是否需要介入」。它是狀態判斷的入口語意，不等於 readiness、liveness 或 diagnostic endpoint 本身。 可先對照 <a href="/blog/backend/knowledge-cards/histogram/" data-link-title="Histogram" data-link-desc="說明 histogram 如何用分桶統計延遲、大小與分布">Histogram</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Health Check 位在 load balancer、platform、diagnostic endpoint 與 application 之間。平台會依這個回應決定是否導流、是否重啟，或是否需要進一步檢查。 可先對照 <a href="/blog/backend/knowledge-cards/histogram/" data-link-title="Histogram" data-link-desc="說明 histogram 如何用分桶統計延遲、大小與分布">Histogram</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 health check 的訊號是服務需要一個快速、低成本、可自動化的狀態回應，讓平台不用靠猜測判斷是否正常。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>Load balancer 以 health check 判斷 instance 能否接新流量；運維工具以 health check 快速確認服務是否仍回應；Kubernetes 會把 health check 的責任拆到 readiness / liveness / startup probe。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要讓 health check 保持簡單、穩定、低成本，並且只反映它被設計要回答的問題。更細的流量條件交給 readiness，更細的存活條件交給 liveness，更完整的操作介面交給 diagnostic endpoint。</p>
]]></content:encoded></item><item><title>Server-Sent Events (SSE)</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/sse/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/sse/</guid><description>&lt;p>Server-Sent Events 的核心概念是「server 用持續的 HTTP response 對 client 單向推送事件」。它比 WebSocket 更適合單向通知、直播更新與簡單即時狀態流。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">Offline Catch-up&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SSE 位在 HTTP 之上，適合 server 主導的事件串流。它常用於通知、進度更新、系統訊號與簡化版即時 feed。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">Offline Catch-up&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 SSE 的訊號是 client 只需要接收事件、不需要頻繁回傳雙向互動。活動進度條、批次作業狀態、公告 feed 與監控看板更新都可能使用 SSE。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>SSE 設計要定義斷線重連、事件 ID、補送起點與保留窗口。若 client 離線後仍要完整補回資料，仍要搭配 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">offline catch-up&lt;/a> 或正式儲存路徑。&lt;/p></description><content:encoded><![CDATA[<p>Server-Sent Events 的核心概念是「server 用持續的 HTTP response 對 client 單向推送事件」。它比 WebSocket 更適合單向通知、直播更新與簡單即時狀態流。 可先對照 <a href="/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">Offline Catch-up</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>SSE 位在 HTTP 之上，適合 server 主導的事件串流。它常用於通知、進度更新、系統訊號與簡化版即時 feed。 可先對照 <a href="/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">Offline Catch-up</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 SSE 的訊號是 client 只需要接收事件、不需要頻繁回傳雙向互動。活動進度條、批次作業狀態、公告 feed 與監控看板更新都可能使用 SSE。</p>
<h2 id="設計責任">設計責任</h2>
<p>SSE 設計要定義斷線重連、事件 ID、補送起點與保留窗口。若 client 離線後仍要完整補回資料，仍要搭配 <a href="/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">offline catch-up</a> 或正式儲存路徑。</p>
]]></content:encoded></item><item><title>Topic</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/topic/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/topic/</guid><description>&lt;p>Topic 的核心概念是「用主題名稱描述一類事件或訊息」。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">Producer&lt;/a> 把事件發布到 topic，&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/routing-rule/" data-link-title="Routing Rule" data-link-desc="說明訊息系統如何依規則把訊息送到不同處理路徑">routing rule&lt;/a> 或 stream 模型把事件交給對應 &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;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Topic 是事件分流的命名邊界。它讓訂單、付款、會員、通知、庫存等事件可以被不同服務訂閱，也讓團隊用事件種類思考資料流與責任範圍。&lt;/p>
&lt;p>Topic 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition&lt;/a> 的關係是：topic 是邏輯命名空間，partition 是 topic 內的物理分片。Topic 跟 &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;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> 訂閱同一個 topic，每個 group 各自消費全量事件，實現 fan-out。&lt;/p>
&lt;p>在 RabbitMQ 生態中，topic 對應 exchange + routing key 的組合；在 NATS 中 topic 對應 subject。概念相同但術語跟語意細節不同。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 topic 設計的訊號是同一個事件來源會供多個 downstream 使用。付款完成事件可以給出貨、通知、報表與風控使用；所有事件都混在同一條 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a> 時，consumer 會承擔更多過濾與相容性成本。&lt;/p>
&lt;p>Topic 命名規則影響長期治理。&lt;code>orders.payment.completed&lt;/code> 比 &lt;code>event_1&lt;/code> 更容易被搜尋跟管理。命名規則要在團隊間統一、進 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/queue-contract/" data-link-title="Queue Contract" data-link-desc="說明佇列工作在重試、確認與重複投遞上的約定">queue contract&lt;/a> 管理。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Topic 設計要定義命名規則、事件 schema、相容性策略（schema evolution）、權限控制（誰能 publish / subscribe）、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention&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> 範圍與 ownership（哪個團隊負責這個 topic）。操作面要能依 topic 查看 publish rate、&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;/p></description><content:encoded><![CDATA[<p>Topic 的核心概念是「用主題名稱描述一類事件或訊息」。<a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">Producer</a> 把事件發布到 topic，<a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> 再依照訂閱關係、<a href="/blog/backend/knowledge-cards/routing-rule/" data-link-title="Routing Rule" data-link-desc="說明訊息系統如何依規則把訊息送到不同處理路徑">routing rule</a> 或 stream 模型把事件交給對應 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Topic 是事件分流的命名邊界。它讓訂單、付款、會員、通知、庫存等事件可以被不同服務訂閱，也讓團隊用事件種類思考資料流與責任範圍。</p>
<p>Topic 跟 <a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition</a> 的關係是：topic 是邏輯命名空間，partition 是 topic 內的物理分片。Topic 跟 <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/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group</a> 訂閱同一個 topic，每個 group 各自消費全量事件，實現 fan-out。</p>
<p>在 RabbitMQ 生態中，topic 對應 exchange + routing key 的組合；在 NATS 中 topic 對應 subject。概念相同但術語跟語意細節不同。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 topic 設計的訊號是同一個事件來源會供多個 downstream 使用。付款完成事件可以給出貨、通知、報表與風控使用；所有事件都混在同一條 <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a> 時，consumer 會承擔更多過濾與相容性成本。</p>
<p>Topic 命名規則影響長期治理。<code>orders.payment.completed</code> 比 <code>event_1</code> 更容易被搜尋跟管理。命名規則要在團隊間統一、進 <a href="/blog/backend/knowledge-cards/queue-contract/" data-link-title="Queue Contract" data-link-desc="說明佇列工作在重試、確認與重複投遞上的約定">queue contract</a> 管理。</p>
<h2 id="設計責任">設計責任</h2>
<p>Topic 設計要定義命名規則、事件 schema、相容性策略（schema evolution）、權限控制（誰能 publish / subscribe）、<a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention</a> 期限、<a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook</a> 範圍與 ownership（哪個團隊負責這個 topic）。操作面要能依 topic 查看 publish rate、<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> 數量。</p>
]]></content:encoded></item><item><title>Resource Limit</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/resource-limit/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/resource-limit/</guid><description>&lt;p>Resource Limit 的核心概念是「限制一個服務實例可使用多少 CPU、memory 或其他運行資源」。它會直接影響啟動、排程、延遲、穩定性與故障型態，當成單純的部署參數會低估其影響面。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">Retention&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Resource Limit 位在 container、runtime、deployment platform 與 scheduler 之間。它決定服務在資源不足時是被 throttling、被拒絕排程，還是因記憶體超限而被終止。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">Retention&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 resource limit 的訊號是：&lt;/p>
&lt;ul>
&lt;li>多個 instance 需要共享固定主機資源&lt;/li>
&lt;li>單一服務可能因記憶體成長或 CPU 尖峰影響其他服務&lt;/li>
&lt;li>平台需要用上限保護整體節點穩定性&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>Kubernetes container limit、單機 systemd service 的 cgroup 限制、worker pool 的 CPU 上限或 memory cap，都屬於 resource limit 的問題。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要區分 request 與 limit、理解 throttling 與 OOM 的差異，並把上限調整和實際流量、cache、啟動成本與重試行為一起看。Resource Limit 的目標是保護系統穩定，而不是只追求把數字填滿。&lt;/p></description><content:encoded><![CDATA[<p>Resource Limit 的核心概念是「限制一個服務實例可使用多少 CPU、memory 或其他運行資源」。它會直接影響啟動、排程、延遲、穩定性與故障型態，當成單純的部署參數會低估其影響面。 可先對照 <a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">Retention</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Resource Limit 位在 container、runtime、deployment platform 與 scheduler 之間。它決定服務在資源不足時是被 throttling、被拒絕排程，還是因記憶體超限而被終止。 可先對照 <a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">Retention</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 resource limit 的訊號是：</p>
<ul>
<li>多個 instance 需要共享固定主機資源</li>
<li>單一服務可能因記憶體成長或 CPU 尖峰影響其他服務</li>
<li>平台需要用上限保護整體節點穩定性</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>Kubernetes container limit、單機 systemd service 的 cgroup 限制、worker pool 的 CPU 上限或 memory cap，都屬於 resource limit 的問題。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要區分 request 與 limit、理解 throttling 與 OOM 的差異，並把上限調整和實際流量、cache、啟動成本與重試行為一起看。Resource Limit 的目標是保護系統穩定，而不是只追求把數字填滿。</p>
]]></content:encoded></item><item><title>Routing Rule</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/routing-rule/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/routing-rule/</guid><description>&lt;p>Routing rule 的核心概念是「用訊息屬性決定訊息要進入哪個處理路徑」。規則可以依 topic、routing key、header、tenant、事件類型、優先級或業務狀態分派訊息。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Routing rule 是 &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/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer&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/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group&lt;/a> 或 stream &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/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">retry policy&lt;/a> 處理。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 routing rule 的訊號是同一類事件有不同處理代價。一般通知可以進入低成本 queue，高價值訂單通知可以進入優先 queue；退款事件可以交給需要更完整 &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> 的 consumer。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Routing rule 要有可測試規則、預設路徑、觀測欄位與變更流程。規則錯誤會讓訊息進錯 queue、漏處理或造成局部 &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;/p></description><content:encoded><![CDATA[<p>Routing rule 的核心概念是「用訊息屬性決定訊息要進入哪個處理路徑」。規則可以依 topic、routing key、header、tenant、事件類型、優先級或業務狀態分派訊息。 可先對照 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">Broker</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Routing rule 是 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> 內的分流邏輯。它把 <a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer</a> 的輸出轉成不同 <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a>、<a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group</a> 或 stream <a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition</a>，讓不同工作可以用不同容量、權限與 <a href="/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">retry policy</a> 處理。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 routing rule 的訊號是同一類事件有不同處理代價。一般通知可以進入低成本 queue，高價值訂單通知可以進入優先 queue；退款事件可以交給需要更完整 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a> 的 consumer。</p>
<h2 id="設計責任">設計責任</h2>
<p>Routing rule 要有可測試規則、預設路徑、觀測欄位與變更流程。規則錯誤會讓訊息進錯 queue、漏處理或造成局部 <a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">consumer lag</a>，因此每次調整都要搭配樣本驗證與回復方式。</p>
]]></content:encoded></item><item><title>Database</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/database/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/database/</guid><description>&lt;p>Database 的核心概念是「保存服務正式狀態並提供可查詢資料邊界」。它通常承擔 &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/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">transaction&lt;/a>、索引、約束、備份、權限與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-lifecycle/" data-link-title="Data Lifecycle" data-link-desc="說明資料從建立、使用、保留到刪除的責任邊界">data lifecycle&lt;/a> 責任。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Database 是產品狀態與操作證據的核心依賴。Cache、search index、read replica、event stream 與報表通常都是衍生資料；資料衝突時，團隊需要知道哪個 database 或資料表承擔正式判斷。 可先對照 &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;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 database 設計的訊號是資料要被長期保存、查詢、修改與稽核。訂單服務需要保存訂單狀態、付款紀錄、出貨狀態與取消原因；這些資料會影響客服、帳務、出貨與報表。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Database 設計要包含 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">schema migration&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/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">isolation level&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&lt;/a>、備份回復、權限、資料保留與觀測指標。操作上要能看 query latency、lock、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">replication lag&lt;/a>、connection pool 使用量與錯誤分類。&lt;/p></description><content:encoded><![CDATA[<p>Database 的核心概念是「保存服務正式狀態並提供可查詢資料邊界」。它通常承擔 <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/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">transaction</a>、索引、約束、備份、權限與 <a href="/blog/backend/knowledge-cards/data-lifecycle/" data-link-title="Data Lifecycle" data-link-desc="說明資料從建立、使用、保留到刪除的責任邊界">data lifecycle</a> 責任。</p>
<h2 id="概念位置">概念位置</h2>
<p>Database 是產品狀態與操作證據的核心依賴。Cache、search index、read replica、event stream 與報表通常都是衍生資料；資料衝突時，團隊需要知道哪個 database 或資料表承擔正式判斷。 可先對照 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">Source of Truth</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 database 設計的訊號是資料要被長期保存、查詢、修改與稽核。訂單服務需要保存訂單狀態、付款紀錄、出貨狀態與取消原因；這些資料會影響客服、帳務、出貨與報表。</p>
<h2 id="設計責任">設計責任</h2>
<p>Database 設計要包含 <a href="/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">schema migration</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/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">isolation level</a>、<a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a>、備份回復、權限、資料保留與觀測指標。操作上要能看 query latency、lock、<a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">replication lag</a>、connection pool 使用量與錯誤分類。</p>
]]></content:encoded></item><item><title>Transaction</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/transaction/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/transaction/</guid><description>&lt;p>Transaction 的核心概念是「把一組資料變更包成同一個一致性單位」。在 &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/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a> 會依 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">isolation level&lt;/a> 保護讀寫，並在 commit 或 rollback 時決定這組變更的結果。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Transaction 是正式資料一致性的工具。它適合保護同一個 database 內的狀態變更，例如建立訂單、扣庫存、寫入付款紀錄；跨服務通知、外部 API 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker&lt;/a> publish 則需要 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">data reconciliation&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 transaction 的訊號是半完成狀態會造成產品錯誤。付款紀錄建立成功但訂單仍停在未付款，客服、倉儲與帳務會看到衝突資料；transaction 可以把這些同庫變更合併成同一個成功條件。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Transaction 設計要控制範圍、時間、鎖、&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/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout&lt;/a> 與錯誤分類。長 transaction 會增加 lock 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&lt;/a> 壓力，因此應把外部呼叫與長時間工作移出交易範圍。&lt;/p></description><content:encoded><![CDATA[<p>Transaction 的核心概念是「把一組資料變更包成同一個一致性單位」。在 <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/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a> 會依 <a href="/blog/backend/knowledge-cards/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">isolation level</a> 保護讀寫，並在 commit 或 rollback 時決定這組變更的結果。</p>
<h2 id="概念位置">概念位置</h2>
<p>Transaction 是正式資料一致性的工具。它適合保護同一個 database 內的狀態變更，例如建立訂單、扣庫存、寫入付款紀錄；跨服務通知、外部 API 與 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> publish 則需要 <a href="/blog/backend/knowledge-cards/outbox-pattern/" data-link-title="Outbox Pattern" data-link-desc="說明資料庫狀態變更與事件發布如何透過 outbox 維持一致">outbox pattern</a>、補償或 <a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">data reconciliation</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 transaction 的訊號是半完成狀態會造成產品錯誤。付款紀錄建立成功但訂單仍停在未付款，客服、倉儲與帳務會看到衝突資料；transaction 可以把這些同庫變更合併成同一個成功條件。</p>
<h2 id="設計責任">設計責任</h2>
<p>Transaction 設計要控制範圍、時間、鎖、<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/timeout/" data-link-title="Timeout" data-link-desc="說明等待外部操作的時間上限如何保護資源與使用者體驗">timeout</a> 與錯誤分類。長 transaction 會增加 lock 與 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a> 壓力，因此應把外部呼叫與長時間工作移出交易範圍。</p>
]]></content:encoded></item><item><title>Migration</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/migration/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/migration/</guid><description>&lt;p>Migration 的核心概念是「把系統從舊狀態移到新狀態的受控流程」。它可以是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">schema migration&lt;/a>、資料 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">backfill&lt;/a>、服務拆分、平台切換、read path 切換或事件模型改版。常見做法之一是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Migration 是 release、資料一致性與操作風險的交界。它通常需要同時考慮相容性、觀測、回復、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">cutover / switchover&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">fallback plan&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/correctness-check/" data-link-title="Correctness Check" data-link-desc="說明遷移或重構期間如何驗證新舊結果是否符合規則">correctness check&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 migration 設計的訊號是新舊路徑會並存一段時間。電商把搜尋從舊索引切到新索引時，需要 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/shadow-read/" data-link-title="Shadow Read" data-link-desc="說明正式讀取仍走舊路徑時如何暗中讀新路徑比對結果">shadow read&lt;/a> 比對結果、backfill 既有商品、觀察錯誤率，最後再切正式流量。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Migration 要定義階段、擁有者、資料範圍、驗證方式、回復條件與完成標準。高風險 migration 應把資料變更、application release 與流量切換拆成可觀察、可停止的步驟，並在上線前安排 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Migration 的核心概念是「把系統從舊狀態移到新狀態的受控流程」。它可以是 <a href="/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">schema migration</a>、資料 <a href="/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">backfill</a>、服務拆分、平台切換、read path 切換或事件模型改版。常見做法之一是 <a href="/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Migration 是 release、資料一致性與操作風險的交界。它通常需要同時考慮相容性、觀測、回復、<a href="/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">cutover / switchover</a>、<a href="/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">fallback plan</a> 與 <a href="/blog/backend/knowledge-cards/correctness-check/" data-link-title="Correctness Check" data-link-desc="說明遷移或重構期間如何驗證新舊結果是否符合規則">correctness check</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 migration 設計的訊號是新舊路徑會並存一段時間。電商把搜尋從舊索引切到新索引時，需要 <a href="/blog/backend/knowledge-cards/shadow-read/" data-link-title="Shadow Read" data-link-desc="說明正式讀取仍走舊路徑時如何暗中讀新路徑比對結果">shadow read</a> 比對結果、backfill 既有商品、觀察錯誤率，最後再切正式流量。</p>
<h2 id="設計責任">設計責任</h2>
<p>Migration 要定義階段、擁有者、資料範圍、驗證方式、回復條件與完成標準。高風險 migration 應把資料變更、application release 與流量切換拆成可觀察、可停止的步驟，並在上線前安排 <a href="/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal</a> 與 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">Migration Gate</a>。</p>
]]></content:encoded></item><item><title>Expand / Contract</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/expand-contract/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/expand-contract/</guid><description>&lt;p>Expand / Contract 的核心概念是「先把新結構或新路徑加進去，確認相容後，再移除舊結構或舊路徑」。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/exponential-backoff/" data-link-title="Exponential Backoff" data-link-desc="說明重試間隔如何逐步拉長以降低下游壓力">Exponential Backoff&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Expand / Contract 位在 schema migration、online migration、deployment 與 release gate 之間。它是降低變更風險的遷移順序，不是單一工具。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/exponential-backoff/" data-link-title="Exponential Backoff" data-link-desc="說明重試間隔如何逐步拉長以降低下游壓力">Exponential Backoff&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 expand / contract 的訊號是：&lt;/p>
&lt;ul>
&lt;li>舊版本與新版本會同時存在&lt;/li>
&lt;li>新功能需要先讓舊程式不壞掉&lt;/li>
&lt;li>移除舊欄位或舊路徑前，必須先讓新版本穩定接上&lt;/li>
&lt;li>migration 不能一次做完&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>新增欄位時先擴表、補預設值、讓新舊版本都能讀寫，再等舊版本完全退出後移除舊欄位；換搜尋索引時先讓新寫入同步到兩邊，等驗證完成後再收斂舊索引。這些都屬於 expand / contract。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Expand / Contract 要定義擴張階段、相容條件、收斂條件、驗證方式與回復方式。它的重點是讓每一步都保有回頭路。&lt;/p></description><content:encoded><![CDATA[<p>Expand / Contract 的核心概念是「先把新結構或新路徑加進去，確認相容後，再移除舊結構或舊路徑」。 可先對照 <a href="/blog/backend/knowledge-cards/exponential-backoff/" data-link-title="Exponential Backoff" data-link-desc="說明重試間隔如何逐步拉長以降低下游壓力">Exponential Backoff</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Expand / Contract 位在 schema migration、online migration、deployment 與 release gate 之間。它是降低變更風險的遷移順序，不是單一工具。 可先對照 <a href="/blog/backend/knowledge-cards/exponential-backoff/" data-link-title="Exponential Backoff" data-link-desc="說明重試間隔如何逐步拉長以降低下游壓力">Exponential Backoff</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 expand / contract 的訊號是：</p>
<ul>
<li>舊版本與新版本會同時存在</li>
<li>新功能需要先讓舊程式不壞掉</li>
<li>移除舊欄位或舊路徑前，必須先讓新版本穩定接上</li>
<li>migration 不能一次做完</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>新增欄位時先擴表、補預設值、讓新舊版本都能讀寫，再等舊版本完全退出後移除舊欄位；換搜尋索引時先讓新寫入同步到兩邊，等驗證完成後再收斂舊索引。這些都屬於 expand / contract。</p>
<h2 id="設計責任">設計責任</h2>
<p>Expand / Contract 要定義擴張階段、相容條件、收斂條件、驗證方式與回復方式。它的重點是讓每一步都保有回頭路。</p>
]]></content:encoded></item><item><title>Log</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/log/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/log/</guid><description>&lt;p>Log 的核心概念是「記錄單一事件發生時的上下文」。它描述某個時間點發生了什麼、由誰觸發、處理結果如何，以及需要哪些欄位才能和 request、&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/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue&lt;/a> 或資料變更關聯。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Log 是可觀測性的事件明細層。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">Metrics&lt;/a> 負責趨勢，trace 負責跨服務路徑，log 負責提供單一事件的判斷證據；&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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 log 設計的訊號是事故時需要回答「哪一筆資料在哪一步失敗」。Checkout 失敗時，團隊需要用 &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>、order id、payment id 與錯誤分類找出同一流程的所有紀錄。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Log 設計要定義 log level、事件名稱、欄位、錯誤分類、敏感資料遮罩、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention&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;/p></description><content:encoded><![CDATA[<p>Log 的核心概念是「記錄單一事件發生時的上下文」。它描述某個時間點發生了什麼、由誰觸發、處理結果如何，以及需要哪些欄位才能和 request、<a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a>、<a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a> 或資料變更關聯。</p>
<h2 id="概念位置">概念位置</h2>
<p>Log 是可觀測性的事件明細層。<a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">Metrics</a> 負責趨勢，trace 負責跨服務路徑，log 負責提供單一事件的判斷證據；<a href="/blog/backend/knowledge-cards/log-schema/" data-link-title="Log Schema" data-link-desc="說明結構化 log 欄位如何支援搜尋、關聯與事故排查">log schema</a> 則讓這些紀錄可以被穩定搜尋與聚合。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 log 設計的訊號是事故時需要回答「哪一筆資料在哪一步失敗」。Checkout 失敗時，團隊需要用 <a href="/blog/backend/knowledge-cards/request-id/" data-link-title="Request ID" data-link-desc="說明單次 request 的識別碼如何支援 log 搜尋與問題定位">request id</a>、order id、payment id 與錯誤分類找出同一流程的所有紀錄。</p>
<h2 id="設計責任">設計責任</h2>
<p>Log 設計要定義 log level、事件名稱、欄位、錯誤分類、敏感資料遮罩、<a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention</a> 與查詢成本。高風險操作應另外寫入 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a>，保留責任證據。</p>
]]></content:encoded></item><item><title>Reliability Boundary</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/reliability-boundary/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/reliability-boundary/</guid><description>&lt;p>Reliability boundary 的核心概念是「系統在哪一段路徑內承諾不遺失、可重試、可追蹤」。同一個功能中，in-process channel、&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;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> 與 database transaction 的可靠性強度不同，必須先界定邊界再談工具。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>可靠性邊界通常出現在 request 結束點、跨 process 傳遞點、跨服務傳遞點與外部第三方呼叫點。邊界內可依靠 transaction、持久化與 ack 機制；邊界外需要 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">offline catch-up&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency&lt;/a> 補償。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要明確 reliability boundary 的訊號是「同一筆事件在某些路徑可追蹤，在某些路徑不可追蹤」。例如聊天推播可接受短暫遺失，但付款通知需要補送；這代表兩者的可靠性邊界不同。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義哪類事件屬於 &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;/p></description><content:encoded><![CDATA[<p>Reliability boundary 的核心概念是「系統在哪一段路徑內承諾不遺失、可重試、可追蹤」。同一個功能中，in-process channel、<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/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue</a> 與 database transaction 的可靠性強度不同，必須先界定邊界再談工具。</p>
<h2 id="概念位置">概念位置</h2>
<p>可靠性邊界通常出現在 request 結束點、跨 process 傳遞點、跨服務傳遞點與外部第三方呼叫點。邊界內可依靠 transaction、持久化與 ack 機制；邊界外需要 <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/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook</a> 與 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 補償。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要明確 reliability boundary 的訊號是「同一筆事件在某些路徑可追蹤，在某些路徑不可追蹤」。例如聊天推播可接受短暫遺失，但付款通知需要補送；這代表兩者的可靠性邊界不同。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義哪類事件屬於 <a href="/blog/backend/knowledge-cards/strong-reliability/" data-link-title="Strong Reliability" data-link-desc="說明高可靠事件路徑需要的保存、重試、去重與回復責任">strong reliability</a>、哪類事件可用低成本即時通道，並對每類事件提供對應的回復與驗證流程。</p>
]]></content:encoded></item><item><title>Trace</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/trace/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/trace/</guid><description>&lt;p>Trace 的核心概念是「把一次 request 或工作流程拆成可關聯的多段執行紀錄」。&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/span/" data-link-title="Span" data-link-desc="說明 trace 中一段工作如何記錄耗時、狀態與關聯">span&lt;/a> 記錄每一段工作，&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/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Trace 是跨服務診斷的路徑層，跟 &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/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics&lt;/a>（趨勢層）互補。Log 回答「某個服務發生了什麼」；metrics 回答「服務的健康趨勢」；trace 回答「一次 request 跨服務時，時間花在哪、錯誤發生在哪一段」。&lt;/p>
&lt;p>Trace 在 waterfall view 中呈現為時間軸上的巢狀條狀圖，root span 在最上面、child span 依序往下。診斷價值是一眼看出延遲瓶頸 — checkout 總延遲 800ms 中 payment span 佔 600ms，問題定位立刻縮小範圍。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 trace 的訊號是單一服務的 log 只呈現局部。Checkout 變慢時，trace 可以顯示時間主要花在庫存查詢、付款 API、database lock 或通知 worker。跨服務錯誤（upstream 回 500 但不知道是哪個 downstream 引起的）也依賴 trace 定位。&lt;/p>
&lt;p>Trace 聚合後可以自動生成 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/service-topology/" data-link-title="4.13 Service Topology 與 Dependency Map" data-link-desc="把跨服務依賴從文件變成自動發現的觀測訊號">service topology&lt;/a> — 哪些服務在呼叫哪些服務、call 頻率、延遲分布、錯誤率。這個 graph 反映實際流量而非設計文件。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Trace 設計要處理 &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> 傳遞（HTTP header、queue message header、thread context）、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="說明觀測資料如何抽樣以控制成本並保留診斷能力">sampling&lt;/a> 策略（head / tail / adaptive）、span 命名慣例、敏感資料 redaction、跨語言 SDK 相容性與 log correlation（trace id 寫進 log 欄位）。&lt;/p>
&lt;p>高流量服務需要控制採樣成本，同時保留錯誤與高延遲樣本。Sampling 策略的完整討論見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/cardinality-cost-governance/#sampling-%e7%ad%96%e7%95%a5" data-link-title="4.7 Cardinality 治理與成本邊界" data-link-desc="把 metric / log / trace 的 cardinality 與成本作為平台一級治理議題">4.7&lt;/a>。Context propagation 在不同邊界（HTTP / queue / thread pool / background job）的斷鏈風險與修復見 &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">4.3&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Trace 的核心概念是「把一次 request 或工作流程拆成可關聯的多段執行紀錄」。<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/span/" data-link-title="Span" data-link-desc="說明 trace 中一段工作如何記錄耗時、狀態與關聯">span</a> 記錄每一段工作，<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/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a> 與 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> 能回到同一條流程。</p>
<h2 id="概念位置">概念位置</h2>
<p>Trace 是跨服務診斷的路徑層，跟 <a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a>（事件層）和 <a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics</a>（趨勢層）互補。Log 回答「某個服務發生了什麼」；metrics 回答「服務的健康趨勢」；trace 回答「一次 request 跨服務時，時間花在哪、錯誤發生在哪一段」。</p>
<p>Trace 在 waterfall view 中呈現為時間軸上的巢狀條狀圖，root span 在最上面、child span 依序往下。診斷價值是一眼看出延遲瓶頸 — checkout 總延遲 800ms 中 payment span 佔 600ms，問題定位立刻縮小範圍。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 trace 的訊號是單一服務的 log 只呈現局部。Checkout 變慢時，trace 可以顯示時間主要花在庫存查詢、付款 API、database lock 或通知 worker。跨服務錯誤（upstream 回 500 但不知道是哪個 downstream 引起的）也依賴 trace 定位。</p>
<p>Trace 聚合後可以自動生成 <a href="/blog/backend/04-observability/service-topology/" data-link-title="4.13 Service Topology 與 Dependency Map" data-link-desc="把跨服務依賴從文件變成自動發現的觀測訊號">service topology</a> — 哪些服務在呼叫哪些服務、call 頻率、延遲分布、錯誤率。這個 graph 反映實際流量而非設計文件。</p>
<h2 id="設計責任">設計責任</h2>
<p>Trace 設計要處理 <a href="/blog/backend/knowledge-cards/trace-context/" data-link-title="Trace Context" data-link-desc="說明跨服務 request 如何用 trace context 串起路徑與耗時">trace context</a> 傳遞（HTTP header、queue message header、thread context）、<a href="/blog/backend/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="說明觀測資料如何抽樣以控制成本並保留診斷能力">sampling</a> 策略（head / tail / adaptive）、span 命名慣例、敏感資料 redaction、跨語言 SDK 相容性與 log correlation（trace id 寫進 log 欄位）。</p>
<p>高流量服務需要控制採樣成本，同時保留錯誤與高延遲樣本。Sampling 策略的完整討論見 <a href="/blog/backend/04-observability/cardinality-cost-governance/#sampling-%e7%ad%96%e7%95%a5" data-link-title="4.7 Cardinality 治理與成本邊界" data-link-desc="把 metric / log / trace 的 cardinality 與成本作為平台一級治理議題">4.7</a>。Context propagation 在不同邊界（HTTP / queue / thread pool / background job）的斷鏈風險與修復見 <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>。</p>
]]></content:encoded></item><item><title>Migration Gate</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/</guid><description>&lt;p>Migration Gate 的核心概念是「在遷移流程中，用明確條件決定能不能進下一階段或正式切換」。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">Migration&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Migration Gate 位在 migration、backfill、correctness check、data completeness 與 cutover 之間。它是遷移內部的階段控制點，不等於一般的 release gate。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">Migration&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 migration gate 的訊號是：&lt;/p>
&lt;ul>
&lt;li>新舊狀態會並存一段時間&lt;/li>
&lt;li>進下一階段前要先確認資料已補齊或結果已比對&lt;/li>
&lt;li>切換前必須先確認副作用可控&lt;/li>
&lt;li>遷移失敗時要能停在安全階段&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>資料搬遷到新 table 後，先確認 row count、關聯完整性與抽樣結果，再決定能否進入 cutover；搜尋索引重建完成後，先通過 correctness check 與 shadow read，再把讀取流量切過去。這些決定都屬於 migration gate。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Migration Gate 要定義每一階段的通過條件、資料證據、擁有者與停止條件。它的目標是讓遷移不只是「做完」，而是「安全地前進或回頭」。&lt;/p></description><content:encoded><![CDATA[<p>Migration Gate 的核心概念是「在遷移流程中，用明確條件決定能不能進下一階段或正式切換」。 可先對照 <a href="/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">Migration</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Migration Gate 位在 migration、backfill、correctness check、data completeness 與 cutover 之間。它是遷移內部的階段控制點，不等於一般的 release gate。 可先對照 <a href="/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">Migration</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 migration gate 的訊號是：</p>
<ul>
<li>新舊狀態會並存一段時間</li>
<li>進下一階段前要先確認資料已補齊或結果已比對</li>
<li>切換前必須先確認副作用可控</li>
<li>遷移失敗時要能停在安全階段</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>資料搬遷到新 table 後，先確認 row count、關聯完整性與抽樣結果，再決定能否進入 cutover；搜尋索引重建完成後，先通過 correctness check 與 shadow read，再把讀取流量切過去。這些決定都屬於 migration gate。</p>
<h2 id="設計責任">設計責任</h2>
<p>Migration Gate 要定義每一階段的通過條件、資料證據、擁有者與停止條件。它的目標是讓遷移不只是「做完」，而是「安全地前進或回頭」。</p>
]]></content:encoded></item><item><title>Pub/Sub</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/pub-sub/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/pub-sub/</guid><description>&lt;p>Pub/Sub 的核心概念是「publisher 把事件送到主題，訂閱者依主題即時接收」。它擅長 &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>Pub/Sub 常用在即時通知、presence 變更、前端狀態廣播與跨節點訊號同步。它和 &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> 的差異在於：pub/sub 偏即時分發，durable queue 偏可靠處理。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>當需求是「在線訂閱者盡快收到訊息」時，pub/sub 是常見候選。例如聊天室 typing indicator、任務進度更新、dashboard 即時刷新。若訂閱者離線後仍要補送，通常需要搭配 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">offline catch-up&lt;/a> 或 durable storage。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要明確訊息是否可遺失、是否需要持久化、是否需要重播。若需求轉向高可靠，應把關鍵事件切到 &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;/p></description><content:encoded><![CDATA[<p>Pub/Sub 的核心概念是「publisher 把事件送到主題，訂閱者依主題即時接收」。它擅長 <a href="/blog/backend/knowledge-cards/fan-out/" data-link-title="Fan-out" data-link-desc="說明單一事件同時分發給多個下游的訊息拓撲">fan-out</a> 與低延遲通知，但通常不承諾完整歷史保存或離線補送。</p>
<h2 id="概念位置">概念位置</h2>
<p>Pub/Sub 常用在即時通知、presence 變更、前端狀態廣播與跨節點訊號同步。它和 <a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue</a> 的差異在於：pub/sub 偏即時分發，durable queue 偏可靠處理。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>當需求是「在線訂閱者盡快收到訊息」時，pub/sub 是常見候選。例如聊天室 typing indicator、任務進度更新、dashboard 即時刷新。若訂閱者離線後仍要補送，通常需要搭配 <a href="/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">offline catch-up</a> 或 durable storage。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要明確訊息是否可遺失、是否需要持久化、是否需要重播。若需求轉向高可靠，應把關鍵事件切到 <a href="/blog/backend/knowledge-cards/strong-reliability/" data-link-title="Strong Reliability" data-link-desc="說明高可靠事件路徑需要的保存、重試、去重與回復責任">strong reliability</a> 路徑。</p>
]]></content:encoded></item><item><title>Dashboard</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/</guid><description>&lt;p>Dashboard 的核心概念是「把多個觀測訊號組成可判讀的服務狀態畫面」。它讓團隊用同一個視角查看 &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>、latency、error rate、traffic、saturation、&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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Dashboard 是告警與排障之間的判讀層。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">Alert&lt;/a> 告訴團隊需要注意，dashboard 幫團隊判斷影響範圍、變化趨勢與可能原因，&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>Dashboard 分層服務不同使用者：service overview 給 &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> 工程師、debug dashboard 給事故中的深入診斷、capacity dashboard 給容量規劃。把所有資訊擠在同一個 dashboard 會讓每個角色都找不到自己要的。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 dashboard 的訊號是事故中需要快速回答「影響多大、從何時開始、哪個依賴異常」。Dashboard 也是日常巡檢的入口 — on-call 工程師每天先看 service overview 確認服務健康，再處理 alert queue。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Dashboard 設計要服務具體決策。每個面板應對應一個可回答的問題（「服務現在健康嗎」「延遲瓶頸在哪」「容量還夠嗎」）。高 cardinality、缺少單位或只呈現低層資源的圖表會增加判讀成本而非降低。&lt;/p>
&lt;p>Dashboard panel 的查詢效能影響使用體驗 — 長時間趨勢 panel 應讀 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup&lt;/a> 資料，避免每次刷新都掃描 raw series。Dashboard / alert 的完整設計見 &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 與容量趨勢">4.4&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Dashboard 的核心概念是「把多個觀測訊號組成可判讀的服務狀態畫面」。它讓團隊用同一個視角查看 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI / SLO</a>、latency、error rate、traffic、saturation、<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> 與下游依賴狀態。</p>
<h2 id="概念位置">概念位置</h2>
<p>Dashboard 是告警與排障之間的判讀層。<a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">Alert</a> 告訴團隊需要注意，dashboard 幫團隊判斷影響範圍、變化趨勢與可能原因，<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 則把判讀結果轉成處理步驟。</p>
<p>Dashboard 分層服務不同使用者：service overview 給 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a> 工程師、debug dashboard 給事故中的深入診斷、capacity dashboard 給容量規劃。把所有資訊擠在同一個 dashboard 會讓每個角色都找不到自己要的。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 dashboard 的訊號是事故中需要快速回答「影響多大、從何時開始、哪個依賴異常」。Dashboard 也是日常巡檢的入口 — on-call 工程師每天先看 service overview 確認服務健康，再處理 alert queue。</p>
<h2 id="設計責任">設計責任</h2>
<p>Dashboard 設計要服務具體決策。每個面板應對應一個可回答的問題（「服務現在健康嗎」「延遲瓶頸在哪」「容量還夠嗎」）。高 cardinality、缺少單位或只呈現低層資源的圖表會增加判讀成本而非降低。</p>
<p>Dashboard panel 的查詢效能影響使用體驗 — 長時間趨勢 panel 應讀 <a href="/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule</a> 或 <a href="/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup</a> 資料，避免每次刷新都掃描 raw series。Dashboard / alert 的完整設計見 <a href="/blog/backend/04-observability/dashboard-alert/" data-link-title="4.4 dashboard 與 alert 設計" data-link-desc="讓 dashboard 與 alert 對應 runbook 與容量趨勢">4.4</a>。</p>
]]></content:encoded></item><item><title>Fan-out</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/fan-out/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/fan-out/</guid><description>&lt;p>Fan-out 的核心概念是「一個事件被多個訂閱者各自獨立處理」。它讓單一 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer&lt;/a> 發布一次事件，多個下游各自消費、各自處理、各自管理進度跟錯誤。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Fan-out 常搭配 &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;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/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group&lt;/a> 實作。在 Kafka 中，多個 consumer group 訂閱同一個 topic 就是 fan-out — 每個 group 各自從 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">offset&lt;/a> 0 開始消費。在 RabbitMQ 中，fanout exchange 把訊息複製到所有綁定的 queue。在 GCP Pub/Sub 中，多個 subscription 訂閱同一個 topic。&lt;/p>
&lt;p>Fan-out 跟 fan-in（多個來源合併成一個流）是相反的拓撲。兩者可以組合成事件處理管線。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>&lt;code>order.paid&lt;/code> 事件同時觸發出貨準備（物流服務）、交易通知（通知服務）、營收紀錄（報表服務）與風控評估（風控服務）。Producer 不需要知道有哪些 consumer — 加減 consumer 不影響 producer 的程式碼。&lt;/p>
&lt;p>Fan-out 降低了 producer 跟 consumer 之間的耦合，但擴大了排障範圍 — 一筆事件的處理結果散落在多個 consumer，需要用 &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> 或 correlation id 串連。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 fan-out 時要為每個訂閱者定義可靠性等級跟回復策略。通知服務短暫失敗可以 retry；報表服務落後可以批次追補；但出貨服務的失敗可能需要人工介入。把所有下游綁成同一個失敗域（一個 consumer 卡住就全部暫停）會讓 fan-out 的解耦價值消失。每個 consumer group 應該獨立管理 &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 runbook&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Fan-out 的核心概念是「一個事件被多個訂閱者各自獨立處理」。它讓單一 <a href="/blog/backend/knowledge-cards/producer/" data-link-title="Producer" data-link-desc="說明 producer 如何把工作、事件或資料送入後續處理路徑">producer</a> 發布一次事件，多個下游各自消費、各自處理、各自管理進度跟錯誤。</p>
<h2 id="概念位置">概念位置</h2>
<p>Fan-out 常搭配 <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/topic/" data-link-title="Topic" data-link-desc="說明 topic 如何把事件依主題分流給不同訂閱者">topic</a> 跟 <a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group</a> 實作。在 Kafka 中，多個 consumer group 訂閱同一個 topic 就是 fan-out — 每個 group 各自從 <a href="/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">offset</a> 0 開始消費。在 RabbitMQ 中，fanout exchange 把訊息複製到所有綁定的 queue。在 GCP Pub/Sub 中，多個 subscription 訂閱同一個 topic。</p>
<p>Fan-out 跟 fan-in（多個來源合併成一個流）是相反的拓撲。兩者可以組合成事件處理管線。</p>
<h2 id="使用情境">使用情境</h2>
<p><code>order.paid</code> 事件同時觸發出貨準備（物流服務）、交易通知（通知服務）、營收紀錄（報表服務）與風控評估（風控服務）。Producer 不需要知道有哪些 consumer — 加減 consumer 不影響 producer 的程式碼。</p>
<p>Fan-out 降低了 producer 跟 consumer 之間的耦合，但擴大了排障範圍 — 一筆事件的處理結果散落在多個 consumer，需要用 <a href="/blog/backend/knowledge-cards/trace-context/" data-link-title="Trace Context" data-link-desc="說明跨服務 request 如何用 trace context 串起路徑與耗時">trace context</a> 或 correlation id 串連。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 fan-out 時要為每個訂閱者定義可靠性等級跟回復策略。通知服務短暫失敗可以 retry；報表服務落後可以批次追補；但出貨服務的失敗可能需要人工介入。把所有下游綁成同一個失敗域（一個 consumer 卡住就全部暫停）會讓 fan-out 的解耦價值消失。每個 consumer group 應該獨立管理 <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 runbook</a>。</p>
]]></content:encoded></item><item><title>Validation Query</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/validation-query/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/validation-query/</guid><description>&lt;p>Validation query 的核心概念是「用可重跑查詢證明資料語意是否符合遷移規則」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/correctness-check/" data-link-title="Correctness Check" data-link-desc="說明遷移或重構期間如何驗證新舊結果是否符合規則">correctness check&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">backfill&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate&lt;/a>，讓資料變更不只靠 job log 或人工抽樣判斷。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Validation query 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">schema migration&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">data reconciliation&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a> 之間。Correctness check 定義要驗什麼，validation query 則把規則落成可查、可保存、可交接的證據。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 validation query 的訊號是：&lt;/p>
&lt;ul>
&lt;li>新舊欄位或新舊資料模型會並存一段時間&lt;/li>
&lt;li>backfill job 顯示完成，但仍需要證明資料語意正確&lt;/li>
&lt;li>cutover 前要知道 mismatch 集中在哪些資料範圍&lt;/li>
&lt;li>事故修復後要留下可回放的資料證據&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>訂單服務把 &lt;code>status&lt;/code> 裡的付款語意拆到 &lt;code>payment_state&lt;/code> 時，validation query 可以比對每批訂單的新舊語意、缺值筆數、mismatch sample 與 replication lag 對位。這些結果會進入 release gate，而不是只停在 migration job 的成功訊息。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Validation query 要保留 query version、time range、資料範圍、mismatch 分類與 owner。它的目標是支援 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback window&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a> 判讀，讓團隊能知道下一步是繼續、暫停、回退讀取，還是做資料修補。&lt;/p></description><content:encoded><![CDATA[<p>Validation query 的核心概念是「用可重跑查詢證明資料語意是否符合遷移規則」。它連接 <a href="/blog/backend/knowledge-cards/correctness-check/" data-link-title="Correctness Check" data-link-desc="說明遷移或重構期間如何驗證新舊結果是否符合規則">correctness check</a>、<a href="/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">backfill</a> 與 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate</a>，讓資料變更不只靠 job log 或人工抽樣判斷。</p>
<h2 id="概念位置">概念位置</h2>
<p>Validation query 位在 <a href="/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">schema migration</a>、<a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">data reconciliation</a> 與 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a> 之間。Correctness check 定義要驗什麼，validation query 則把規則落成可查、可保存、可交接的證據。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 validation query 的訊號是：</p>
<ul>
<li>新舊欄位或新舊資料模型會並存一段時間</li>
<li>backfill job 顯示完成，但仍需要證明資料語意正確</li>
<li>cutover 前要知道 mismatch 集中在哪些資料範圍</li>
<li>事故修復後要留下可回放的資料證據</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>訂單服務把 <code>status</code> 裡的付款語意拆到 <code>payment_state</code> 時，validation query 可以比對每批訂單的新舊語意、缺值筆數、mismatch sample 與 replication lag 對位。這些結果會進入 release gate，而不是只停在 migration job 的成功訊息。</p>
<h2 id="設計責任">設計責任</h2>
<p>Validation query 要保留 query version、time range、資料範圍、mismatch 分類與 owner。它的目標是支援 <a href="/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback window</a> 與 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a> 判讀，讓團隊能知道下一步是繼續、暫停、回退讀取，還是做資料修補。</p>
]]></content:encoded></item><item><title>Alert</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/alert/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/alert/</guid><description>&lt;p>Alert 的核心概念是「把需要人或自動流程處理的服務症狀轉成通知」。好的 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;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;p>Alert 是可觀測性進入操作流程的入口。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/symptom-based-alert/" data-link-title="Symptom-Based Alert" data-link-desc="說明告警應優先偵測使用者可感知症狀">Symptom-based alert&lt;/a> 優先偵測使用者可感知結果（error rate、latency p99）；cause-based alert 偵測內部原因（CPU、&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/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&lt;/a>）。Symptom-based 用於 page on-call、cause-based 用於 warning 級通知。&lt;/p>
&lt;p>Alert 觸發後由 &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;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;p>系統需要 alert 設計的訊號是服務異常需要在使用者大量回報前被發現跟處理。付款成功率下降、API availability 低於 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLO&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 如何隔離多次處理失敗的訊息">DLQ&lt;/a> 快速增加，都應觸發可行動通知。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Alert 設計要定義門檻、持續時間（&lt;code>for&lt;/code> duration）、severity、通知對象、抑制規則、runbook link 與回復條件。每個 alert rule 帶 owner metadata — 沒有 owner 的 alert 會在服務演進後退化成 noise 來源，形成 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">alert fatigue&lt;/a>。&lt;/p>
&lt;p>SLO-based alerting 用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">burn rate&lt;/a> 取代固定閾值，自動適應流量變化。完整的 alert 設計見 &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 與容量趨勢">4.4&lt;/a>、SLO-based alerting 見 &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.6&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Alert 的核心概念是「把需要人或自動流程處理的服務症狀轉成通知」。好的 alert 連到產品影響、判斷條件、<a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a>、<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 與升級流程。</p>
<h2 id="概念位置">概念位置</h2>
<p>Alert 是可觀測性進入操作流程的入口。<a href="/blog/backend/knowledge-cards/symptom-based-alert/" data-link-title="Symptom-Based Alert" data-link-desc="說明告警應優先偵測使用者可感知症狀">Symptom-based alert</a> 優先偵測使用者可感知結果（error rate、latency p99）；cause-based alert 偵測內部原因（CPU、<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/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a>）。Symptom-based 用於 page on-call、cause-based 用於 warning 級通知。</p>
<p>Alert 觸發後由 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a> 工程師承接，按 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 的步驟診斷跟處理。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 alert 設計的訊號是服務異常需要在使用者大量回報前被發現跟處理。付款成功率下降、API availability 低於 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLO</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 如何隔離多次處理失敗的訊息">DLQ</a> 快速增加，都應觸發可行動通知。</p>
<h2 id="設計責任">設計責任</h2>
<p>Alert 設計要定義門檻、持續時間（<code>for</code> duration）、severity、通知對象、抑制規則、runbook link 與回復條件。每個 alert rule 帶 owner metadata — 沒有 owner 的 alert 會在服務演進後退化成 noise 來源，形成 <a href="/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">alert fatigue</a>。</p>
<p>SLO-based alerting 用 <a href="/blog/backend/knowledge-cards/burn-rate/" data-link-title="Burn Rate" data-link-desc="說明 error budget 消耗速度如何支援告警與事故分級">burn rate</a> 取代固定閾值，自動適應流量變化。完整的 alert 設計見 <a href="/blog/backend/04-observability/dashboard-alert/" data-link-title="4.4 dashboard 與 alert 設計" data-link-desc="讓 dashboard 與 alert 對應 runbook 與容量趨勢">4.4</a>、SLO-based alerting 見 <a href="/blog/backend/04-observability/sli-slo-signal/" data-link-title="4.6 SLI 量測與 SLO 訊號設計" data-link-desc="把可靠性目標的訊號從 metric 端設計好、餵給 6.6 SLO 政策">4.6</a>。</p>
]]></content:encoded></item><item><title>Read Compatibility</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/read-compatibility/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/read-compatibility/</guid><description>&lt;p>Read compatibility 的核心概念是「讀取路徑在過渡期同時理解新舊資料語意」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">schema migration&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">fallback&lt;/a>，讓新欄位或新資料模型可以先進入 production，再逐步切換讀取權。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Read compatibility 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">dual write&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">cutover / switchover&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate&lt;/a> 之間。雙寫處理寫入一致性，read compatibility 處理讀取方如何在缺值、延遲回填或版本混跑時仍能給出一致判讀。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 read compatibility 的訊號是：&lt;/p>
&lt;ul>
&lt;li>新欄位已新增，但歷史資料尚未全部 backfill&lt;/li>
&lt;li>新舊程式版本會同時服務流量&lt;/li>
&lt;li>rollback 後舊版本仍需要讀懂 production 資料&lt;/li>
&lt;li>內部後台、對帳或報表的切換節奏不同於使用者可見路徑&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>訂單服務新增 &lt;code>payment_state&lt;/code> 後，讀取時可先看新欄位，缺值時回到舊 &lt;code>status&lt;/code> 的付款語意。客服後台可以先用這條相容讀取路徑驗證資料，再逐步讓使用者可見查詢改用新欄位。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Read compatibility 要定義讀取優先順序、fallback read 條件、資料新鮮度限制與停止條件。它要搭配 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/validation-query/" data-link-title="Validation Query" data-link-desc="說明遷移、回填與修復期間如何用查詢證明資料語意是否一致">validation query&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback strategy&lt;/a>，避免 cutover 後才發現舊版本或長尾讀取路徑無法判讀資料。&lt;/p></description><content:encoded><![CDATA[<p>Read compatibility 的核心概念是「讀取路徑在過渡期同時理解新舊資料語意」。它連接 <a href="/blog/backend/knowledge-cards/expand-contract/" data-link-title="Expand / Contract" data-link-desc="說明先擴充相容面、再收斂舊路徑的遷移做法">Expand / Contract</a>、<a href="/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">schema migration</a> 與 <a href="/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">fallback</a>，讓新欄位或新資料模型可以先進入 production，再逐步切換讀取權。</p>
<h2 id="概念位置">概念位置</h2>
<p>Read compatibility 位在 <a href="/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">dual write</a>、<a href="/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">cutover / switchover</a> 與 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate</a> 之間。雙寫處理寫入一致性，read compatibility 處理讀取方如何在缺值、延遲回填或版本混跑時仍能給出一致判讀。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 read compatibility 的訊號是：</p>
<ul>
<li>新欄位已新增，但歷史資料尚未全部 backfill</li>
<li>新舊程式版本會同時服務流量</li>
<li>rollback 後舊版本仍需要讀懂 production 資料</li>
<li>內部後台、對帳或報表的切換節奏不同於使用者可見路徑</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>訂單服務新增 <code>payment_state</code> 後，讀取時可先看新欄位，缺值時回到舊 <code>status</code> 的付款語意。客服後台可以先用這條相容讀取路徑驗證資料，再逐步讓使用者可見查詢改用新欄位。</p>
<h2 id="設計責任">設計責任</h2>
<p>Read compatibility 要定義讀取優先順序、fallback read 條件、資料新鮮度限制與停止條件。它要搭配 <a href="/blog/backend/knowledge-cards/validation-query/" data-link-title="Validation Query" data-link-desc="說明遷移、回填與修復期間如何用查詢證明資料語意是否一致">validation query</a> 與 <a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback strategy</a>，避免 cutover 後才發現舊版本或長尾讀取路徑無法判讀資料。</p>
]]></content:encoded></item><item><title>Offline Catch-up</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/offline-catchup/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/offline-catchup/</guid><description>&lt;p>Offline catch-up 的核心概念是「接收端離線期間漏掉的事件，如何在重新連線後補齊」。它是即時通道與正式狀態之間的補償設計。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Offline catch-up 常出現在 WebSocket、mobile push 與跨區域同步。即時通道只負責在線時低延遲傳遞，離線後的完整性通常由 &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>、event log 或資料庫狀態查詢提供。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>例如聊天訊息在使用者離線時不能遺失，重新上線後需要補拉缺失訊息；typing indicator 可以不補送。兩者差異來自事件語意，而不是傳輸通道本身。&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></description><content:encoded><![CDATA[<p>Offline catch-up 的核心概念是「接收端離線期間漏掉的事件，如何在重新連線後補齊」。它是即時通道與正式狀態之間的補償設計。 可先對照 <a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">Durable Queue</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Offline catch-up 常出現在 WebSocket、mobile push 與跨區域同步。即時通道只負責在線時低延遲傳遞，離線後的完整性通常由 <a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue</a>、event log 或資料庫狀態查詢提供。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>例如聊天訊息在使用者離線時不能遺失，重新上線後需要補拉缺失訊息；typing indicator 可以不補送。兩者差異來自事件語意，而不是傳輸通道本身。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義補送範圍、游標或版本、補送時限與去重規則，並把流程寫入 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a>。</p>
]]></content:encoded></item><item><title>Runbook</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/</guid><description>&lt;p>Runbook 的核心概念是「把事故判斷與操作步驟標準化」。它是 &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/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call&lt;/a> 工程師看到特定訊號時如何確認影響、查哪些資料、採取哪些緩解、何時升級，以及如何驗證恢復。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Runbook 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert&lt;/a> 的行動指南。Alert 告訴 &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> 工程師有問題，runbook 告訴他們「收到這個 alert 時該做什麼」。每個 critical alert 應該連到一份 runbook — 缺少 runbook link 的 alert 等於「通知了但不告訴你做什麼」，是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">alert fatigue&lt;/a> 的起點。&lt;/p>
&lt;p>Runbook 也服務於 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review&lt;/a> — 事故中實際執行的步驟跟 runbook 預設的步驟比較，差異就是 runbook 需要更新的地方。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 runbook 的訊號是同一類事故每次都靠個人經驗處理。&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> 快速增加時，runbook 應引導處理者查看錯誤分類、payload 範圍、最近部署、replay 條件與暫停 &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;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Runbook 的有效結構：症狀描述、影響評估、診斷步驟（先看哪個 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a>、查哪些 log）、可能的修復動作（restart / scale / rollback / failover）、升級路徑（15 分鐘內無法解決時通知誰）。維護責任跟 alert 的 owner 一致 — alert rule 改了但 runbook 沒更新是常見的退化。完整設計見 &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 與容量趨勢">4.4&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Runbook 的核心概念是「把事故判斷與操作步驟標準化」。它是 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 的行動指南，描述 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a> 工程師看到特定訊號時如何確認影響、查哪些資料、採取哪些緩解、何時升級，以及如何驗證恢復。</p>
<h2 id="概念位置">概念位置</h2>
<p>Runbook 是 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 的行動指南。Alert 告訴 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a> 工程師有問題，runbook 告訴他們「收到這個 alert 時該做什麼」。每個 critical alert 應該連到一份 runbook — 缺少 runbook link 的 alert 等於「通知了但不告訴你做什麼」，是 <a href="/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">alert fatigue</a> 的起點。</p>
<p>Runbook 也服務於 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review</a> — 事故中實際執行的步驟跟 runbook 預設的步驟比較，差異就是 runbook 需要更新的地方。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 runbook 的訊號是同一類事故每次都靠個人經驗處理。<a href="/blog/backend/knowledge-cards/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">DLQ</a> 快速增加時，runbook 應引導處理者查看錯誤分類、payload 範圍、最近部署、replay 條件與暫停 <a href="/blog/backend/knowledge-cards/consumer/" data-link-title="Consumer" data-link-desc="說明 consumer 如何取得等待處理的工作並產生業務結果">consumer</a> 的判斷。</p>
<h2 id="設計責任">設計責任</h2>
<p>Runbook 的有效結構：症狀描述、影響評估、診斷步驟（先看哪個 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a>、查哪些 log）、可能的修復動作（restart / scale / rollback / failover）、升級路徑（15 分鐘內無法解決時通知誰）。維護責任跟 alert 的 owner 一致 — alert rule 改了但 runbook 沒更新是常見的退化。完整設計見 <a href="/blog/backend/04-observability/dashboard-alert/" data-link-title="4.4 dashboard 與 alert 設計" data-link-desc="讓 dashboard 與 alert 對應 runbook 與容量趨勢">4.4</a>。</p>
]]></content:encoded></item><item><title>Fallback Read</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-read/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-read/</guid><description>&lt;p>Fallback read 的核心概念是「新讀取路徑尚未穩定時，暫時回到舊資料語意或舊讀取來源」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/read-compatibility/" data-link-title="Read Compatibility" data-link-desc="說明資料或服務演進期間讀取路徑如何同時支援新舊語意">read compatibility&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback-window&lt;/a>，讓 cutover 失敗時可以先限制在讀取判讀層。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Fallback read 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">cutover / switchover&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">schema migration&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback strategy&lt;/a> 之間。它保留新資料結構、暫時把讀取判斷交回舊語意或舊來源，比完整 rollback 成本低且破壞性小。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 fallback read 的訊號是：&lt;/p>
&lt;ul>
&lt;li>新欄位讀取後 mismatch 升高&lt;/li>
&lt;li>客服後台、報表或使用者可見查詢結果漂移&lt;/li>
&lt;li>寫入路徑已經收斂，但讀取模型或索引尚未穩定&lt;/li>
&lt;li>release gate 允許暫停 cutover，但尚未需要資料修補&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>訂單服務把付款狀態拆到 &lt;code>payment_state&lt;/code> 後，客服後台若發現新欄位判讀 mismatch 升高，可以先回到舊 &lt;code>status&lt;/code> 的付款語意讀取，讓客服分類回到基線，同時保留 backfill 與 validation query 繼續查證。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Fallback read 要定義觸發條件、讀取優先順序、可維持多久、哪些入口適用，以及何時重新嘗試 cutover。它要與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/validation-query/" data-link-title="Validation Query" data-link-desc="說明遷移、回填與修復期間如何用查詢證明資料語意是否一致">validation query&lt;/a> 和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a> 對齊，避免讀取回退變成沒有證據的永久分岔。&lt;/p></description><content:encoded><![CDATA[<p>Fallback read 的核心概念是「新讀取路徑尚未穩定時，暫時回到舊資料語意或舊讀取來源」。它連接 <a href="/blog/backend/knowledge-cards/read-compatibility/" data-link-title="Read Compatibility" data-link-desc="說明資料或服務演進期間讀取路徑如何同時支援新舊語意">read compatibility</a>、<a href="/blog/backend/knowledge-cards/fallback/" data-link-title="Fallback" data-link-desc="說明主要路徑失敗時使用替代結果或替代流程的設計責任">fallback</a> 與 <a href="/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback-window</a>，讓 cutover 失敗時可以先限制在讀取判讀層。</p>
<h2 id="概念位置">概念位置</h2>
<p>Fallback read 位在 <a href="/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">cutover / switchover</a>、<a href="/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">schema migration</a> 與 <a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback strategy</a> 之間。它保留新資料結構、暫時把讀取判斷交回舊語意或舊來源，比完整 rollback 成本低且破壞性小。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 fallback read 的訊號是：</p>
<ul>
<li>新欄位讀取後 mismatch 升高</li>
<li>客服後台、報表或使用者可見查詢結果漂移</li>
<li>寫入路徑已經收斂，但讀取模型或索引尚未穩定</li>
<li>release gate 允許暫停 cutover，但尚未需要資料修補</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>訂單服務把付款狀態拆到 <code>payment_state</code> 後，客服後台若發現新欄位判讀 mismatch 升高，可以先回到舊 <code>status</code> 的付款語意讀取，讓客服分類回到基線，同時保留 backfill 與 validation query 繼續查證。</p>
<h2 id="設計責任">設計責任</h2>
<p>Fallback read 要定義觸發條件、讀取優先順序、可維持多久、哪些入口適用，以及何時重新嘗試 cutover。它要與 <a href="/blog/backend/knowledge-cards/validation-query/" data-link-title="Validation Query" data-link-desc="說明遷移、回填與修復期間如何用查詢證明資料語意是否一致">validation query</a> 和 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a> 對齊，避免讀取回退變成沒有證據的永久分岔。</p>
]]></content:encoded></item><item><title>Strong Reliability</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/strong-reliability/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/strong-reliability/</guid><description>&lt;p>Strong reliability 的核心概念是「關鍵事件在失敗條件下仍可被恢復到可接受狀態」。它不代表絕對零失敗，而是要求可追蹤、可補償、可驗證。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>高可靠路徑常用在金流、庫存、權限與稽核事件。這些路徑通常需要 &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;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/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency&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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>例如付款成功事件若遺失，可能造成對帳錯誤；這類事件需要保存與補送。相對地，typing indicator 遺失通常不影響核心產品承諾。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義失敗代價、保證等級、觀測指標與驗證流程，並界定 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/reliability-boundary/" data-link-title="Reliability Boundary" data-link-desc="說明系統在哪個邊界內承諾可靠傳遞，邊界外需要哪些補償機制">reliability boundary&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Strong reliability 的核心概念是「關鍵事件在失敗條件下仍可被恢復到可接受狀態」。它不代表絕對零失敗，而是要求可追蹤、可補償、可驗證。 可先對照 <a href="/blog/backend/knowledge-cards/message-persistence/" data-link-title="Message Persistence" data-link-desc="說明訊息是否落盤保存，以及 broker 重啟後能否恢復">Message Persistence</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>高可靠路徑常用在金流、庫存、權限與稽核事件。這些路徑通常需要 <a href="/blog/backend/knowledge-cards/message-persistence/" data-link-title="Message Persistence" data-link-desc="說明訊息是否落盤保存，以及 broker 重啟後能否恢復">message persistence</a>、<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/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</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> 與回復流程。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>例如付款成功事件若遺失，可能造成對帳錯誤；這類事件需要保存與補送。相對地，typing indicator 遺失通常不影響核心產品承諾。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義失敗代價、保證等級、觀測指標與驗證流程，並界定 <a href="/blog/backend/knowledge-cards/reliability-boundary/" data-link-title="Reliability Boundary" data-link-desc="說明系統在哪個邊界內承諾可靠傳遞，邊界外需要哪些補償機制">reliability boundary</a>。</p>
]]></content:encoded></item><item><title>Cutover Window</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-window/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-window/</guid><description>&lt;p>Cutover window 的核心概念是「正式切換發生並被密集觀察的時間與條件範圍」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">cutover / switchover&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback-window&lt;/a>，讓切換成為一段可停止、可判讀的窗口，脫離瞬間按鈕的思維。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cutover window 位在 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a> 之間。Release gate 決定能否開始切換，cutover window 定義切換後多久內要看哪些訊號、達到什麼條件才算穩定。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 cutover window 的訊號是：&lt;/p>
&lt;ul>
&lt;li>新路徑開始承接正式讀取或寫入&lt;/li>
&lt;li>切換後需要觀察 mismatch、latency、error rate 或 lag&lt;/li>
&lt;li>回退條件只在切換初期仍然低成本&lt;/li>
&lt;li>多個入口會分批切換，需要分別記錄時間窗&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>客服後台先切到新 &lt;code>payment_state&lt;/code> 讀取後，前 30 分鐘是 cutover window。這段期間要看 mismatch sample、客服查詢慢查詢、對帳補償量與 rollback window；穩定後才放行使用者可見讀取。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Cutover window 要定義開始時間、觀察長度、通過條件、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stop-condition/" data-link-title="Stop Condition" data-link-desc="說明變更、實驗或事故處理何時必須暫停、回退或改路線">stop condition&lt;/a> 與 owner。它應進入 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a>，讓事後能回放切換當時的訊號。&lt;/p></description><content:encoded><![CDATA[<p>Cutover window 的核心概念是「正式切換發生並被密集觀察的時間與條件範圍」。它連接 <a href="/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">cutover / switchover</a>、<a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate</a> 與 <a href="/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback-window</a>，讓切換成為一段可停止、可判讀的窗口，脫離瞬間按鈕的思維。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cutover window 位在 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">release gate</a>、<a href="/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state</a> 與 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a> 之間。Release gate 決定能否開始切換，cutover window 定義切換後多久內要看哪些訊號、達到什麼條件才算穩定。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 cutover window 的訊號是：</p>
<ul>
<li>新路徑開始承接正式讀取或寫入</li>
<li>切換後需要觀察 mismatch、latency、error rate 或 lag</li>
<li>回退條件只在切換初期仍然低成本</li>
<li>多個入口會分批切換，需要分別記錄時間窗</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>客服後台先切到新 <code>payment_state</code> 讀取後，前 30 分鐘是 cutover window。這段期間要看 mismatch sample、客服查詢慢查詢、對帳補償量與 rollback window；穩定後才放行使用者可見讀取。</p>
<h2 id="設計責任">設計責任</h2>
<p>Cutover window 要定義開始時間、觀察長度、通過條件、<a href="/blog/backend/knowledge-cards/stop-condition/" data-link-title="Stop Condition" data-link-desc="說明變更、實驗或事故處理何時必須暫停、回退或改路線">stop condition</a> 與 owner。它應進入 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a> 與 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a>，讓事後能回放切換當時的訊號。</p>
]]></content:encoded></item><item><title>Durable Queue</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/durable-queue/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/durable-queue/</guid><description>&lt;p>Durable queue 的核心概念是「待處理工作在 process 重啟或節點故障後仍可被取回」。它把 queue 從記憶體暫存提升為可恢復的工作通道。 可先對照 &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>Durable queue 是 &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/message-persistence/" data-link-title="Message Persistence" data-link-desc="說明訊息是否落盤保存，以及 broker 重啟後能否恢復">message persistence&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;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;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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>當工作可延遲但不可遺失時，durable queue 是常見候選。例如付款後通知、對帳同步、背景轉檔。若僅需在線即時廣播，通常 &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;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義保存期限、重試上限、去重策略、queue lag 告警與回復流程，避免把可靠性責任留給人工排障。&lt;/p></description><content:encoded><![CDATA[<p>Durable queue 的核心概念是「待處理工作在 process 重啟或節點故障後仍可被取回」。它把 queue 從記憶體暫存提升為可恢復的工作通道。 可先對照 <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">Queue</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Durable queue 是 <a href="/blog/backend/knowledge-cards/queue/" data-link-title="Queue" data-link-desc="說明 queue 如何保存等待處理的工作並形成容量邊界">queue</a> 與 <a href="/blog/backend/knowledge-cards/message-persistence/" data-link-title="Message Persistence" data-link-desc="說明訊息是否落盤保存，以及 broker 重啟後能否恢復">message persistence</a> 的組合，常由 <a href="/blog/backend/knowledge-cards/broker/" data-link-title="Broker" data-link-desc="說明 broker 在訊息傳遞系統中負責保存、路由與交付訊息">broker</a> 提供，並搭配 <a href="/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">ack/nack</a>、<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>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>當工作可延遲但不可遺失時，durable queue 是常見候選。例如付款後通知、對帳同步、背景轉檔。若僅需在線即時廣播，通常 <a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">pub/sub</a> 成本更低。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義保存期限、重試上限、去重策略、queue lag 告警與回復流程，避免把可靠性責任留給人工排障。</p>
]]></content:encoded></item><item><title>Event Log</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/event-log/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/event-log/</guid><description>&lt;p>Event log 按時間保存已發生事件的不可變紀錄，是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-sourcing/" data-link-title="Event Sourcing" data-link-desc="說明用 append-only 事件流取代 mutable state 作為正式紀錄的設計模式、需求判準與代價">event sourcing&lt;/a> 的儲存層。每一筆事件記錄一次狀態變更，整條事件流構成完整的變更歷史。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Event log 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-sourcing/" data-link-title="Event Sourcing" data-link-desc="說明用 append-only 事件流取代 mutable state 作為正式紀錄的設計模式、需求判準與代價">event sourcing&lt;/a> 的儲存層。在 event sourcing 架構中，event log 是 &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>，current state 透過 replay 事件流推算。在非 event sourcing 架構中，event log 是輔助紀錄 — 正式狀態仍由 mutable record 承擔，event log 提供變更歷史跟 replay 能力。&lt;/p>
&lt;p>Event log 的讀取面透過 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">projection&lt;/a> 轉換成 &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>，讓消費者不需要每次 replay 整條事件流。在訊息傳遞面，event log 常搭配 &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;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/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook&lt;/a> 使用。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>訂單狀態變更可寫入 event log，後續由報表、通知、稽核服務各自消費。當下游落後時，可用 replay 補齊資料。金融帳務的每一筆增減、權限變更的每一次授權與撤銷、訂閱方案的每一次升降級，都是典型的 event log 應用。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義事件 schema 演進（新版 consumer 要能消費舊版事件）、保留期限（無限保留 vs retention-based 清理）、重播邊界（從哪個 offset 開始 replay）與去重策略（&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency&lt;/a> 保證）。Event log 的儲存成長是長期成本 — 高頻寫入的系統需要 snapshot 機制或 retention 策略來控制。&lt;/p></description><content:encoded><![CDATA[<p>Event log 按時間保存已發生事件的不可變紀錄，是 <a href="/blog/backend/knowledge-cards/event-sourcing/" data-link-title="Event Sourcing" data-link-desc="說明用 append-only 事件流取代 mutable state 作為正式紀錄的設計模式、需求判準與代價">event sourcing</a> 的儲存層。每一筆事件記錄一次狀態變更，整條事件流構成完整的變更歷史。</p>
<h2 id="概念位置">概念位置</h2>
<p>Event log 是 <a href="/blog/backend/knowledge-cards/event-sourcing/" data-link-title="Event Sourcing" data-link-desc="說明用 append-only 事件流取代 mutable state 作為正式紀錄的設計模式、需求判準與代價">event sourcing</a> 的儲存層。在 event sourcing 架構中，event log 是 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a>，current state 透過 replay 事件流推算。在非 event sourcing 架構中，event log 是輔助紀錄 — 正式狀態仍由 mutable record 承擔，event log 提供變更歷史跟 replay 能力。</p>
<p>Event log 的讀取面透過 <a href="/blog/backend/knowledge-cards/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">projection</a> 轉換成 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a>，讓消費者不需要每次 replay 整條事件流。在訊息傳遞面，event log 常搭配 <a href="/blog/backend/knowledge-cards/consumer-group/" data-link-title="Consumer Group" data-link-desc="說明一組 consumer 如何共同分攤 stream 或 topic 的處理責任">consumer group</a>、<a href="/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">offset</a> 與 <a href="/blog/backend/knowledge-cards/replay-runbook/" data-link-title="Replay Runbook" data-link-desc="說明事件重放前需要控制的範圍、順序、驗證與副作用">replay runbook</a> 使用。</p>
<h2 id="使用情境">使用情境</h2>
<p>訂單狀態變更可寫入 event log，後續由報表、通知、稽核服務各自消費。當下游落後時，可用 replay 補齊資料。金融帳務的每一筆增減、權限變更的每一次授權與撤銷、訂閱方案的每一次升降級，都是典型的 event log 應用。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義事件 schema 演進（新版 consumer 要能消費舊版事件）、保留期限（無限保留 vs retention-based 清理）、重播邊界（從哪個 offset 開始 replay）與去重策略（<a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 保證）。Event log 的儲存成長是長期成本 — 高頻寫入的系統需要 snapshot 機制或 retention 策略來控制。</p>
]]></content:encoded></item><item><title>Mapping Table</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/mapping-table/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/mapping-table/</guid><description>&lt;p>Mapping table 的核心概念是「把舊資料語意明確對應到新資料語意」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">schema migration&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/correctness-check/" data-link-title="Correctness Check" data-link-desc="說明遷移或重構期間如何驗證新舊結果是否符合規則">correctness check&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/validation-query/" data-link-title="Validation Query" data-link-desc="說明遷移、回填與修復期間如何用查詢證明資料語意是否一致">validation-query&lt;/a>，讓轉換規則成為可查證 artifact，而不是工程師腦中的口頭規則。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Mapping table 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">backfill&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">data reconciliation&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate&lt;/a> 之間。Backfill 依它轉換資料，validation query 依它判斷 mismatch，incident decision log 則依它追溯當時的判讀依據。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 mapping table 的訊號是：&lt;/p>
&lt;ul>
&lt;li>舊欄位混合多種業務語意，需要拆到新欄位&lt;/li>
&lt;li>多個舊狀態會對應到同一個新狀態&lt;/li>
&lt;li>某些舊狀態需要人工確認或例外處理&lt;/li>
&lt;li>事後要能解釋 mismatch 是資料錯誤還是轉換規則錯誤&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>訂單服務把 &lt;code>pending_payment&lt;/code>、&lt;code>paid&lt;/code>、&lt;code>payment_failed&lt;/code>、&lt;code>refunded&lt;/code> 對應到 &lt;code>payment_state&lt;/code> 的 &lt;code>pending&lt;/code>、&lt;code>captured&lt;/code>、&lt;code>failed&lt;/code>、&lt;code>refunded&lt;/code>。這張 mapping table 同時支撐 backfill job、validation query 與 cutover gate。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Mapping table 要保留來源欄位、新欄位、對應理由、例外狀態與 owner。高風險 mapping 要版本化，並進入 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a>；否則資料漂移時，團隊很難判斷問題出在資料、程式還是規則本身。&lt;/p></description><content:encoded><![CDATA[<p>Mapping table 的核心概念是「把舊資料語意明確對應到新資料語意」。它連接 <a href="/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">schema migration</a>、<a href="/blog/backend/knowledge-cards/correctness-check/" data-link-title="Correctness Check" data-link-desc="說明遷移或重構期間如何驗證新舊結果是否符合規則">correctness check</a> 與 <a href="/blog/backend/knowledge-cards/validation-query/" data-link-title="Validation Query" data-link-desc="說明遷移、回填與修復期間如何用查詢證明資料語意是否一致">validation-query</a>，讓轉換規則成為可查證 artifact，而不是工程師腦中的口頭規則。</p>
<h2 id="概念位置">概念位置</h2>
<p>Mapping table 位在 <a href="/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">backfill</a>、<a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">data reconciliation</a> 與 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate</a> 之間。Backfill 依它轉換資料，validation query 依它判斷 mismatch，incident decision log 則依它追溯當時的判讀依據。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 mapping table 的訊號是：</p>
<ul>
<li>舊欄位混合多種業務語意，需要拆到新欄位</li>
<li>多個舊狀態會對應到同一個新狀態</li>
<li>某些舊狀態需要人工確認或例外處理</li>
<li>事後要能解釋 mismatch 是資料錯誤還是轉換規則錯誤</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>訂單服務把 <code>pending_payment</code>、<code>paid</code>、<code>payment_failed</code>、<code>refunded</code> 對應到 <code>payment_state</code> 的 <code>pending</code>、<code>captured</code>、<code>failed</code>、<code>refunded</code>。這張 mapping table 同時支撐 backfill job、validation query 與 cutover gate。</p>
<h2 id="設計責任">設計責任</h2>
<p>Mapping table 要保留來源欄位、新欄位、對應理由、例外狀態與 owner。高風險 mapping 要版本化，並進入 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a>；否則資料漂移時，團隊很難判斷問題出在資料、程式還是規則本身。</p>
]]></content:encoded></item><item><title>Website Certificate Lifecycle</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/website-certificate-lifecycle/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/website-certificate-lifecycle/</guid><description>&lt;p>Website certificate lifecycle 的核心概念是「把網站憑證視為持續運作流程，而非一次性設定」。流程包含簽發、部署、驗證、監控、續期、輪替、撤銷與事故處理。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>網站憑證生命週期位在 &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/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>系統需要網站憑證生命週期設計的訊號是服務會公開提供 HTTPS。電商網站在促銷高峰若遇到憑證過期，使用者會直接遇到瀏覽器安全警示並中斷交易。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計要定義簽發方式、部署邊界、過期門檻 &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/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&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;/p></description><content:encoded><![CDATA[<p>Website certificate lifecycle 的核心概念是「把網站憑證視為持續運作流程，而非一次性設定」。流程包含簽發、部署、驗證、監控、續期、輪替、撤銷與事故處理。 可先對照 <a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>網站憑證生命週期位在 <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/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">secret management</a> 的交界。它同時影響可用性、資安與操作成本，因為憑證過期、鏈錯誤或私鑰洩漏都會直接影響服務可用性。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要網站憑證生命週期設計的訊號是服務會公開提供 HTTPS。電商網站在促銷高峰若遇到憑證過期，使用者會直接遇到瀏覽器安全警示並中斷交易。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計要定義簽發方式、部署邊界、過期門檻 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>、續期演練、撤銷流程、權限分離與 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a>。高流量站點應把憑證健康納入 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> 與停機演練。</p>
]]></content:encoded></item><item><title>Search Index</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/search-index/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/search-index/</guid><description>&lt;p>Search index 的核心概念是「為查詢體驗建立專用的讀取模型」。它擅長全文搜尋、排序、filter 與 facet，通常是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">derived state&lt;/a>、從正式資料源同步而來。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Search index 是 &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/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth&lt;/a> 管理（relational DB、document DB），search index 透過 CDC、event subscription 或 ETL 同步更新。概念上跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/materialized-view/" data-link-title="Materialized View" data-link-desc="說明預先計算並儲存查詢結果以加速讀取的資料結構">materialized view&lt;/a> 類似 — 都是為特定查詢需求預先準備的資料形狀。&lt;/p>
&lt;p>在觀測領域，log storage 的 search index（Elasticsearch / Loki 的 label index）承擔 log 查詢的效能。Index 的欄位選擇跟 cardinality 影響查詢延遲跟儲存成本，見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/log-schema/" data-link-title="4.1 log schema 與搜尋規劃" data-link-desc="整理 log 欄位、索引與搜尋策略">4.1 log schema&lt;/a>。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>商品搜尋、文件站搜尋、客服多條件檢索、log 查詢通常都需要 search index 提供低延遲查詢體驗。Elasticsearch、Algolia、Meilisearch、Typesense 是常見實作。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義索引更新延遲（source 變更到 index 可查的時間）、重建流程（index 損壞或 schema 改版時的 full reindex）、查詢語意（全文 vs 結構化 filter）與權限過濾（search 結果是否要按使用者權限過濾）。Index 是 derived state — 修復方式是 rebuild 而非直接修改。&lt;/p></description><content:encoded><![CDATA[<p>Search index 的核心概念是「為查詢體驗建立專用的讀取模型」。它擅長全文搜尋、排序、filter 與 facet，通常是 <a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">derived state</a>、從正式資料源同步而來。</p>
<h2 id="概念位置">概念位置</h2>
<p>Search index 是 <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/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a> 管理（relational DB、document DB），search index 透過 CDC、event subscription 或 ETL 同步更新。概念上跟 <a href="/blog/backend/knowledge-cards/materialized-view/" data-link-title="Materialized View" data-link-desc="說明預先計算並儲存查詢結果以加速讀取的資料結構">materialized view</a> 類似 — 都是為特定查詢需求預先準備的資料形狀。</p>
<p>在觀測領域，log storage 的 search index（Elasticsearch / Loki 的 label index）承擔 log 查詢的效能。Index 的欄位選擇跟 cardinality 影響查詢延遲跟儲存成本，見 <a href="/blog/backend/04-observability/log-schema/" data-link-title="4.1 log schema 與搜尋規劃" data-link-desc="整理 log 欄位、索引與搜尋策略">4.1 log schema</a>。</p>
<h2 id="使用情境">使用情境</h2>
<p>商品搜尋、文件站搜尋、客服多條件檢索、log 查詢通常都需要 search index 提供低延遲查詢體驗。Elasticsearch、Algolia、Meilisearch、Typesense 是常見實作。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義索引更新延遲（source 變更到 index 可查的時間）、重建流程（index 損壞或 schema 改版時的 full reindex）、查詢語意（全文 vs 結構化 filter）與權限過濾（search 結果是否要按使用者權限過濾）。Index 是 derived state — 修復方式是 rebuild 而非直接修改。</p>
]]></content:encoded></item><item><title>ACME Automation</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/acme-automation/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/acme-automation/</guid><description>&lt;p>ACME automation 的核心概念是「用標準化協議自動化網站憑證簽發與續期」。它透過 HTTP-01、DNS-01 或 TLS-ALPN-01 驗證網域控制權，減少手動更新憑證的風險。 可先對照 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>ACME 自動化是 &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> 的簽發與續期機制。它通常和 ingress、CDN、load balancer 或 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 ACME 自動化的訊號是站點數量增加、環境增加或憑證更新頻率提高。多網域 SaaS 服務若使用手動續期，憑證遺漏更新的風險會快速上升。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計要定義 challenge 類型、失敗重試、續期窗口、憑證分發、失敗 &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/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a>。網域與 DNS 權限要和 &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;/p></description><content:encoded><![CDATA[<p>ACME automation 的核心概念是「用標準化協議自動化網站憑證簽發與續期」。它透過 HTTP-01、DNS-01 或 TLS-ALPN-01 驗證網域控制權，減少手動更新憑證的風險。 可先對照 <a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">Website Certificate Lifecycle</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>ACME 自動化是 <a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">website certificate lifecycle</a> 的簽發與續期機制。它通常和 ingress、CDN、load balancer 或 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a> 整合，確保多節點部署時維持一致憑證狀態。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 ACME 自動化的訊號是站點數量增加、環境增加或憑證更新頻率提高。多網域 SaaS 服務若使用手動續期，憑證遺漏更新的風險會快速上升。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計要定義 challenge 類型、失敗重試、續期窗口、憑證分發、失敗 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 與回復 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a>。網域與 DNS 權限要和 <a href="/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">least privilege</a> 對齊。</p>
]]></content:encoded></item><item><title>Certificate Chain and Trust Root</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-chain-trust/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-chain-trust/</guid><description>&lt;p>Certificate chain and trust root 的核心概念是「憑證驗證依賴完整憑證鏈與受信任根」。伺服器端需要提供 leaf certificate 與中繼憑證，客戶端再以信任根驗證整條鏈。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>憑證鏈與信任根是 &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> 成功握手的基礎。鏈配置錯誤、根憑證不受信任或中繼遺失，都會造成 HTTPS 連線失敗。&lt;/p>
&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>。運維流程要把憑證鏈檢查納入部署 gate 與例行健康檢查。&lt;/p></description><content:encoded><![CDATA[<p>Certificate chain and trust root 的核心概念是「憑證驗證依賴完整憑證鏈與受信任根」。伺服器端需要提供 leaf certificate 與中繼憑證，客戶端再以信任根驗證整條鏈。 可先對照 <a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>憑證鏈與信任根是 <a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS</a> 成功握手的基礎。鏈配置錯誤、根憑證不受信任或中繼遺失，都會造成 HTTPS 連線失敗。</p>
<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>。運維流程要把憑證鏈檢查納入部署 gate 與例行健康檢查。</p>
]]></content:encoded></item><item><title>Object Storage</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/object-storage/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/object-storage/</guid><description>&lt;p>Object storage 的核心概念是「用 object key 管理大型檔案內容」。它適合圖片、影片、附件、匯出檔與備份，不適合承擔複雜交易查詢。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/observability-middleware/" data-link-title="Observability Middleware" data-link-desc="說明請求進入 handler 前後如何補上觀測欄位">Observability Middleware&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>常見做法是把檔案 metadata 放在資料庫，內容放在 object storage，並用 key 連結兩者。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/observability-middleware/" data-link-title="Observability Middleware" data-link-desc="說明請求進入 handler 前後如何補上觀測欄位">Observability Middleware&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>例如使用者上傳附件、報表匯出、備份封存，通常都會走 object storage 路徑。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義存取權限、下載時效、版本策略、保留期限與刪除流程，避免檔案生命週期失控。&lt;/p></description><content:encoded><![CDATA[<p>Object storage 的核心概念是「用 object key 管理大型檔案內容」。它適合圖片、影片、附件、匯出檔與備份，不適合承擔複雜交易查詢。 可先對照 <a href="/blog/backend/knowledge-cards/observability-middleware/" data-link-title="Observability Middleware" data-link-desc="說明請求進入 handler 前後如何補上觀測欄位">Observability Middleware</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>常見做法是把檔案 metadata 放在資料庫，內容放在 object storage，並用 key 連結兩者。 可先對照 <a href="/blog/backend/knowledge-cards/observability-middleware/" data-link-title="Observability Middleware" data-link-desc="說明請求進入 handler 前後如何補上觀測欄位">Observability Middleware</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>例如使用者上傳附件、報表匯出、備份封存，通常都會走 object storage 路徑。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義存取權限、下載時效、版本策略、保留期限與刪除流程，避免檔案生命週期失控。</p>
]]></content:encoded></item><item><title>Certificate Rotation and Renewal</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-rotation-renewal/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-rotation-renewal/</guid><description>&lt;p>Certificate rotation and renewal 的核心概念是「在不中斷服務的前提下更新憑證與私鑰」。續期關注到期前更新，輪替關注主動替換既有憑證與金鑰材料。 可先對照 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>續期與輪替是 &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> 的穩定性核心，並與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">downtime&lt;/a> 風險直接相關。流程設計不完整時，憑證到期會直接造成服務中斷。&lt;/p>
&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/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert&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;/p></description><content:encoded><![CDATA[<p>Certificate rotation and renewal 的核心概念是「在不中斷服務的前提下更新憑證與私鑰」。續期關注到期前更新，輪替關注主動替換既有憑證與金鑰材料。 可先對照 <a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">Website Certificate Lifecycle</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>續期與輪替是 <a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">website certificate lifecycle</a> 的穩定性核心，並與 <a href="/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">downtime</a> 風險直接相關。流程設計不完整時，憑證到期會直接造成服務中斷。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要續期與輪替設計的訊號是憑證有效期縮短或多環境併行部署。支付入口在到期日前未完成灰度更新，可能在流量尖峰觸發連線失敗。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計要定義到期門檻 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>、灰度部署、回滾條件、私鑰輪替、兼容測試與驗證清單。變更後應以 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> 追蹤握手錯誤率與憑證剩餘天數。</p>
]]></content:encoded></item><item><title>Local Worker</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/local-worker/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/local-worker/</guid><description>&lt;p>Local worker 的核心概念是「背景工作仍留在同一個 application process」。它可降低 request 等待時間，但不提供跨 process 的持久可靠保證。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Local worker 常搭配 &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;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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>例如非關鍵通知、短週期快取刷新、定時清理記憶體資料，可先由 local worker 承擔。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義停止行為、錯誤處理、隊列上限與 shutdown 合約，避免背景任務在重啟時遺失而不可見。&lt;/p></description><content:encoded><![CDATA[<p>Local worker 的核心概念是「背景工作仍留在同一個 application process」。它可降低 request 等待時間，但不提供跨 process 的持久可靠保證。 可先對照 <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>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Local worker 常搭配 <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>；若需求轉向跨節點可靠處理，通常要改用 <a href="/blog/backend/knowledge-cards/durable-queue/" data-link-title="Durable Queue" data-link-desc="說明可持久化的 queue 如何在重啟與失敗後保留待處理工作">durable queue</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>例如非關鍵通知、短週期快取刷新、定時清理記憶體資料，可先由 local worker 承擔。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義停止行為、錯誤處理、隊列上限與 shutdown 合約，避免背景任務在重啟時遺失而不可見。</p>
]]></content:encoded></item><item><title>Certificate Revocation</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-revocation/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/certificate-revocation/</guid><description>&lt;p>Certificate revocation 的核心概念是「在憑證不再可信時快速宣布失效」。常見觸發情境是私鑰洩漏、錯誤簽發、身份資訊不再有效或資安事件需要立即切斷信任。 可先對照 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>憑證撤銷是 &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> 的事故處理能力，與 &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/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log&lt;/a> 一起構成憑證風險控制邊界。&lt;/p>
&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">post-incident&lt;/a> 更新偵測與輪替策略。&lt;/p></description><content:encoded><![CDATA[<p>Certificate revocation 的核心概念是「在憑證不再可信時快速宣布失效」。常見觸發情境是私鑰洩漏、錯誤簽發、身份資訊不再有效或資安事件需要立即切斷信任。 可先對照 <a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">Website Certificate Lifecycle</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>憑證撤銷是 <a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">website certificate lifecycle</a> 的事故處理能力，與 <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/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit log</a> 一起構成憑證風險控制邊界。</p>
<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>。事故後要以 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">post-incident</a> 更新偵測與輪替策略。</p>
]]></content:encoded></item><item><title>Delivery Semantics</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/delivery-semantics/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/delivery-semantics/</guid><description>&lt;p>Delivery semantics 的核心概念是「系統對事件投遞結果的承諾」。它回答訊息可否遺失、可否重複、是否要求順序，以及失敗後如何補償。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Delivery semantics 直接影響 &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/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency&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 runbook&lt;/a> 設計。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>例如支付事件通常需要高可靠與去重；typing indicator 通常可接受遺失。兩者應使用不同的 delivery semantics。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要把語意寫入事件合約與操作流程，避免不同服務對同一事件有不同預設而造成隱性風險。&lt;/p></description><content:encoded><![CDATA[<p>Delivery semantics 的核心概念是「系統對事件投遞結果的承諾」。它回答訊息可否遺失、可否重複、是否要求順序，以及失敗後如何補償。 可先對照 <a href="/blog/backend/knowledge-cards/retry-policy/" data-link-title="Retry Policy" data-link-desc="說明重試策略如何區分暫時性錯誤、永久錯誤與副作用風險">Retry Policy</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Delivery semantics 直接影響 <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/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</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 runbook</a> 設計。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>例如支付事件通常需要高可靠與去重；typing indicator 通常可接受遺失。兩者應使用不同的 delivery semantics。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要把語意寫入事件合約與操作流程，避免不同服務對同一事件有不同預設而造成隱性風險。</p>
]]></content:encoded></item><item><title>Read Model</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/read-model/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/read-model/</guid><description>&lt;p>Read model 的核心概念是「為特定查詢需求建立專用的資料形狀」。它跟正式狀態（&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>）的責任分離 — 正式狀態為寫入的正確性最佳化，read model 為讀取的效率與體驗最佳化。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Read model 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cqrs/" data-link-title="CQRS" data-link-desc="說明讀寫不對稱時為何需要分離查詢與寫入責任、分離的判準與代價">CQRS&lt;/a> 的讀取面產物。在 CQRS 架構中，write model 跟 read model 各自獨立，read model 透過同步機制（event handler、CDC、定期刷新）從 write model 更新。&lt;/p>
&lt;p>Read model 的來源可以是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">projection&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/materialized-view/" data-link-title="Materialized View" data-link-desc="說明預先計算並儲存查詢結果以加速讀取的資料結構">materialized view&lt;/a>（從 SQL 查詢預計算）、CDC consumer（從 row change 同步到搜尋索引）或批次 ETL（定期從 OLTP 匯出到 analytics store）。不同的來源機制有不同的更新延遲跟維護成本。&lt;/p>
&lt;p>在觀測領域，&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup&lt;/a> 扮演類似 read model 的角色 — 從 raw time series 預計算聚合結果，讓 dashboard 讀取預聚合資料而非重算 raw data。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 read model 時要定義同步延遲（read model 落後 write model 多久可以接受）、重建流程（read model 損壞或 schema 變更時如何從頭重建）、欄位語意（read model 的欄位定義跟 write model 可能不同）與查詢邊界（這個 read model 能回答什麼問題、不能回答什麼問題）。&lt;/p>
&lt;p>Read model 是派生狀態，修復方式是「砍掉重建」而非直接修改。把 read model 當正式狀態修改會導致 write model 跟 read model 分岔、後續同步覆蓋修改。&lt;/p></description><content:encoded><![CDATA[<p>Read model 的核心概念是「為特定查詢需求建立專用的資料形狀」。它跟正式狀態（<a href="/blog/backend/knowledge-cards/source-of-truth/" data-link-title="Source of Truth" data-link-desc="說明正式資料來源如何決定資料判斷、修復與一致性責任">source of truth</a>）的責任分離 — 正式狀態為寫入的正確性最佳化，read model 為讀取的效率與體驗最佳化。</p>
<h2 id="概念位置">概念位置</h2>
<p>Read model 是 <a href="/blog/backend/knowledge-cards/cqrs/" data-link-title="CQRS" data-link-desc="說明讀寫不對稱時為何需要分離查詢與寫入責任、分離的判準與代價">CQRS</a> 的讀取面產物。在 CQRS 架構中，write model 跟 read model 各自獨立，read model 透過同步機制（event handler、CDC、定期刷新）從 write model 更新。</p>
<p>Read model 的來源可以是 <a href="/blog/backend/knowledge-cards/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">projection</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/materialized-view/" data-link-title="Materialized View" data-link-desc="說明預先計算並儲存查詢結果以加速讀取的資料結構">materialized view</a>（從 SQL 查詢預計算）、CDC consumer（從 row change 同步到搜尋索引）或批次 ETL（定期從 OLTP 匯出到 analytics store）。不同的來源機制有不同的更新延遲跟維護成本。</p>
<p>在觀測領域，<a href="/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule</a> 跟 <a href="/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup</a> 扮演類似 read model 的角色 — 從 raw time series 預計算聚合結果，讓 dashboard 讀取預聚合資料而非重算 raw data。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 read model 時要定義同步延遲（read model 落後 write model 多久可以接受）、重建流程（read model 損壞或 schema 變更時如何從頭重建）、欄位語意（read model 的欄位定義跟 write model 可能不同）與查詢邊界（這個 read model 能回答什麼問題、不能回答什麼問題）。</p>
<p>Read model 是派生狀態，修復方式是「砍掉重建」而非直接修改。把 read model 當正式狀態修改會導致 write model 跟 read model 分岔、後續同步覆蓋修改。</p>
]]></content:encoded></item><item><title>Incident Severity</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/</guid><description>&lt;p>Incident severity 的核心概念是「用一致標準把事故影響分級」。分級描述的是產品影響範圍、持續時間、資料風險與回復緊急程度，技術細節放在其他層處理。 可先對照 &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;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Incident severity 連接 &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/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy&lt;/a>。同一類技術錯誤在不同業務場景可能有不同等級，因此分級要以產品後果為主。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要分級模型的訊號是事件發生後團隊對嚴重度判斷不一致。付款成功率下降與單一內部報表延遲都可能由 timeout 引起，但前者需要立即啟動高優先級處置，後者通常走一般排程修復。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>分級要定義等級條件、升級門檻、負責角色、通訊頻率與回顧要求。等級規則應定期和事故紀錄對照，避免長期失真。&lt;/p></description><content:encoded><![CDATA[<p>Incident severity 的核心概念是「用一致標準把事故影響分級」。分級描述的是產品影響範圍、持續時間、資料風險與回復緊急程度，技術細節放在其他層處理。 可先對照 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">Alert</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Incident severity 連接 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>、<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 與 <a href="/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy</a>。同一類技術錯誤在不同業務場景可能有不同等級，因此分級要以產品後果為主。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要分級模型的訊號是事件發生後團隊對嚴重度判斷不一致。付款成功率下降與單一內部報表延遲都可能由 timeout 引起，但前者需要立即啟動高優先級處置，後者通常走一般排程修復。</p>
<h2 id="設計責任">設計責任</h2>
<p>分級要定義等級條件、升級門檻、負責角色、通訊頻率與回顧要求。等級規則應定期和事故紀錄對照，避免長期失真。</p>
]]></content:encoded></item><item><title>Incident Command System</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/incident-command-system/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/incident-command-system/</guid><description>&lt;p>Incident command system 的核心概念是「事故期間由明確角色統一決策與分工」。它把指揮、操作、溝通與紀錄拆開，降低多人同時決策造成的混亂。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>指揮系統連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline&lt;/a>。常見角色包括 incident commander、technical owner、communication owner 與 scribe。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要指揮系統的訊號是事故期間同時出現多個聊天室與多個口頭指令。若沒有單一指揮窗口，團隊容易同時做出互相衝突的切換與回滾。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>指揮系統要定義角色責任、決策權限、交接規則與值班補位流程。事故結束後應回看決策時間線，調整角色設計與授權邊界。&lt;/p></description><content:encoded><![CDATA[<p>Incident command system 的核心概念是「事故期間由明確角色統一決策與分工」。它把指揮、操作、溝通與紀錄拆開，降低多人同時決策造成的混亂。 可先對照 <a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>指揮系統連接 <a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity</a>、<a href="/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy</a> 與 <a href="/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline</a>。常見角色包括 incident commander、technical owner、communication owner 與 scribe。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要指揮系統的訊號是事故期間同時出現多個聊天室與多個口頭指令。若沒有單一指揮窗口，團隊容易同時做出互相衝突的切換與回滾。</p>
<h2 id="設計責任">設計責任</h2>
<p>指揮系統要定義角色責任、決策權限、交接規則與值班補位流程。事故結束後應回看決策時間線，調整角色設計與授權邊界。</p>
]]></content:encoded></item><item><title>Service Discovery</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/service-discovery/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/service-discovery/</guid><description>&lt;p>Service discovery 的核心概念是「讓呼叫端根據 registry 或 DNS 找到目前可用的服務實例」。它支援擴容、滾動更新與故障切換。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>常與 &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>、load balancer、健康檢查與部署平台整合，決定流量如何導向健康節點。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義查找條件、轉譯規則與回復條件，避免流量導向未準備好的實例。&lt;/p></description><content:encoded><![CDATA[<p>Service discovery 的核心概念是「讓呼叫端根據 registry 或 DNS 找到目前可用的服務實例」。它支援擴容、滾動更新與故障切換。 可先對照 <a href="/blog/backend/knowledge-cards/service-registry/" data-link-title="Service Registry" data-link-desc="說明服務實例如何被註冊、維護與摘除">Service Registry</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>常與 <a href="/blog/backend/knowledge-cards/service-registry/" data-link-title="Service Registry" data-link-desc="說明服務實例如何被註冊、維護與摘除">Service Registry</a>、load balancer、健康檢查與部署平台整合，決定流量如何導向健康節點。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義查找條件、轉譯規則與回復條件，避免流量導向未準備好的實例。</p>
]]></content:encoded></item><item><title>Config Rollout</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/config-rollout/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/config-rollout/</guid><description>&lt;p>Config Rollout 的核心概念是「把設定變更從程式部署中分離，並以可控方式送到正在運作的服務」。它處理的是設定版本、下發節奏、回復方式與觀察驗證，不是單純修改一個環境變數值。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Config Rollout 位在 configuration source、deployment platform 與 running instances 之間。它通常與 service discovery、container runtime、feature flag、secret management 或配置中心一起出現。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 config rollout 的訊號是：&lt;/p>
&lt;ul>
&lt;li>同一版程式要搭配不同環境設定&lt;/li>
&lt;li>設定變更可能影響流量、權限或依賴連線&lt;/li>
&lt;li>希望設定可以分批驗證與回復&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>新增下游 endpoint、切換第三方金鑰、調整 feature flag、更新來源白名單或變更 retry policy，都屬於 config rollout 問題。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義設定來源、分發順序、驗證方式、回復方式與影響範圍。Config Rollout 應該讓設定變更可預測，而不是把風險藏在部署流程裡。&lt;/p></description><content:encoded><![CDATA[<p>Config Rollout 的核心概念是「把設定變更從程式部署中分離，並以可控方式送到正在運作的服務」。它處理的是設定版本、下發節奏、回復方式與觀察驗證，不是單純修改一個環境變數值。 可先對照 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Config Rollout 位在 configuration source、deployment platform 與 running instances 之間。它通常與 service discovery、container runtime、feature flag、secret management 或配置中心一起出現。 可先對照 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 config rollout 的訊號是：</p>
<ul>
<li>同一版程式要搭配不同環境設定</li>
<li>設定變更可能影響流量、權限或依賴連線</li>
<li>希望設定可以分批驗證與回復</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>新增下游 endpoint、切換第三方金鑰、調整 feature flag、更新來源白名單或變更 retry policy，都屬於 config rollout 問題。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義設定來源、分發順序、驗證方式、回復方式與影響範圍。Config Rollout 應該讓設定變更可預測，而不是把風險藏在部署流程裡。</p>
]]></content:encoded></item><item><title>Service Registry</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/service-registry/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/service-registry/</guid><description>&lt;p>Service Registry 的核心概念是「保存目前可用服務實例的位址、狀態與 metadata，供 discovery、load balancer 或內部呼叫查找」。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/session-invalidation/" data-link-title="Session Invalidation" data-link-desc="說明事件後如何讓既有會話失效，避免被重放或延續利用">Session Invalidation&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Service Registry 位在 deployment platform、health check、service discovery 與 load balancing 之間。它負責維持「目前有哪些實例可用」這份資料。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/session-invalidation/" data-link-title="Session Invalidation" data-link-desc="說明事件後如何讓既有會話失效，避免被重放或延續利用">Session Invalidation&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 service registry 的訊號是：&lt;/p>
&lt;ul>
&lt;li>服務實例會動態擴縮&lt;/li>
&lt;li>instance 需要在啟動後自動登錄&lt;/li>
&lt;li>instance 失效時要自動摘除&lt;/li>
&lt;li>呼叫端需要依據 metadata 找到合適實例&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>Kubernetes 會把 pod、labels 與 endpoint 維持成可查找狀態；service mesh 會用 registry 資料決定流量要導向哪個 instance；服務縮容時若 registry 沒有及時摘除舊實例，呼叫端就可能打到已下線節點。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Service Registry 要定義註冊來源、heartbeat 或 TTL、失效摘除條件、metadata 結構與回復方式。它的重點是讓查找方拿到可信且更新的實例資料。&lt;/p></description><content:encoded><![CDATA[<p>Service Registry 的核心概念是「保存目前可用服務實例的位址、狀態與 metadata，供 discovery、load balancer 或內部呼叫查找」。 可先對照 <a href="/blog/backend/knowledge-cards/session-invalidation/" data-link-title="Session Invalidation" data-link-desc="說明事件後如何讓既有會話失效，避免被重放或延續利用">Session Invalidation</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Service Registry 位在 deployment platform、health check、service discovery 與 load balancing 之間。它負責維持「目前有哪些實例可用」這份資料。 可先對照 <a href="/blog/backend/knowledge-cards/session-invalidation/" data-link-title="Session Invalidation" data-link-desc="說明事件後如何讓既有會話失效，避免被重放或延續利用">Session Invalidation</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 service registry 的訊號是：</p>
<ul>
<li>服務實例會動態擴縮</li>
<li>instance 需要在啟動後自動登錄</li>
<li>instance 失效時要自動摘除</li>
<li>呼叫端需要依據 metadata 找到合適實例</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>Kubernetes 會把 pod、labels 與 endpoint 維持成可查找狀態；service mesh 會用 registry 資料決定流量要導向哪個 instance；服務縮容時若 registry 沒有及時摘除舊實例，呼叫端就可能打到已下線節點。</p>
<h2 id="設計責任">設計責任</h2>
<p>Service Registry 要定義註冊來源、heartbeat 或 TTL、失效摘除條件、metadata 結構與回復方式。它的重點是讓查找方拿到可信且更新的實例資料。</p>
]]></content:encoded></item><item><title>Escalation Policy</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/escalation-policy/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/escalation-policy/</guid><description>&lt;p>Escalation policy 的核心概念是「在指定時間內把未解決事故交給下一層責任角色」。它確保事故在無回應或無進展時自動升級，而不是停在單一值班人員。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>升級策略是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity&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/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">incident command system&lt;/a> 一起運作。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 escalation policy 的訊號是高嚴重度告警在深夜長時間無回應。付款 API 中斷若 10 分鐘內沒有確認接手，應自動升級到下一層 on-call 與 incident commander。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>升級策略要定義回應時限、升級路徑、通知通道、交接內容與最終責任人。策略要定期演練，確認通訊資訊與值班名單有效。&lt;/p></description><content:encoded><![CDATA[<p>Escalation policy 的核心概念是「在指定時間內把未解決事故交給下一層責任角色」。它確保事故在無回應或無進展時自動升級，而不是停在單一值班人員。 可先對照 <a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>升級策略是 <a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity</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/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">incident command system</a> 一起運作。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 escalation policy 的訊號是高嚴重度告警在深夜長時間無回應。付款 API 中斷若 10 分鐘內沒有確認接手，應自動升級到下一層 on-call 與 incident commander。</p>
<h2 id="設計責任">設計責任</h2>
<p>升級策略要定義回應時限、升級路徑、通知通道、交接內容與最終責任人。策略要定期演練，確認通訊資訊與值班名單有效。</p>
]]></content:encoded></item><item><title>Handover Protocol</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/handover-protocol/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/handover-protocol/</guid><description>&lt;p>Handover protocol 的核心概念是「把事故或值班責任從一個人或一組人，完整、安全地轉到下一個接手者」。它的責任是確認目前狀態、未完成事項、風險與下一步，單純通知誰接手只完成了形式。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Handover protocol 位在 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">incident command system&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy&lt;/a> 之間。它承接角色切換、班次結束與事故升級時的資訊交接。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 handover protocol 的訊號是：事故已經持續一段時間、原本負責的人要下班、或指揮權需要轉給下一位。若沒有明確交接，常見問題是重複排查、遺漏已嘗試過的措施，或對下一步有不同理解。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Handover protocol 要明確包含當前狀態、已知事實、已嘗試動作、阻塞點、下一個檢查時間、對外溝通狀態與接手確認。交接完成前，責任歸屬應保持單一，不要同時存在多個實際決策者。&lt;/p></description><content:encoded><![CDATA[<p>Handover protocol 的核心概念是「把事故或值班責任從一個人或一組人，完整、安全地轉到下一個接手者」。它的責任是確認目前狀態、未完成事項、風險與下一步，單純通知誰接手只完成了形式。 可先對照 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">On-Call</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Handover protocol 位在 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a>、<a href="/blog/backend/knowledge-cards/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">incident command system</a> 與 <a href="/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy</a> 之間。它承接角色切換、班次結束與事故升級時的資訊交接。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 handover protocol 的訊號是：事故已經持續一段時間、原本負責的人要下班、或指揮權需要轉給下一位。若沒有明確交接，常見問題是重複排查、遺漏已嘗試過的措施，或對下一步有不同理解。</p>
<h2 id="設計責任">設計責任</h2>
<p>Handover protocol 要明確包含當前狀態、已知事實、已嘗試動作、阻塞點、下一個檢查時間、對外溝通狀態與接手確認。交接完成前，責任歸屬應保持單一，不要同時存在多個實際決策者。</p>
]]></content:encoded></item><item><title>Rolling Update</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/rolling-update/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/rolling-update/</guid><description>&lt;p>Rolling update 的核心概念是「逐批替換舊版本實例，維持服務持續可用」。它可降低一次性切換風險。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>常搭配 &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/service-discovery/" data-link-title="Service Discovery" data-link-desc="說明服務實例如何被查找與路由">service discovery&lt;/a>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義每批比例、健康檢查門檻、回滾條件與流量切換節奏。&lt;/p></description><content:encoded><![CDATA[<p>Rolling update 的核心概念是「逐批替換舊版本實例，維持服務持續可用」。它可降低一次性切換風險。 可先對照 <a href="/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">Readiness</a>。</p>
<h2 id="概念位置">概念位置</h2>
<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/graceful-shutdown/" data-link-title="Graceful Shutdown" data-link-desc="說明服務停止前如何排空流量、完成工作與保存狀態">graceful shutdown</a> 與 <a href="/blog/backend/knowledge-cards/service-discovery/" data-link-title="Service Discovery" data-link-desc="說明服務實例如何被查找與路由">service discovery</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義每批比例、健康檢查門檻、回滾條件與流量切換節奏。</p>
]]></content:encoded></item><item><title>Incident Timeline</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/</guid><description>&lt;p>Incident timeline 的核心概念是「按時間順序記錄事故中的觀測、決策與操作」。時間線是事故的共同事實來源，連接 &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/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review&lt;/a> 復盤，讓團隊可以對齊發生順序與影響變化。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Timeline 連接 &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/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call&lt;/a> 回應（何時開始處理）、操作紀錄（做了什麼）、影響變化（使用者影響何時改善 / 惡化）跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review&lt;/a>（復盤時重建因果鏈）。&lt;/p>
&lt;p>Timeline 也是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a> 的時間軸基礎 — decision log 記錄「在這個時間點、基於這個觀測、做了這個決策」，timeline 提供「這個時間點」的上下文。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 incident timeline 的訊號是事故後大家對「先發生什麼」說法不同。若沒有一致時間軸，復盤時很難判斷哪個操作真正帶來改善、哪個決策在當時是合理的。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Timeline 要包含時間戳（UTC、精確到分鐘）、訊號來源（哪個 &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> / 人為觀察）、操作內容（restart / rollback / scale）、決策理由與結果驗證。記錄方式應簡潔且可在高壓下維持更新 — 事故中寫 timeline 的成本太高會導致沒人寫。Slack channel pinned message 或事故管理工具的自動 timeline 是常見實作。&lt;/p></description><content:encoded><![CDATA[<p>Incident timeline 的核心概念是「按時間順序記錄事故中的觀測、決策與操作」。時間線是事故的共同事實來源，連接 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 觸發到 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review</a> 復盤，讓團隊可以對齊發生順序與影響變化。</p>
<h2 id="概念位置">概念位置</h2>
<p>Timeline 連接 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 觸發（事故何時被偵測到）、<a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a> 回應（何時開始處理）、操作紀錄（做了什麼）、影響變化（使用者影響何時改善 / 惡化）跟 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review</a>（復盤時重建因果鏈）。</p>
<p>Timeline 也是 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a> 的時間軸基礎 — decision log 記錄「在這個時間點、基於這個觀測、做了這個決策」，timeline 提供「這個時間點」的上下文。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 incident timeline 的訊號是事故後大家對「先發生什麼」說法不同。若沒有一致時間軸，復盤時很難判斷哪個操作真正帶來改善、哪個決策在當時是合理的。</p>
<h2 id="設計責任">設計責任</h2>
<p>Timeline 要包含時間戳（UTC、精確到分鐘）、訊號來源（哪個 <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> / 人為觀察）、操作內容（restart / rollback / scale）、決策理由與結果驗證。記錄方式應簡潔且可在高壓下維持更新 — 事故中寫 timeline 的成本太高會導致沒人寫。Slack channel pinned message 或事故管理工具的自動 timeline 是常見實作。</p>
]]></content:encoded></item><item><title>Runtime Config</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/runtime-config/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/runtime-config/</guid><description>&lt;p>Runtime Config 的核心概念是「服務在執行時需要哪些設定，以及這些設定如何被讀取、預設與覆寫」。它處理的是設定來源與組合規則，不是設定發送流程本身。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="說明觀測資料如何抽樣以控制成本並保留診斷能力">Sampling&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Runtime Config 位在 environment variable、config file、secret injection、feature flag 與 application startup 之間。它決定服務如何取得執行所需的參數與開關。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="說明觀測資料如何抽樣以控制成本並保留診斷能力">Sampling&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 runtime config 的訊號是：&lt;/p>
&lt;ul>
&lt;li>不同環境要使用不同參數&lt;/li>
&lt;li>某些值必須由部署平台或 secret management 注入&lt;/li>
&lt;li>服務需要可預期的預設值與覆寫順序&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>資料庫連線字串、第三方 API base URL、限制值、路由開關與功能旗標，都屬於 runtime config 的一部分。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義設定來源優先序、缺值行為、型別驗證、啟動失敗條件與是否允許動態更新。Runtime Config 應該讓服務在不同環境中保持一致的配置語意。&lt;/p></description><content:encoded><![CDATA[<p>Runtime Config 的核心概念是「服務在執行時需要哪些設定，以及這些設定如何被讀取、預設與覆寫」。它處理的是設定來源與組合規則，不是設定發送流程本身。 可先對照 <a href="/blog/backend/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="說明觀測資料如何抽樣以控制成本並保留診斷能力">Sampling</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Runtime Config 位在 environment variable、config file、secret injection、feature flag 與 application startup 之間。它決定服務如何取得執行所需的參數與開關。 可先對照 <a href="/blog/backend/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="說明觀測資料如何抽樣以控制成本並保留診斷能力">Sampling</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 runtime config 的訊號是：</p>
<ul>
<li>不同環境要使用不同參數</li>
<li>某些值必須由部署平台或 secret management 注入</li>
<li>服務需要可預期的預設值與覆寫順序</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>資料庫連線字串、第三方 API base URL、限制值、路由開關與功能旗標，都屬於 runtime config 的一部分。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義設定來源優先序、缺值行為、型別驗證、啟動失敗條件與是否允許動態更新。Runtime Config 應該讓服務在不同環境中保持一致的配置語意。</p>
]]></content:encoded></item><item><title>Autoscaling</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/autoscaling/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/autoscaling/</guid><description>&lt;p>Autoscaling 的核心概念是「依指標自動調整容量」。它適合吸收流量波動，但不是可靠性保證本身。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">Backfill&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>常使用 CPU、QPS、queue lag 或自訂業務指標作為擴縮容條件。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">Backfill&lt;/a>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義擴縮容門檻、冷啟動成本、最小/最大實例與保護策略，避免擴縮容震盪。&lt;/p></description><content:encoded><![CDATA[<p>Autoscaling 的核心概念是「依指標自動調整容量」。它適合吸收流量波動，但不是可靠性保證本身。 可先對照 <a href="/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">Backfill</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>常使用 CPU、QPS、queue lag 或自訂業務指標作為擴縮容條件。 可先對照 <a href="/blog/backend/knowledge-cards/backfill/" data-link-title="Backfill" data-link-desc="說明如何為既有資料補上新欄位、新索引或新衍生狀態">Backfill</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義擴縮容門檻、冷啟動成本、最小/最大實例與保護策略，避免擴縮容震盪。</p>
]]></content:encoded></item><item><title>Blast Radius</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/</guid><description>&lt;p>Blast radius 的核心概念是「估算故障可擴散到哪些服務、資料與使用者」。它幫助團隊在事故早期決定先隔離哪個邊界，避免影響持續擴大。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">Degradation&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Blast radius 與 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback-strategy&lt;/a> 密切相關。影響面判斷會直接改變事故分級與處置策略。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 blast radius 判斷的訊號是單點異常開始波及更多路徑。某個推薦服務超時最初只影響商品頁，若重試策略失控，可能進一步拖慢共用 database 與 checkout 路徑。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>影響面設計要標出依賴拓撲、共享資源與隔離手段。事故期間應持續更新影響面估算，並把結果同步到指揮與通訊流程。&lt;/p></description><content:encoded><![CDATA[<p>Blast radius 的核心概念是「估算故障可擴散到哪些服務、資料與使用者」。它幫助團隊在事故早期決定先隔離哪個邊界，避免影響持續擴大。 可先對照 <a href="/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">Degradation</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Blast radius 與 <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> 與 <a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback-strategy</a> 密切相關。影響面判斷會直接改變事故分級與處置策略。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 blast radius 判斷的訊號是單點異常開始波及更多路徑。某個推薦服務超時最初只影響商品頁，若重試策略失控，可能進一步拖慢共用 database 與 checkout 路徑。</p>
<h2 id="設計責任">設計責任</h2>
<p>影響面設計要標出依賴拓撲、共享資源與隔離手段。事故期間應持續更新影響面估算，並把結果同步到指揮與通訊流程。</p>
]]></content:encoded></item><item><title>Feature Flag</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/feature-flag/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/feature-flag/</guid><description>&lt;p>Feature flag 的核心概念是「把功能啟用控制與部署分離」。它可用於灰度發布、A/B 測試與緊急關閉。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/full-text-search/" data-link-title="Full-Text Search" data-link-desc="說明全文檢索如何處理關鍵字匹配、語言分析與排序">Full-Text Search&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>常出現在高風險功能、實驗功能與跨租戶差異化控制。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/full-text-search/" data-link-title="Full-Text Search" data-link-desc="說明全文檢索如何處理關鍵字匹配、語言分析與排序">Full-Text Search&lt;/a>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義旗標生命週期、預設值、回退策略與清理節點，避免旗標長期堆積。&lt;/p></description><content:encoded><![CDATA[<p>Feature flag 的核心概念是「把功能啟用控制與部署分離」。它可用於灰度發布、A/B 測試與緊急關閉。 可先對照 <a href="/blog/backend/knowledge-cards/full-text-search/" data-link-title="Full-Text Search" data-link-desc="說明全文檢索如何處理關鍵字匹配、語言分析與排序">Full-Text Search</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>常出現在高風險功能、實驗功能與跨租戶差異化控制。 可先對照 <a href="/blog/backend/knowledge-cards/full-text-search/" data-link-title="Full-Text Search" data-link-desc="說明全文檢索如何處理關鍵字匹配、語言分析與排序">Full-Text Search</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義旗標生命週期、預設值、回退策略與清理節點，避免旗標長期堆積。</p>
]]></content:encoded></item><item><title>Incident Communication Channel</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/incident-communication-channel/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/incident-communication-channel/</guid><description>&lt;p>Incident communication channel 的核心概念是「事故期間用固定通道承接對內同步、對外公告與跨角色協作」。它關心的是誰在什麼通道收到什麼資訊，而不是技術傳輸格式。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">Incident Command System&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Incident communication channel 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">incident command system&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline&lt;/a> 與對外通知流程之間。它讓指揮者、執行者、利害關係人與客服能在同一節奏上更新狀態。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 incident communication channel 的訊號是事故時資訊散落在多個聊天群、會議室與郵件串，導致外部說法不一致。常見例子包括內部 war room、對外 status update、客服同步與管理層簡報。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Incident communication channel 要定義主要通道、備援通道、更新頻率、對象分層與發言權限。對外公告不應和內部推進混在同一個通道，避免把未確認資訊直接擴散出去。&lt;/p></description><content:encoded><![CDATA[<p>Incident communication channel 的核心概念是「事故期間用固定通道承接對內同步、對外公告與跨角色協作」。它關心的是誰在什麼通道收到什麼資訊，而不是技術傳輸格式。 可先對照 <a href="/blog/backend/knowledge-cards/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">Incident Command System</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Incident communication channel 位在 <a href="/blog/backend/knowledge-cards/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">incident command system</a>、<a href="/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline</a> 與對外通知流程之間。它讓指揮者、執行者、利害關係人與客服能在同一節奏上更新狀態。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 incident communication channel 的訊號是事故時資訊散落在多個聊天群、會議室與郵件串，導致外部說法不一致。常見例子包括內部 war room、對外 status update、客服同步與管理層簡報。</p>
<h2 id="設計責任">設計責任</h2>
<p>Incident communication channel 要定義主要通道、備援通道、更新頻率、對象分層與發言權限。對外公告不應和內部推進混在同一個通道，避免把未確認資訊直接擴散出去。</p>
]]></content:encoded></item><item><title>Rollback Strategy</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/</guid><description>&lt;p>Rollback strategy 的核心概念是「在事故期間用可驗證條件決定是否回滾」。回滾是根據影響面、資料風險與回復速度做出的風險控制決策，當成預設答案會忽略回滾本身的代價。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>回滾策略連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">cutover / switchover&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">fallback plan&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal&lt;/a> 驗證。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 rollback strategy 的訊號是新版本上線後出現錯誤率上升。若回滾可在 5 分鐘內顯著降低使用者影響，通常優先回滾，再在低風險環境分析根因。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>回滾策略要定義觸發條件、資料相容性檢查、回滾步驟、停止條件與回滾後驗證。高風險變更應在發版前先演練回滾流程。&lt;/p></description><content:encoded><![CDATA[<p>Rollback strategy 的核心概念是「在事故期間用可驗證條件決定是否回滾」。回滾是根據影響面、資料風險與回復速度做出的風險控制決策，當成預設答案會忽略回滾本身的代價。 可先對照 <a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>回滾策略連接 <a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity</a>、<a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius</a>、<a href="/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">cutover / switchover</a> 與 <a href="/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">fallback plan</a>；是否放行變更則會受 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a> 影響，而實際可行性則應由 <a href="/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal</a> 驗證。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 rollback strategy 的訊號是新版本上線後出現錯誤率上升。若回滾可在 5 分鐘內顯著降低使用者影響，通常優先回滾，再在低風險環境分析根因。</p>
<h2 id="設計責任">設計責任</h2>
<p>回滾策略要定義觸發條件、資料相容性檢查、回滾步驟、停止條件與回滾後驗證。高風險變更應在發版前先演練回滾流程。</p>
]]></content:encoded></item><item><title>Webhook</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/</guid><description>&lt;p>Webhook 的核心概念是「外部系統主動把事件推送到你的 endpoint」。它常用於支付、物流、第三方整合通知。 可先對照 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Webhook 通常需要來源驗證、重放防護、重試處理與可追蹤事件 ID。 可先對照 &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>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義簽章驗證、時窗限制、冪等處理與錯誤回應策略，避免假請求或重放造成狀態錯誤。&lt;/p></description><content:encoded><![CDATA[<p>Webhook 的核心概念是「外部系統主動把事件推送到你的 endpoint」。它常用於支付、物流、第三方整合通知。 可先對照 <a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">Website Certificate Lifecycle</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Webhook 通常需要來源驗證、重放防護、重試處理與可追蹤事件 ID。 可先對照 <a href="/blog/backend/knowledge-cards/website-certificate-lifecycle/" data-link-title="Website Certificate Lifecycle" data-link-desc="說明網站 TLS 憑證從簽發到續期與撤銷的全流程責任">Website Certificate Lifecycle</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義簽章驗證、時窗限制、冪等處理與錯誤回應策略，避免假請求或重放造成狀態錯誤。</p>
]]></content:encoded></item><item><title>Rollback Window</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-window/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-window/</guid><description>&lt;p>Rollback window 的核心概念是「變更進入 production 後，仍能用特定方式回退或改路線的有效窗口」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback strategy&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate&lt;/a>，讓 gate 能判斷目前還剩哪種退路。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Rollback window 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">cutover / switchover&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">fallback plan&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a> 之間。Rollback strategy 說明回退決策，rollback window 說明這個決策在目前階段是否仍可執行。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 rollback window 的訊號是：&lt;/p>
&lt;ul>
&lt;li>expand、backfill、cutover、contract 每一階段的回退方式不同&lt;/li>
&lt;li>舊版本或舊資料語意只能支撐一段時間&lt;/li>
&lt;li>cutover 後仍可 fallback read，但 contract 後只能資料修復或 fail-forward&lt;/li>
&lt;li>release gate 要判斷是否還能安全暫停或回退&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>資料庫 migration 在 expand 階段通常能回到舊讀取；backfill 階段可以暫停與重跑；cutover 後可回到 fallback read；contract 移除舊欄位後，回退會轉成資料修補或 fail-forward。這些差異都屬於 rollback window。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Rollback window 要寫清楚目前階段、可用回退方式、最後可回退時間、資料相容性限制與 owner。它要進入 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a>，避免事故期間把已經關閉的退路當成可用選項。&lt;/p></description><content:encoded><![CDATA[<p>Rollback window 的核心概念是「變更進入 production 後，仍能用特定方式回退或改路線的有效窗口」。它連接 <a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback strategy</a>、<a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">release gate</a> 與 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate</a>，讓 gate 能判斷目前還剩哪種退路。</p>
<h2 id="概念位置">概念位置</h2>
<p>Rollback window 位在 <a href="/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">cutover / switchover</a>、<a href="/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">fallback plan</a> 與 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a> 之間。Rollback strategy 說明回退決策，rollback window 說明這個決策在目前階段是否仍可執行。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 rollback window 的訊號是：</p>
<ul>
<li>expand、backfill、cutover、contract 每一階段的回退方式不同</li>
<li>舊版本或舊資料語意只能支撐一段時間</li>
<li>cutover 後仍可 fallback read，但 contract 後只能資料修復或 fail-forward</li>
<li>release gate 要判斷是否還能安全暫停或回退</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>資料庫 migration 在 expand 階段通常能回到舊讀取；backfill 階段可以暫停與重跑；cutover 後可回到 fallback read；contract 移除舊欄位後，回退會轉成資料修補或 fail-forward。這些差異都屬於 rollback window。</p>
<h2 id="設計責任">設計責任</h2>
<p>Rollback window 要寫清楚目前階段、可用回退方式、最後可回退時間、資料相容性限制與 owner。它要進入 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">release gate</a> 與 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a>，避免事故期間把已經關閉的退路當成可用選項。</p>
]]></content:encoded></item><item><title>Rollback Rehearsal</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-rehearsal/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-rehearsal/</guid><description>&lt;p>Rollback Rehearsal 的核心概念是「在低風險環境實際走一次回滾流程，確認步驟、權限與耗時都符合預期」。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">Rollback Strategy&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Rollback Rehearsal 位在 release gate、rollback strategy、migration 與 disaster recovery 之間。它是把回滾步驟實際走過一次的演練，文件審查無法替代實機驗證。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">Rollback Strategy&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 rollback rehearsal 的訊號是：&lt;/p>
&lt;ul>
&lt;li>變更失敗時回復速度會直接影響使用者影響&lt;/li>
&lt;li>團隊不確定回滾步驟是否真的可執行&lt;/li>
&lt;li>高風險 migration 或 release 會同時影響資料與流量&lt;/li>
&lt;li>權限、腳本、順序或相容性可能成為回復瓶頸&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>資料表結構變更前先在接近正式環境演練 rollback，可以確認舊欄位是否還能恢復、資料補回是否可逆、以及切回舊版本後是否還能接流量。服務替換前做 rollback rehearsal，也能驗證 DNS、load balancer 與設定切換的回復時間。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Rollback Rehearsal 要定義環境、資料範圍、演練步驟、驗證項目與紀錄方式。演練的重點是找出「看似可回滾、實際回不去」的缺口。&lt;/p></description><content:encoded><![CDATA[<p>Rollback Rehearsal 的核心概念是「在低風險環境實際走一次回滾流程，確認步驟、權限與耗時都符合預期」。 可先對照 <a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">Rollback Strategy</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Rollback Rehearsal 位在 release gate、rollback strategy、migration 與 disaster recovery 之間。它是把回滾步驟實際走過一次的演練，文件審查無法替代實機驗證。 可先對照 <a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">Rollback Strategy</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 rollback rehearsal 的訊號是：</p>
<ul>
<li>變更失敗時回復速度會直接影響使用者影響</li>
<li>團隊不確定回滾步驟是否真的可執行</li>
<li>高風險 migration 或 release 會同時影響資料與流量</li>
<li>權限、腳本、順序或相容性可能成為回復瓶頸</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>資料表結構變更前先在接近正式環境演練 rollback，可以確認舊欄位是否還能恢復、資料補回是否可逆、以及切回舊版本後是否還能接流量。服務替換前做 rollback rehearsal，也能驗證 DNS、load balancer 與設定切換的回復時間。</p>
<h2 id="設計責任">設計責任</h2>
<p>Rollback Rehearsal 要定義環境、資料範圍、演練步驟、驗證項目與紀錄方式。演練的重點是找出「看似可回滾、實際回不去」的缺口。</p>
]]></content:encoded></item><item><title>BFF</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/bff/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/bff/</guid><description>&lt;p>BFF 的核心概念是「為特定前端體驗提供專用後端聚合層」。它可降低前端多次呼叫與資料拼裝成本。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">Blast Radius&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>常見於 Web 與 App 需求差異明顯時，BFF 會整合多個下游 API 並回傳前端所需形狀。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">Blast Radius&lt;/a>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義聚合邊界、快取策略、超時控制與降級策略，避免單一 BFF 成為新瓶頸。&lt;/p></description><content:encoded><![CDATA[<p>BFF 的核心概念是「為特定前端體驗提供專用後端聚合層」。它可降低前端多次呼叫與資料拼裝成本。 可先對照 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">Blast Radius</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>常見於 Web 與 App 需求差異明顯時，BFF 會整合多個下游 API 並回傳前端所需形狀。 可先對照 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">Blast Radius</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義聚合邊界、快取策略、超時控制與降級策略，避免單一 BFF 成為新瓶頸。</p>
]]></content:encoded></item><item><title>Post-Incident Review</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/</guid><description>&lt;p>Post-incident review 的核心概念是「事故後把事實、原因與改進行動整理成可驗證輸出」。它的目標是提升系統與流程，不是追究個人。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">Incident Timeline&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>復盤連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline&lt;/a>、&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/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a> 更新。它也是可靠性改進與工程優先序調整的輸入來源。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要復盤流程的訊號是同類事故反覆發生。若每次都只做當下修補，沒有形成結構化改進，事故頻率通常不會下降。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>復盤要包含影響摘要、時間線、根因、有效措施、無效措施、行動項與驗證期限。行動項需要指定 owner 與完成標準，避免停在會議紀錄。&lt;/p></description><content:encoded><![CDATA[<p>Post-incident review 的核心概念是「事故後把事實、原因與改進行動整理成可驗證輸出」。它的目標是提升系統與流程，不是追究個人。 可先對照 <a href="/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">Incident Timeline</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>復盤連接 <a href="/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline</a>、<a href="/blog/backend/knowledge-cards/rca/" data-link-title="RCA" data-link-desc="說明根因分析如何區分觸發事件、系統弱點與防線缺口">rca</a> 與 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 更新。它也是可靠性改進與工程優先序調整的輸入來源。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要復盤流程的訊號是同類事故反覆發生。若每次都只做當下修補，沒有形成結構化改進，事故頻率通常不會下降。</p>
<h2 id="設計責任">設計責任</h2>
<p>復盤要包含影響摘要、時間線、根因、有效措施、無效措施、行動項與驗證期限。行動項需要指定 owner 與完成標準，避免停在會議紀錄。</p>
]]></content:encoded></item><item><title>Fail-forward</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/fail-forward/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/fail-forward/</guid><description>&lt;p>Fail-forward 的核心概念是「當回退代價高於前進修復時，用受控方式往新狀態完成修復」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback strategy&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">fallback plan&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a>，不是忽略失敗繼續推進。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Fail-forward 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback window&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/containment/" data-link-title="Containment" data-link-desc="說明事故處理中如何限制擴散面，為回復與驗證爭取時間">containment&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review&lt;/a> 之間。Rollback window 關閉後，團隊仍需要一條能限制影響、補資料、完成相容收斂的前進路線。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 fail-forward 的訊號是：&lt;/p>
&lt;ul>
&lt;li>舊資料語意已被 contract 或不可逆寫入移除&lt;/li>
&lt;li>回退會造成更大的資料不一致或客戶影響&lt;/li>
&lt;li>新路徑有明確修補方案、停損條件與 owner&lt;/li>
&lt;li>事故 decision log 需要記錄為何不回滾&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>資料庫 migration 已完成 contract 後，舊欄位被移除，回到舊版本會讓讀取路徑失效。此時比較可控的做法可能是暫停部分寫入、修補 mismatch、補 validation query，再讓新路徑收斂到可用狀態。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Fail-forward 要定義 containment、修補步驟、預期效果、停止條件與回寫項目。它要搭配 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/action-item-closure/" data-link-title="Action Item Closure" data-link-desc="說明事故行動項如何被驗證完成，而不是只停留在待辦清單">action item closure&lt;/a>，避免「不能回滾」被誤用成沒有證據的硬推。&lt;/p></description><content:encoded><![CDATA[<p>Fail-forward 的核心概念是「當回退代價高於前進修復時，用受控方式往新狀態完成修復」。它連接 <a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback strategy</a>、<a href="/blog/backend/knowledge-cards/fallback-plan/" data-link-title="Fallback Plan" data-link-desc="說明變更失敗時如何回到可接受狀態">fallback plan</a> 與 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a>，不是忽略失敗繼續推進。</p>
<h2 id="概念位置">概念位置</h2>
<p>Fail-forward 位在 <a href="/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback window</a>、<a href="/blog/backend/knowledge-cards/containment/" data-link-title="Containment" data-link-desc="說明事故處理中如何限制擴散面，為回復與驗證爭取時間">containment</a> 與 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review</a> 之間。Rollback window 關閉後，團隊仍需要一條能限制影響、補資料、完成相容收斂的前進路線。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 fail-forward 的訊號是：</p>
<ul>
<li>舊資料語意已被 contract 或不可逆寫入移除</li>
<li>回退會造成更大的資料不一致或客戶影響</li>
<li>新路徑有明確修補方案、停損條件與 owner</li>
<li>事故 decision log 需要記錄為何不回滾</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>資料庫 migration 已完成 contract 後，舊欄位被移除，回到舊版本會讓讀取路徑失效。此時比較可控的做法可能是暫停部分寫入、修補 mismatch、補 validation query，再讓新路徑收斂到可用狀態。</p>
<h2 id="設計責任">設計責任</h2>
<p>Fail-forward 要定義 containment、修補步驟、預期效果、停止條件與回寫項目。它要搭配 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a> 與 <a href="/blog/backend/knowledge-cards/action-item-closure/" data-link-title="Action Item Closure" data-link-desc="說明事故行動項如何被驗證完成，而不是只停留在待辦清單">action item closure</a>，避免「不能回滾」被誤用成沒有證據的硬推。</p>
]]></content:encoded></item><item><title>CI Pipeline</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/ci-pipeline/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/ci-pipeline/</guid><description>&lt;p>CI pipeline 的核心概念是「在變更合併前自動執行檢查與測試」。它把品質門檻前移，降低上線風險。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>常包含編譯、單元測試、靜態檢查、契約驗證與安全檢查。 可先對照 &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;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義必要 gate、失敗回饋與執行時間上限，避免流程形同形式或過慢。&lt;/p></description><content:encoded><![CDATA[<p>CI pipeline 的核心概念是「在變更合併前自動執行檢查與測試」。它把品質門檻前移，降低上線風險。 可先對照 <a href="/blog/backend/knowledge-cards/circuit-breaker/" data-link-title="Circuit Breaker" data-link-desc="說明下游持續失敗時如何暫停呼叫並保護系統">Circuit Breaker</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>常包含編譯、單元測試、靜態檢查、契約驗證與安全檢查。 可先對照 <a href="/blog/backend/knowledge-cards/circuit-breaker/" data-link-title="Circuit Breaker" data-link-desc="說明下游持續失敗時如何暫停呼叫並保護系統">Circuit Breaker</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義必要 gate、失敗回饋與執行時間上限，避免流程形同形式或過慢。</p>
]]></content:encoded></item><item><title>RCA</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/rca/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/rca/</guid><description>&lt;p>RCA 的核心概念是「找出事故能發生的系統性原因」。它區分 trigger、contributing factors 與 control gaps，避免把單一操作失誤當成唯一答案。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">Post-Incident Review&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>RCA 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review&lt;/a> 的分析骨架，並和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline&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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 RCA 的訊號是事故說明只停在「某人操作錯誤」。更完整的分析通常還包含告警門檻不足、權限設計過寬、回滾流程不清楚等系統層因素。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>RCA 要建立證據鏈、假設邊界與可驗證改進。分析結果應轉成具體行動項，並與後續演練或測試串接。&lt;/p></description><content:encoded><![CDATA[<p>RCA 的核心概念是「找出事故能發生的系統性原因」。它區分 trigger、contributing factors 與 control gaps，避免把單一操作失誤當成唯一答案。 可先對照 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">Post-Incident Review</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>RCA 是 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review</a> 的分析骨架，並和 <a href="/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline</a> 與 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 改進連動。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 RCA 的訊號是事故說明只停在「某人操作錯誤」。更完整的分析通常還包含告警門檻不足、權限設計過寬、回滾流程不清楚等系統層因素。</p>
<h2 id="設計責任">設計責任</h2>
<p>RCA 要建立證據鏈、假設邊界與可驗證改進。分析結果應轉成具體行動項，並與後續演練或測試串接。</p>
]]></content:encoded></item><item><title>Stop Condition</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/stop-condition/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/stop-condition/</guid><description>&lt;p>Stop condition 的核心概念是「事前定義何時必須暫停、回退或改路線」。它連接 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback strategy&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a>，避免團隊在壓力下用感覺決定是否繼續。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Stop condition 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-window/" data-link-title="Cutover Window" data-link-desc="說明正式切換發生的觀察窗口、停止條件與回退判讀範圍">cutover-window&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state&lt;/a> 之間。Gate 說明能否開始，stop condition 說明開始後看到哪些訊號必須停。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 stop condition 的訊號是：&lt;/p>
&lt;ul>
&lt;li>rollout、backfill、replay 或 experiment 會逐批擴大影響&lt;/li>
&lt;li>指標短暫變壞時需要知道是觀察、暫停還是回退&lt;/li>
&lt;li>owner 需要在事故現場快速做一致決策&lt;/li>
&lt;li>post-incident review 要檢查當時是否該更早停下來&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>資料庫 migration 可以定義 &lt;code>mismatch_rate &amp;gt;= 0.1% for two consecutive batches&lt;/code> 或 &lt;code>replication_lag &amp;gt;= 30s for 10 minutes&lt;/code> 作為 stop condition。達到條件時，團隊先暫停下一批 backfill 或回到 fallback read，而不是等使用者回報。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Stop condition 要包含訊號、門檻、觀察窗口、對應動作與 owner。它要進入 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a>，並且要能被 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a> 支撐。&lt;/p></description><content:encoded><![CDATA[<p>Stop condition 的核心概念是「事前定義何時必須暫停、回退或改路線」。它連接 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">release gate</a>、<a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback strategy</a> 與 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a>，避免團隊在壓力下用感覺決定是否繼續。</p>
<h2 id="概念位置">概念位置</h2>
<p>Stop condition 位在 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate</a>、<a href="/blog/backend/knowledge-cards/cutover-window/" data-link-title="Cutover Window" data-link-desc="說明正式切換發生的觀察窗口、停止條件與回退判讀範圍">cutover-window</a> 與 <a href="/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state</a> 之間。Gate 說明能否開始，stop condition 說明開始後看到哪些訊號必須停。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 stop condition 的訊號是：</p>
<ul>
<li>rollout、backfill、replay 或 experiment 會逐批擴大影響</li>
<li>指標短暫變壞時需要知道是觀察、暫停還是回退</li>
<li>owner 需要在事故現場快速做一致決策</li>
<li>post-incident review 要檢查當時是否該更早停下來</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>資料庫 migration 可以定義 <code>mismatch_rate &gt;= 0.1% for two consecutive batches</code> 或 <code>replication_lag &gt;= 30s for 10 minutes</code> 作為 stop condition。達到條件時，團隊先暫停下一批 backfill 或回到 fallback read，而不是等使用者回報。</p>
<h2 id="設計責任">設計責任</h2>
<p>Stop condition 要包含訊號、門檻、觀察窗口、對應動作與 owner。它要進入 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">release gate</a> 和 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a>，並且要能被 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a> 支撐。</p>
]]></content:encoded></item><item><title>Load Test</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/load-test/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/load-test/</guid><description>&lt;p>Load test 的核心概念是「以接近真實流量模型驗證系統容量」。它用來發現瓶頸與評估擴容/降級策略。 可先對照 &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;h2 id="概念位置">概念位置&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>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義流量模型、成功標準與可回應行動，避免只跑壓測數字而沒有決策結論。&lt;/p></description><content:encoded><![CDATA[<p>Load test 的核心概念是「以接近真實流量模型驗證系統容量」。它用來發現瓶頸與評估擴容/降級策略。 可先對照 <a href="/blog/backend/knowledge-cards/local-worker/" data-link-title="Local Worker" data-link-desc="說明同一個 process 內的背景工作模型與其生命週期邊界">Local Worker</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>常在活動前、重大發版前或架構調整後執行，並觀察延遲、錯誤率與資源使用。 可先對照 <a href="/blog/backend/knowledge-cards/local-worker/" data-link-title="Local Worker" data-link-desc="說明同一個 process 內的背景工作模型與其生命週期邊界">Local Worker</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義流量模型、成功標準與可回應行動，避免只跑壓測數字而沒有決策結論。</p>
]]></content:encoded></item><item><title>RTO</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/rto/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/rto/</guid><description>&lt;p>RTO 的核心概念是「事故後服務恢復到可接受狀態所需的最長時間」。它是產品承諾與技術設計之間的時間約束。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">Downtime&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>RTO 連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">downtime&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback-strategy&lt;/a>。更短 RTO 通常需要更高操作準備與基礎設施成本。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 RTO 的訊號是停機時間會直接影響收入或合約責任。付款服務若目標 RTO 為 15 分鐘，值班流程與切換能力都要圍繞這個目標設計。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>RTO 要對應分級、責任角色、演練頻率與驗證方式。設定後需用演練與真實事故資料驗證是否達成。&lt;/p></description><content:encoded><![CDATA[<p>RTO 的核心概念是「事故後服務恢復到可接受狀態所需的最長時間」。它是產品承諾與技術設計之間的時間約束。 可先對照 <a href="/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">Downtime</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>RTO 連接 <a href="/blog/backend/knowledge-cards/downtime/" data-link-title="Downtime" data-link-desc="說明服務中斷時需要評估的產品後果、資料保護與復原順序">downtime</a>、<a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">failover</a> 與 <a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback-strategy</a>。更短 RTO 通常需要更高操作準備與基礎設施成本。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 RTO 的訊號是停機時間會直接影響收入或合約責任。付款服務若目標 RTO 為 15 分鐘，值班流程與切換能力都要圍繞這個目標設計。</p>
<h2 id="設計責任">設計責任</h2>
<p>RTO 要對應分級、責任角色、演練頻率與驗證方式。設定後需用演練與真實事故資料驗證是否達成。</p>
]]></content:encoded></item><item><title>Gate Decision</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/gate-decision/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/gate-decision/</guid><description>&lt;p>Gate decision 的核心概念是「release gate 根據證據做出的明確下一步」。它連接 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stop-condition/" data-link-title="Stop Condition" data-link-desc="說明變更、實驗或事故處理何時必須暫停、回退或改路線">stop condition&lt;/a>，讓 gate 不只寫檢查結果，也寫出能不能前進。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Gate decision 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/confidence/" data-link-title="Confidence" data-link-desc="說明證據包如何標示 confirmed、suspected 或 needs follow-up 的判讀信心">confidence&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback window&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a> 之間。Checks 描述檢查結果，gate decision 把結果轉成放行、暫停、回退、fail-forward 或補證據。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 gate decision 的訊號是：&lt;/p>
&lt;ul>
&lt;li>CI、SLO、validation query 都有結果，但沒人知道下一步&lt;/li>
&lt;li>evidence 足以支持部分放行，但不足以支持完整 cutover&lt;/li>
&lt;li>變更需要逐批 rollout、backfill、warmup 或 replay&lt;/li>
&lt;li>gate 要保留 owner 與 rollback window&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>資料庫 migration 的 gate decision 可以寫成 &lt;code>allow next 10% backfill; block customer-visible read cutover&lt;/code>。這句話比 &lt;code>migration pass&lt;/code> 更可操作，因為它同時說明允許前進的範圍與被擋住的風險面。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Gate decision 要包含決策內容、支撐 checks、stop condition、rollback window 與 owner。它要能被 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a> 承接，讓放行後出現異常時能回放當時依據。&lt;/p></description><content:encoded><![CDATA[<p>Gate decision 的核心概念是「release gate 根據證據做出的明確下一步」。它連接 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">release gate</a>、<a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a> 與 <a href="/blog/backend/knowledge-cards/stop-condition/" data-link-title="Stop Condition" data-link-desc="說明變更、實驗或事故處理何時必須暫停、回退或改路線">stop condition</a>，讓 gate 不只寫檢查結果，也寫出能不能前進。</p>
<h2 id="概念位置">概念位置</h2>
<p>Gate decision 位在 <a href="/blog/backend/knowledge-cards/confidence/" data-link-title="Confidence" data-link-desc="說明證據包如何標示 confirmed、suspected 或 needs follow-up 的判讀信心">confidence</a>、<a href="/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback window</a> 與 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a> 之間。Checks 描述檢查結果，gate decision 把結果轉成放行、暫停、回退、fail-forward 或補證據。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 gate decision 的訊號是：</p>
<ul>
<li>CI、SLO、validation query 都有結果，但沒人知道下一步</li>
<li>evidence 足以支持部分放行，但不足以支持完整 cutover</li>
<li>變更需要逐批 rollout、backfill、warmup 或 replay</li>
<li>gate 要保留 owner 與 rollback window</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>資料庫 migration 的 gate decision 可以寫成 <code>allow next 10% backfill; block customer-visible read cutover</code>。這句話比 <code>migration pass</code> 更可操作，因為它同時說明允許前進的範圍與被擋住的風險面。</p>
<h2 id="設計責任">設計責任</h2>
<p>Gate decision 要包含決策內容、支撐 checks、stop condition、rollback window 與 owner。它要能被 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a> 承接，讓放行後出現異常時能回放當時依據。</p>
]]></content:encoded></item><item><title>Chaos Test</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/chaos-test/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/chaos-test/</guid><description>&lt;p>Chaos test 的核心概念是「在可控範圍內主動注入故障，驗證系統韌性」。它用於驗證降級、切換與回復流程。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間處理流程如何記錄可恢復進度">Checkpoint&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>常在預備環境或受控生產範圍執行，模擬節點失效、網路延遲、依賴不可用等情境。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間處理流程如何記錄可恢復進度">Checkpoint&lt;/a>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義故障範圍、停止條件、觀測指標與回復流程，避免測試本身造成失控影響。&lt;/p></description><content:encoded><![CDATA[<p>Chaos test 的核心概念是「在可控範圍內主動注入故障，驗證系統韌性」。它用於驗證降級、切換與回復流程。 可先對照 <a href="/blog/backend/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間處理流程如何記錄可恢復進度">Checkpoint</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>常在預備環境或受控生產範圍執行，模擬節點失效、網路延遲、依賴不可用等情境。 可先對照 <a href="/blog/backend/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間處理流程如何記錄可恢復進度">Checkpoint</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義故障範圍、停止條件、觀測指標與回復流程，避免測試本身造成失控影響。</p>
]]></content:encoded></item><item><title>RPO</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/rpo/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/rpo/</guid><description>&lt;p>RPO 的核心概念是「事故後可接受的最大資料損失窗口」。它回答回復後最多能遺失多久的資料變更。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>RPO 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a>、備份策略、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">replication lag&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">data reconciliation&lt;/a> 緊密相關。RPO 越嚴格，資料保護與同步成本通常越高。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 RPO 的訊號是資料遺失會造成財務或合規風險。訂單與付款資料若目標 RPO 接近零，需要更嚴格的持久化與回復設計。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>RPO 要定義資料類型分級、保護機制、驗證流程與例外處理。設定後應透過備份回復演練檢查實際可達成範圍。&lt;/p></description><content:encoded><![CDATA[<p>RPO 的核心概念是「事故後可接受的最大資料損失窗口」。它回答回復後最多能遺失多久的資料變更。 可先對照 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>RPO 與 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a>、備份策略、<a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">replication lag</a> 與 <a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">data reconciliation</a> 緊密相關。RPO 越嚴格，資料保護與同步成本通常越高。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 RPO 的訊號是資料遺失會造成財務或合規風險。訂單與付款資料若目標 RPO 接近零，需要更嚴格的持久化與回復設計。</p>
<h2 id="設計責任">設計責任</h2>
<p>RPO 要定義資料類型分級、保護機制、驗證流程與例外處理。設定後應透過備份回復演練檢查實際可達成範圍。</p>
]]></content:encoded></item><item><title>Projection</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/projection/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/projection/</guid><description>&lt;p>Projection 從事件流或資料變更中持續推算出特定用途的讀取視圖，連接寫入端（事件產生）跟讀取端（查詢消費）。Projection 的輸出是 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Projection 在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-sourcing/" data-link-title="Event Sourcing" data-link-desc="說明用 append-only 事件流取代 mutable state 作為正式紀錄的設計模式、需求判準與代價">event sourcing&lt;/a> 架構中扮演「event → current state」的推算角色。Event log 是 append-only 的事件序列，直接對 event log 做查詢效率低；projection 持續消費事件、維護可查詢的 read model，讓讀取端不需要每次 replay 整條事件流。&lt;/p>
&lt;p>Projection 不限於 event sourcing。CDC（Change Data Capture）把資料庫的 row 變更推送到下游、下游建立搜尋索引或統計摘要，這也是 projection — 來源是 row change event 而非 domain event。觀測領域的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule&lt;/a> 也是一種 projection — 從 raw time series 持續推算預聚合的 metrics。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 projection 時要定義四個面向：&lt;/p>
&lt;p>&lt;strong>更新策略&lt;/strong>：同步（事件寫入時立即更新 read model）或非同步（事件寫入後由背景消費者更新）。同步更新延遲低但耦合寫入路徑的效能；非同步更新解耦但 read model 有 lag。&lt;/p>
&lt;p>&lt;strong>重建流程&lt;/strong>：當 projection 邏輯改變或 read model 損壞時，需要從 event log 重新 replay 建立 read model。重建流程要能離線執行、不影響線上讀取。大量事件的 replay 可能需要數小時，設計時要估算重建時間跟資源需求。&lt;/p>
&lt;p>&lt;strong>正確性驗證&lt;/strong>：projection 是持續運行的計算，任何 bug 都會讓 read model 靜默偏離真實狀態。需要定期的 reconciliation（拿 projection 結果跟 event log 全量 replay 比較）來偵測漂移。&lt;/p>
&lt;p>&lt;strong>schema evolution&lt;/strong>：當來源事件的 schema 改版，projection 邏輯要能同時處理新舊版本的事件。這跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-sourcing/" data-link-title="Event Sourcing" data-link-desc="說明用 append-only 事件流取代 mutable state 作為正式紀錄的設計模式、需求判準與代價">event sourcing&lt;/a> 的 upcasting 問題直接相關。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>需要 projection 的訊號是：讀取需求跟寫入結構不同（列表頁需要反正規化 view、搜尋需要全文索引、報表需要聚合摘要），而且這些讀取視圖需要隨資料變更持續更新而非批次重建。&lt;/p>
&lt;p>常見的 projection 實作包括：event handler 更新 read DB、CDC consumer 更新 Elasticsearch index、Kafka Streams 維護 KTable、觀測 collector 做 log-to-metric 轉換。&lt;/p></description><content:encoded><![CDATA[<p>Projection 從事件流或資料變更中持續推算出特定用途的讀取視圖，連接寫入端（事件產生）跟讀取端（查詢消費）。Projection 的輸出是 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a> — 為特定查詢需求反正規化的資料形狀。</p>
<h2 id="概念位置">概念位置</h2>
<p>Projection 在 <a href="/blog/backend/knowledge-cards/event-sourcing/" data-link-title="Event Sourcing" data-link-desc="說明用 append-only 事件流取代 mutable state 作為正式紀錄的設計模式、需求判準與代價">event sourcing</a> 架構中扮演「event → current state」的推算角色。Event log 是 append-only 的事件序列，直接對 event log 做查詢效率低；projection 持續消費事件、維護可查詢的 read model，讓讀取端不需要每次 replay 整條事件流。</p>
<p>Projection 不限於 event sourcing。CDC（Change Data Capture）把資料庫的 row 變更推送到下游、下游建立搜尋索引或統計摘要，這也是 projection — 來源是 row change event 而非 domain event。觀測領域的 <a href="/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule</a> 也是一種 projection — 從 raw time series 持續推算預聚合的 metrics。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 projection 時要定義四個面向：</p>
<p><strong>更新策略</strong>：同步（事件寫入時立即更新 read model）或非同步（事件寫入後由背景消費者更新）。同步更新延遲低但耦合寫入路徑的效能；非同步更新解耦但 read model 有 lag。</p>
<p><strong>重建流程</strong>：當 projection 邏輯改變或 read model 損壞時，需要從 event log 重新 replay 建立 read model。重建流程要能離線執行、不影響線上讀取。大量事件的 replay 可能需要數小時，設計時要估算重建時間跟資源需求。</p>
<p><strong>正確性驗證</strong>：projection 是持續運行的計算，任何 bug 都會讓 read model 靜默偏離真實狀態。需要定期的 reconciliation（拿 projection 結果跟 event log 全量 replay 比較）來偵測漂移。</p>
<p><strong>schema evolution</strong>：當來源事件的 schema 改版，projection 邏輯要能同時處理新舊版本的事件。這跟 <a href="/blog/backend/knowledge-cards/event-sourcing/" data-link-title="Event Sourcing" data-link-desc="說明用 append-only 事件流取代 mutable state 作為正式紀錄的設計模式、需求判準與代價">event sourcing</a> 的 upcasting 問題直接相關。</p>
<h2 id="使用情境">使用情境</h2>
<p>需要 projection 的訊號是：讀取需求跟寫入結構不同（列表頁需要反正規化 view、搜尋需要全文索引、報表需要聚合摘要），而且這些讀取視圖需要隨資料變更持續更新而非批次重建。</p>
<p>常見的 projection 實作包括：event handler 更新 read DB、CDC consumer 更新 Elasticsearch index、Kafka Streams 維護 KTable、觀測 collector 做 log-to-metric 轉換。</p>
]]></content:encoded></item><item><title>Rollback Condition</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-condition/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-condition/</guid><description>&lt;p>Rollback condition 的核心概念是「某個決策執行後，看到哪些訊號時要撤回、回退或改路線」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback strategy&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stop-condition/" data-link-title="Stop Condition" data-link-desc="說明變更、實驗或事故處理何時必須暫停、回退或改路線">stop condition&lt;/a>，讓事故現場能控制次生風險。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Rollback condition 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/gate-decision/" data-link-title="Gate Decision" data-link-desc="說明 release gate 如何把證據轉成放行、暫停、回退或補證據的決策">gate decision&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback window&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/time-range/" data-link-title="Time Range" data-link-desc="說明證據、查詢與事故判讀如何用時間窗保留可回放上下文">time range&lt;/a> 之間。Stop condition 常用於流程何時停，rollback condition 則跟某筆已做出的 decision 綁在一起。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 rollback condition 的訊號是：&lt;/p>
&lt;ul>
&lt;li>rollback、fallback、degradation 或 fail-forward 本身也可能造成風險&lt;/li>
&lt;li>IC handoff 後，新 IC 需要知道什麼條件下要改路線&lt;/li>
&lt;li>stakeholder update 需要說明目前決策如何被監控&lt;/li>
&lt;li>PIR 需要檢查當時是否有明確撤回條件&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>客服後台切回 legacy status fallback 後，rollback condition 可以寫成 &lt;code>mismatch remains above threshold after 15 minutes&lt;/code>。這表示 fallback 沒有降低錯誤時，團隊要改成資料修補或暫停相關入口，而不是繼續等待。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Rollback condition 要包含訊號、門檻、觀察窗口、對應動作與 owner。它要連到 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/query-link/" data-link-title="Query Link" data-link-desc="說明證據包如何保存可重跑查詢入口，而不是只保留截圖或口頭結論">query link&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/time-range/" data-link-title="Time Range" data-link-desc="說明證據、查詢與事故判讀如何用時間窗保留可回放上下文">time range&lt;/a>，讓決策撤回成為可回放的證據判讀，口頭判斷的準確度和可追溯性都不足。&lt;/p></description><content:encoded><![CDATA[<p>Rollback condition 的核心概念是「某個決策執行後，看到哪些訊號時要撤回、回退或改路線」。它連接 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a>、<a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback strategy</a> 與 <a href="/blog/backend/knowledge-cards/stop-condition/" data-link-title="Stop Condition" data-link-desc="說明變更、實驗或事故處理何時必須暫停、回退或改路線">stop condition</a>，讓事故現場能控制次生風險。</p>
<h2 id="概念位置">概念位置</h2>
<p>Rollback condition 位在 <a href="/blog/backend/knowledge-cards/gate-decision/" data-link-title="Gate Decision" data-link-desc="說明 release gate 如何把證據轉成放行、暫停、回退或補證據的決策">gate decision</a>、<a href="/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">rollback window</a> 與 <a href="/blog/backend/knowledge-cards/time-range/" data-link-title="Time Range" data-link-desc="說明證據、查詢與事故判讀如何用時間窗保留可回放上下文">time range</a> 之間。Stop condition 常用於流程何時停，rollback condition 則跟某筆已做出的 decision 綁在一起。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 rollback condition 的訊號是：</p>
<ul>
<li>rollback、fallback、degradation 或 fail-forward 本身也可能造成風險</li>
<li>IC handoff 後，新 IC 需要知道什麼條件下要改路線</li>
<li>stakeholder update 需要說明目前決策如何被監控</li>
<li>PIR 需要檢查當時是否有明確撤回條件</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>客服後台切回 legacy status fallback 後，rollback condition 可以寫成 <code>mismatch remains above threshold after 15 minutes</code>。這表示 fallback 沒有降低錯誤時，團隊要改成資料修補或暫停相關入口，而不是繼續等待。</p>
<h2 id="設計責任">設計責任</h2>
<p>Rollback condition 要包含訊號、門檻、觀察窗口、對應動作與 owner。它要連到 <a href="/blog/backend/knowledge-cards/query-link/" data-link-title="Query Link" data-link-desc="說明證據包如何保存可重跑查詢入口，而不是只保留截圖或口頭結論">query link</a> 與 <a href="/blog/backend/knowledge-cards/time-range/" data-link-title="Time Range" data-link-desc="說明證據、查詢與事故判讀如何用時間窗保留可回放上下文">time range</a>，讓決策撤回成為可回放的證據判讀，口頭判斷的準確度和可追溯性都不足。</p>
]]></content:encoded></item><item><title>MTTR</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/mttr/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/mttr/</guid><description>&lt;p>MTTR 的核心概念是「從事故開始到恢復的平均時間」。它幫助團隊追蹤處置效率趨勢，但不能單獨代表可靠性品質。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>MTTR 連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity&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;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/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review&lt;/a>。不同等級事故應分開計算，避免指標失真。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 MTTR 的訊號是團隊想驗證事故流程是否改進。若新增 runbook 與升級策略後 MTTR 持續下降，表示流程變更有實際效果。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>MTTR 指標要搭配樣本數、嚴重度分層與影響範圍一起解讀。它應導向流程改善與演練設計，而不是單純追求數字下降。&lt;/p></description><content:encoded><![CDATA[<p>MTTR 的核心概念是「從事故開始到恢復的平均時間」。它幫助團隊追蹤處置效率趨勢，但不能單獨代表可靠性品質。 可先對照 <a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>MTTR 連接 <a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity</a>、<a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>、<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 與 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review</a>。不同等級事故應分開計算，避免指標失真。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 MTTR 的訊號是團隊想驗證事故流程是否改進。若新增 runbook 與升級策略後 MTTR 持續下降，表示流程變更有實際效果。</p>
<h2 id="設計責任">設計責任</h2>
<p>MTTR 指標要搭配樣本數、嚴重度分層與影響範圍一起解讀。它應導向流程改善與演練設計，而不是單純追求數字下降。</p>
]]></content:encoded></item><item><title>On-Call</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/on-call/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/on-call/</guid><description>&lt;p>On-call 的核心概念是「在指定時段由明確責任角色承接運行事件」。它是 &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/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy&lt;/a> 的執行入口，把告警回應、事故分級、升級決策與交接責任固定化，讓事故處理不依賴臨時找人。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>On-call 是 &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/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy&lt;/a> 的執行入口。值班工程師是 alert 的第一個接收者，負責判斷「這個 alert 需要什麼等級的回應」。&lt;/p>
&lt;p>On-call 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a> 搭配運作 — runbook 提供行動指南、on-call 工程師執行。制度需要跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a> 跟演練一起維護，避免值班只剩 pager 通知而沒有可執行流程。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 on-call 制度的訊號是事故常在非上班時間發生、或跨區團隊需要連續處理。付款 API 夜間故障時，若沒有清楚值班安排，回復時間通常被人員定位延遲拉長。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>On-call 設計要定義排班週期、回應時限（critical alert 需要 N 分鐘內 ack）、交接格式（交班時把當前狀態跟未關閉事項傳給下一位）、升級路徑（on-call 解不了時升級到 tech lead / manager）與支援角色（secondary on-call 或 subject matter expert）。Alert noise 治理跟 on-call 品質直接相關 — &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">alert fatigue&lt;/a> 會讓值班品質退化。&lt;/p></description><content:encoded><![CDATA[<p>On-call 的核心概念是「在指定時段由明確責任角色承接運行事件」。它是 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a> 與 <a href="/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy</a> 的執行入口，把告警回應、事故分級、升級決策與交接責任固定化，讓事故處理不依賴臨時找人。</p>
<h2 id="概念位置">概念位置</h2>
<p>On-call 是 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>、<a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity</a> 與 <a href="/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy</a> 的執行入口。值班工程師是 alert 的第一個接收者，負責判斷「這個 alert 需要什麼等級的回應」。</p>
<p>On-call 跟 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 搭配運作 — runbook 提供行動指南、on-call 工程師執行。制度需要跟 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a> 跟演練一起維護，避免值班只剩 pager 通知而沒有可執行流程。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 on-call 制度的訊號是事故常在非上班時間發生、或跨區團隊需要連續處理。付款 API 夜間故障時，若沒有清楚值班安排，回復時間通常被人員定位延遲拉長。</p>
<h2 id="設計責任">設計責任</h2>
<p>On-call 設計要定義排班週期、回應時限（critical alert 需要 N 分鐘內 ack）、交接格式（交班時把當前狀態跟未關閉事項傳給下一位）、升級路徑（on-call 解不了時升級到 tech lead / manager）與支援角色（secondary on-call 或 subject matter expert）。Alert noise 治理跟 on-call 品質直接相關 — <a href="/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">alert fatigue</a> 會讓值班品質退化。</p>
]]></content:encoded></item><item><title>Full-Text Search</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/full-text-search/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/full-text-search/</guid><description>&lt;p>Full-text search 的核心概念是「對文本內容做可擴展檢索」。它支援分詞、相關性排序與關鍵字查詢。 可先對照 &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="概念位置">概念位置&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;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義語言分析規則、索引更新延遲與查詢範圍，避免搜尋結果與產品預期落差。&lt;/p></description><content:encoded><![CDATA[<p>Full-text search 的核心概念是「對文本內容做可擴展檢索」。它支援分詞、相關性排序與關鍵字查詢。 可先對照 <a href="/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">Search Index</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>通常由 <a href="/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">search index</a> 提供，適合文件、商品描述與知識庫查詢。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義語言分析規則、索引更新延遲與查詢範圍，避免搜尋結果與產品預期落差。</p>
]]></content:encoded></item><item><title>Facet Query</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/facet-query/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/facet-query/</guid><description>&lt;p>Facet query 的核心概念是「在搜尋結果上提供可聚合的分類維度」。它讓使用者能快速依品牌、分類、價格區間等條件縮小結果。 可先對照 &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="概念位置">概念位置&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="說明全文檢索如何處理關鍵字匹配、語言分析與排序">full-text search&lt;/a> 搭配，提升查詢互動性。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義分面欄位、聚合成本與更新策略，避免高成本聚合拖慢查詢。&lt;/p></description><content:encoded><![CDATA[<p>Facet query 的核心概念是「在搜尋結果上提供可聚合的分類維度」。它讓使用者能快速依品牌、分類、價格區間等條件縮小結果。 可先對照 <a href="/blog/backend/knowledge-cards/search-index/" data-link-title="Search Index" data-link-desc="說明搜尋索引如何承擔全文檢索、排序與查詢體驗">Search Index</a>。</p>
<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/full-text-search/" data-link-title="Full-Text Search" data-link-desc="說明全文檢索如何處理關鍵字匹配、語言分析與排序">full-text search</a> 搭配，提升查詢互動性。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義分面欄位、聚合成本與更新策略，避免高成本聚合拖慢查詢。</p>
]]></content:encoded></item><item><title>Playbook</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/playbook/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/playbook/</guid><description>&lt;p>Playbook 的核心概念是「針對特定故障場景提供可直接執行的處置腳本」。它比通用 &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;p>Playbook 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">incident command system&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback-strategy&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review&lt;/a> 之間。復盤後的改進常會沉澱成新的 playbook。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 playbook 的訊號是某類事故反覆出現且處置步驟可預期。consumer lag 持續擴大、憑證即將過期、單區域流量異常等場景都適合建立專用 playbook。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Playbook 要定義觸發條件、必要查詢、操作步驟、停止條件與回復驗證。內容應保持短而可執行，並在每次演練或真實事故後更新。&lt;/p></description><content:encoded><![CDATA[<p>Playbook 的核心概念是「針對特定故障場景提供可直接執行的處置腳本」。它比通用 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 更聚焦，通常對應單一風險模式或單一系統路徑。</p>
<h2 id="概念位置">概念位置</h2>
<p>Playbook 位在 <a href="/blog/backend/knowledge-cards/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">incident command system</a>、<a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback-strategy</a> 與 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review</a> 之間。復盤後的改進常會沉澱成新的 playbook。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 playbook 的訊號是某類事故反覆出現且處置步驟可預期。consumer lag 持續擴大、憑證即將過期、單區域流量異常等場景都適合建立專用 playbook。</p>
<h2 id="設計責任">設計責任</h2>
<p>Playbook 要定義觸發條件、必要查詢、操作步驟、停止條件與回復驗證。內容應保持短而可執行，並在每次演練或真實事故後更新。</p>
]]></content:encoded></item><item><title>Fuzz Test</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/fuzz-test/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/fuzz-test/</guid><description>&lt;p>Fuzz test 的核心概念是「用大量變異輸入找出非預期崩潰與解析漏洞」。它特別適合 parser、協議處理與輸入邊界驗證。 可先對照 &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>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>這張卡位在 &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>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義輸入範圍、崩潰判定與回歸樣本保留，確保問題可重現與可修復。&lt;/p></description><content:encoded><![CDATA[<p>Fuzz test 的核心概念是「用大量變異輸入找出非預期崩潰與解析漏洞」。它特別適合 parser、協議處理與輸入邊界驗證。 可先對照 <a href="/blog/backend/knowledge-cards/game-day/" data-link-title="Game Day" data-link-desc="說明事故演練如何驗證流程、工具與團隊協作">Game Day</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>這張卡位在 <a href="/blog/backend/knowledge-cards/game-day/" data-link-title="Game Day" data-link-desc="說明事故演練如何驗證流程、工具與團隊協作">Game Day</a> 附近，可和它一起看。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義輸入範圍、崩潰判定與回歸樣本保留，確保問題可重現與可修復。</p>
]]></content:encoded></item><item><title>Game Day</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/game-day/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/game-day/</guid><description>&lt;p>Game day 的核心概念是「在受控環境模擬故障並演練處置流程」。它用實際操作驗證告警、分級、指揮、回滾與通訊是否真的可用。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Game day 是 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review&lt;/a> 的訓練場景。它把文件假設轉成可觀察行為與量化結果。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 game day 的訊號是流程文件完整但實戰仍常卡住。團隊可在預備環境模擬 broker 中斷、database 延遲或憑證失效，觀察 MTTR 與升級節奏是否符合預期。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Game day 要定義演練範圍、安全邊界、成功標準、紀錄方式與復盤輸出。演練設計應避免只測單一團隊，並包含跨角色溝通與決策節點。&lt;/p></description><content:encoded><![CDATA[<p>Game day 的核心概念是「在受控環境模擬故障並演練處置流程」。它用實際操作驗證告警、分級、指揮、回滾與通訊是否真的可用。 可先對照 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">On-Call</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Game day 是 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a>、<a href="/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline</a> 與 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review</a> 的訓練場景。它把文件假設轉成可觀察行為與量化結果。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 game day 的訊號是流程文件完整但實戰仍常卡住。團隊可在預備環境模擬 broker 中斷、database 延遲或憑證失效，觀察 MTTR 與升級節奏是否符合預期。</p>
<h2 id="設計責任">設計責任</h2>
<p>Game day 要定義演練範圍、安全邊界、成功標準、紀錄方式與復盤輸出。演練設計應避免只測單一團隊，並包含跨角色溝通與決策節點。</p>
]]></content:encoded></item><item><title>Ownership</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/ownership/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/ownership/</guid><description>&lt;p>Ownership 的核心概念是「把責任固定到可執行角色」。它讓團隊在事件、變更與回寫流程中能快速判斷誰主責、誰協作、誰做決策，是 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy&lt;/a> 運作的前提。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Ownership 連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert&lt;/a>（每個 alert rule 需要 owner）、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard&lt;/a>（每個 dashboard 需要維護者）、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook&lt;/a>（runbook 的更新責任跟服務 owner 一致）、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy&lt;/a>。&lt;/p>
&lt;p>在觀測系統中，沒有 owner 的 alert 跟 dashboard 會隨服務演進退化 — alert 變成 noise、dashboard 變成裝飾。&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/signal-governance-loop/" data-link-title="4.8 訊號治理閉環" data-link-desc="把 postmortem 揭露的偵測缺口回寫成新訊號、讓觀測能力隨事故學習成長">4.8 訊號治理閉環&lt;/a> 的定期審視需要每個訊號都有明確 owner。&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 operating model&lt;/a> 定義 ownership 矩陣。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 ownership 的訊號是同一事件在不同角色之間反覆轉手、或 alert 觸發後沒人知道該誰處理。Owner 離職但 alert / dashboard / runbook 沒有交接是常見的退化模式。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Ownership 需要定義主責角色、協作角色、升級路由與關閉責任。Owner 變動時（離職、轉組）需要交接流程 — orphan alert / dashboard 的定期掃描是治理的一部分。每次服務邊界調整（新服務上線、服務合併）都應同步檢查 ownership 是否仍對齊。&lt;/p></description><content:encoded><![CDATA[<p>Ownership 的核心概念是「把責任固定到可執行角色」。它讓團隊在事件、變更與回寫流程中能快速判斷誰主責、誰協作、誰做決策，是 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a> 與 <a href="/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy</a> 運作的前提。</p>
<h2 id="概念位置">概念位置</h2>
<p>Ownership 連接 <a href="/blog/backend/knowledge-cards/alert/" data-link-title="Alert" data-link-desc="說明 alert 如何把需要處理的服務症狀轉成可行動通知">alert</a>（每個 alert rule 需要 owner）、<a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a>（每個 dashboard 需要維護者）、<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a>（runbook 的更新責任跟服務 owner 一致）、<a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity</a> 跟 <a href="/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy</a>。</p>
<p>在觀測系統中，沒有 owner 的 alert 跟 dashboard 會隨服務演進退化 — alert 變成 noise、dashboard 變成裝飾。<a href="/blog/backend/04-observability/signal-governance-loop/" data-link-title="4.8 訊號治理閉環" data-link-desc="把 postmortem 揭露的偵測缺口回寫成新訊號、讓觀測能力隨事故學習成長">4.8 訊號治理閉環</a> 的定期審視需要每個訊號都有明確 owner。<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 operating model</a> 定義 ownership 矩陣。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 ownership 的訊號是同一事件在不同角色之間反覆轉手、或 alert 觸發後沒人知道該誰處理。Owner 離職但 alert / dashboard / runbook 沒有交接是常見的退化模式。</p>
<h2 id="設計責任">設計責任</h2>
<p>Ownership 需要定義主責角色、協作角色、升級路由與關閉責任。Owner 變動時（離職、轉組）需要交接流程 — orphan alert / dashboard 的定期掃描是治理的一部分。每次服務邊界調整（新服務上線、服務合併）都應同步檢查 ownership 是否仍對齊。</p>
]]></content:encoded></item><item><title>Little's Law</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/little-law/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/little-law/</guid><description>&lt;p>Little&amp;rsquo;s Law 的核心概念是「穩態系統內、平均並發 = 到達率 × 平均逗留時間（L = λW）」。三個變數固定兩個就能推第三個、是容量規劃最小的數學工具。可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Little&amp;rsquo;s Law 連接「業務需求」跟「系統參數」。給定預期 RPS（λ）跟 SLO latency 上限（W）、能算出系統最大同時並發數（L）；反過來、給定 connection pool size（L）跟 latency 目標、能算出可支撐的 RPS。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要用 Little&amp;rsquo;s Law 反推的訊號是「不知道該訂多少 connection pool、thread pool、async worker」。例如：付款 API 預期 1000 RPS、SLO 是 p99 &amp;lt; 200ms、那麼穩態並發 ≈ 1000 × 0.2 = 200、connection pool 至少 200 + headroom。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Little&amp;rsquo;s Law 只在穩態（steady state）下成立、不適用 burst transient。應用前要確認系統已度過 warmup、流量穩定才有意義。所有 stage（網路、應用、DB）都可獨立套用、用於 latency budget 分解。&lt;/p></description><content:encoded><![CDATA[<p>Little&rsquo;s Law 的核心概念是「穩態系統內、平均並發 = 到達率 × 平均逗留時間（L = λW）」。三個變數固定兩個就能推第三個、是容量規劃最小的數學工具。可先對照 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI / SLO</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Little&rsquo;s Law 連接「業務需求」跟「系統參數」。給定預期 RPS（λ）跟 SLO latency 上限（W）、能算出系統最大同時並發數（L）；反過來、給定 connection pool size（L）跟 latency 目標、能算出可支撐的 RPS。可先對照 <a href="/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要用 Little&rsquo;s Law 反推的訊號是「不知道該訂多少 connection pool、thread pool、async worker」。例如：付款 API 預期 1000 RPS、SLO 是 p99 &lt; 200ms、那麼穩態並發 ≈ 1000 × 0.2 = 200、connection pool 至少 200 + headroom。</p>
<h2 id="設計責任">設計責任</h2>
<p>Little&rsquo;s Law 只在穩態（steady state）下成立、不適用 burst transient。應用前要確認系統已度過 warmup、流量穩定才有意義。所有 stage（網路、應用、DB）都可獨立套用、用於 latency budget 分解。</p>
]]></content:encoded></item><item><title>Universal Scalability Law (USL)</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/universal-scalability-law/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/universal-scalability-law/</guid><description>&lt;p>Universal Scalability Law 的核心概念是「擴容到某個臨界點之後、加機器反而讓吞吐下降」。Neil Gunther 的公式 throughput(N) = N / (1 + α(N-1) + βN(N-1))，其中 α = serialization（Amdahl 部分）、β = crosstalk（跨節點協調成本）。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/little-law/" data-link-title="Little&amp;#39;s Law" data-link-desc="說明系統內並發數、到達率與逗留時間三者的數學關係">Little&amp;rsquo;s Law&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>USL 解釋「加機器為什麼會失效」。線性擴容是理想、但實際系統有兩個拖累：α 是必須序列化的部分（如 lock、coordinator）、β 是節點間互相通訊的成本（如 cache invalidation、consensus quorum）。β 通常比 α 更危險、會讓 throughput 在 N 大到某點後反而下降。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/little-law/" data-link-title="Little&amp;#39;s Law" data-link-desc="說明系統內並發數、到達率與逗留時間三者的數學關係">Little&amp;rsquo;s Law&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要思考 USL 的訊號是「擴容到 N 個 instance 後、QPS 不再線性成長」。常見原因：共用 cache 變熱點、distributed lock 競爭、跨 region replication 變慢。對照案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">Spanner&lt;/a> 用 TrueTime 降低 β 達成線性擴展；&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/coinbase-ultra-low-latency-exchange-2023/" data-link-title="9.C3 Coinbase International Exchange：超低延遲交易的逆向容量設計" data-link-desc="為什麼 Coinbase 國際交易所選 Cluster Placement Group &amp;#43; z1d 而不是自動擴容 — 延遲敏感型負載的容量取捨">Coinbase RAFT&lt;/a> 因 consensus 限制了水平擴容。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計分散式系統時、要主動識別 α 跟 β 來源、想辦法降低。常見手段：partition 切分（降 β）、sharding（降 α 的範圍）、避免 distributed lock（降 β）、async vs sync（降 α 的關鍵路徑）。USL 是 &lt;em>選型決策&lt;/em> 的工具、不是 production runtime 的訊號。&lt;/p></description><content:encoded><![CDATA[<p>Universal Scalability Law 的核心概念是「擴容到某個臨界點之後、加機器反而讓吞吐下降」。Neil Gunther 的公式 throughput(N) = N / (1 + α(N-1) + βN(N-1))，其中 α = serialization（Amdahl 部分）、β = crosstalk（跨節點協調成本）。可先對照 <a href="/blog/backend/knowledge-cards/little-law/" data-link-title="Little&#39;s Law" data-link-desc="說明系統內並發數、到達率與逗留時間三者的數學關係">Little&rsquo;s Law</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>USL 解釋「加機器為什麼會失效」。線性擴容是理想、但實際系統有兩個拖累：α 是必須序列化的部分（如 lock、coordinator）、β 是節點間互相通訊的成本（如 cache invalidation、consensus quorum）。β 通常比 α 更危險、會讓 throughput 在 N 大到某點後反而下降。可先對照 <a href="/blog/backend/knowledge-cards/little-law/" data-link-title="Little&#39;s Law" data-link-desc="說明系統內並發數、到達率與逗留時間三者的數學關係">Little&rsquo;s Law</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要思考 USL 的訊號是「擴容到 N 個 instance 後、QPS 不再線性成長」。常見原因：共用 cache 變熱點、distributed lock 競爭、跨 region replication 變慢。對照案例：<a href="/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">Spanner</a> 用 TrueTime 降低 β 達成線性擴展；<a href="/blog/backend/09-performance-capacity/cases/coinbase-ultra-low-latency-exchange-2023/" data-link-title="9.C3 Coinbase International Exchange：超低延遲交易的逆向容量設計" data-link-desc="為什麼 Coinbase 國際交易所選 Cluster Placement Group &#43; z1d 而不是自動擴容 — 延遲敏感型負載的容量取捨">Coinbase RAFT</a> 因 consensus 限制了水平擴容。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計分散式系統時、要主動識別 α 跟 β 來源、想辦法降低。常見手段：partition 切分（降 β）、sharding（降 α 的範圍）、避免 distributed lock（降 β）、async vs sync（降 α 的關鍵路徑）。USL 是 <em>選型決策</em> 的工具、不是 production runtime 的訊號。</p>
]]></content:encoded></item><item><title>Saturation Point</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/saturation-point/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/saturation-point/</guid><description>&lt;p>Saturation point 的核心概念是「系統 latency 從線性穩態進入指數成長的流量臨界點」。容量曲線分三段：linear → knee → cliff。knee point 是設計容量上限（safe operating zone 的邊界）、cliff 是系統極限（已不可用）。可先對照 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Saturation 不是「系統掛掉」、是「進入 latency 不可預測區」。健康系統運轉在 knee point 以下 50-70%。M/M/c queueing theory 顯示：utilization 接近 80% 時、queue length 跟 latency 指數成長 — 這個 80% 就是常見的 knee。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/little-law/" data-link-title="Little&amp;#39;s Law" data-link-desc="說明系統內並發數、到達率與逗留時間三者的數學關係">Little&amp;rsquo;s Law&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Saturation point 出現的訊號是「pressure 增加 10%、latency 增加 100%」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &amp;#43; 傳統伺服器當慢速消費者、承受 100K&amp;#43; 同時選位 &amp;#43; 30 秒從 6 台擴到 800 台">Tixcraft DynamoDB IOPS 從 20 衝到 135K&lt;/a> — partition 設計均勻時 saturation point 推到極遠；hot partition 場景下 saturation point 提前出現、即使整體 capacity 還有餘。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>容量規劃必須先量出 saturation point、再以 headroom 規劃實際 capacity。沒有量過 saturation point 的系統等於「不知道距離崩潰多遠」。每次重大改動後 re-test、確認 knee 沒往不好的方向移。&lt;/p></description><content:encoded><![CDATA[<p>Saturation point 的核心概念是「系統 latency 從線性穩態進入指數成長的流量臨界點」。容量曲線分三段：linear → knee → cliff。knee point 是設計容量上限（safe operating zone 的邊界）、cliff 是系統極限（已不可用）。可先對照 <a href="/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">Load Test</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Saturation 不是「系統掛掉」、是「進入 latency 不可預測區」。健康系統運轉在 knee point 以下 50-70%。M/M/c queueing theory 顯示：utilization 接近 80% 時、queue length 跟 latency 指數成長 — 這個 80% 就是常見的 knee。可先對照 <a href="/blog/backend/knowledge-cards/little-law/" data-link-title="Little&#39;s Law" data-link-desc="說明系統內並發數、到達率與逗留時間三者的數學關係">Little&rsquo;s Law</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Saturation point 出現的訊號是「pressure 增加 10%、latency 增加 100%」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &#43; 傳統伺服器當慢速消費者、承受 100K&#43; 同時選位 &#43; 30 秒從 6 台擴到 800 台">Tixcraft DynamoDB IOPS 從 20 衝到 135K</a> — partition 設計均勻時 saturation point 推到極遠；hot partition 場景下 saturation point 提前出現、即使整體 capacity 還有餘。</p>
<h2 id="設計責任">設計責任</h2>
<p>容量規劃必須先量出 saturation point、再以 headroom 規劃實際 capacity。沒有量過 saturation point 的系統等於「不知道距離崩潰多遠」。每次重大改動後 re-test、確認 knee 沒往不好的方向移。</p>
]]></content:encoded></item><item><title>USE Method</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/use-method/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/use-method/</guid><description>&lt;p>USE method 的核心概念是「對每個資源（CPU / RAM / disk / network / DB connection）量測 Utilization、Saturation、Errors 三個維度」。第一個出現 saturation 上升的資源、就是 bottleneck。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/red-method/" data-link-title="RED Method" data-link-desc="Tom Wilkie 提出的請求層 Rate / Errors / Duration 三維度量測法">RED Method&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>USE 是 resource-oriented 的觀察法、跟 request-oriented 的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/red-method/" data-link-title="RED Method" data-link-desc="Tom Wilkie 提出的請求層 Rate / Errors / Duration 三維度量測法">RED method&lt;/a> 互補。USE 回答「哪個資源先頂不住」、RED 回答「哪個 endpoint 表現變差」。容量規劃通常先看 USE 找瓶頸、再看 RED 看影響面。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>USE 三維度的典型訊號：CPU utilization 100% 但 saturation queue 空 → 還能撐；CPU 80% 但 run queue 不斷增長 → 已 saturate。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &amp;#43; AWS Media Services 撐 30 channels live &amp;#43; 5M MAU、工程工時下降 90%">Lemino connection limit&lt;/a> — utilization 看似還行、但 connection saturation 已爆。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>USE method 的關鍵是「不要只看 utilization」。utilization 是「目前用了多少」、saturation 是「排隊有多少在等」 — 後者才是 capacity 真正的領先指標。每個資源都要量三個維度、不能用 average 代替 percentile。&lt;/p></description><content:encoded><![CDATA[<p>USE method 的核心概念是「對每個資源（CPU / RAM / disk / network / DB connection）量測 Utilization、Saturation、Errors 三個維度」。第一個出現 saturation 上升的資源、就是 bottleneck。可先對照 <a href="/blog/backend/knowledge-cards/red-method/" data-link-title="RED Method" data-link-desc="Tom Wilkie 提出的請求層 Rate / Errors / Duration 三維度量測法">RED Method</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>USE 是 resource-oriented 的觀察法、跟 request-oriented 的 <a href="/blog/backend/knowledge-cards/red-method/" data-link-title="RED Method" data-link-desc="Tom Wilkie 提出的請求層 Rate / Errors / Duration 三維度量測法">RED method</a> 互補。USE 回答「哪個資源先頂不住」、RED 回答「哪個 endpoint 表現變差」。容量規劃通常先看 USE 找瓶頸、再看 RED 看影響面。可先對照 <a href="/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>USE 三維度的典型訊號：CPU utilization 100% 但 saturation queue 空 → 還能撐；CPU 80% 但 run queue 不斷增長 → 已 saturate。對應案例：<a href="/blog/backend/09-performance-capacity/cases/ntt-docomo-lemino-japanese-streaming/" data-link-title="9.C29 NTT DOCOMO Lemino：3 個月達 500 萬 MAU 的串流後端" data-link-desc="Lemino 用 DynamoDB &#43; AWS Media Services 撐 30 channels live &#43; 5M MAU、工程工時下降 90%">Lemino connection limit</a> — utilization 看似還行、但 connection saturation 已爆。</p>
<h2 id="設計責任">設計責任</h2>
<p>USE method 的關鍵是「不要只看 utilization」。utilization 是「目前用了多少」、saturation 是「排隊有多少在等」 — 後者才是 capacity 真正的領先指標。每個資源都要量三個維度、不能用 average 代替 percentile。</p>
]]></content:encoded></item><item><title>RED Method</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/red-method/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/red-method/</guid><description>&lt;p>RED method 的核心概念是「對每個 service / endpoint 量測 Rate、Errors、Duration 三個維度」。Rate 是 RPS、Errors 是錯誤率、Duration 是 latency 分布（p50 / p95 / p99 / p999）。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/use-method/" data-link-title="USE Method" data-link-desc="Brendan Gregg 提出的資源層 Utilization / Saturation / Errors 三維度量測法">USE Method&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>RED 是 request-oriented 觀察法、跟 resource-oriented 的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/use-method/" data-link-title="USE Method" data-link-desc="Brendan Gregg 提出的資源層 Utilization / Saturation / Errors 三維度量測法">USE method&lt;/a> 互補。USE 看「資源層」、RED 看「業務層」。Duration 變差通常先於 Errors 出現 — 是 capacity 接近 saturation 的早期警訊。可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>RED 三維度的典型訊號：Rate 上升、Errors 維持低、但 Duration p99 飆升 → 接近 saturation；Rate 維持、Errors 飆升 → downstream 出問題（不是容量議題）。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/gr8-tech-ai-predicted-betting-peak/" data-link-title="9.C2 GR8 Tech：AI 預測式自動擴容下的體育博彩高峰" data-link-desc="AI 預測 &amp;#43; EKS 自動擴容怎麼在 25ms p95 下承載 54000 TPS 體育博彩峰值流量">GR8 Tech 25ms p95&lt;/a> — 把 p95 變業務 KPI 而非技術指標。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>每個 service / endpoint 必須有獨立 RED dashboard、不能只看全站 average。Duration 必須記錄分布（histogram）而非單一 percentile、否則無法做 long-tail 分析。RED metrics 通常驅動 SLO；duration 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">latency budget&lt;/a> 對接。&lt;/p></description><content:encoded><![CDATA[<p>RED method 的核心概念是「對每個 service / endpoint 量測 Rate、Errors、Duration 三個維度」。Rate 是 RPS、Errors 是錯誤率、Duration 是 latency 分布（p50 / p95 / p99 / p999）。可先對照 <a href="/blog/backend/knowledge-cards/use-method/" data-link-title="USE Method" data-link-desc="Brendan Gregg 提出的資源層 Utilization / Saturation / Errors 三維度量測法">USE Method</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>RED 是 request-oriented 觀察法、跟 resource-oriented 的 <a href="/blog/backend/knowledge-cards/use-method/" data-link-title="USE Method" data-link-desc="Brendan Gregg 提出的資源層 Utilization / Saturation / Errors 三維度量測法">USE method</a> 互補。USE 看「資源層」、RED 看「業務層」。Duration 變差通常先於 Errors 出現 — 是 capacity 接近 saturation 的早期警訊。可先對照 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI / SLO</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>RED 三維度的典型訊號：Rate 上升、Errors 維持低、但 Duration p99 飆升 → 接近 saturation；Rate 維持、Errors 飆升 → downstream 出問題（不是容量議題）。對應案例：<a href="/blog/backend/09-performance-capacity/cases/gr8-tech-ai-predicted-betting-peak/" data-link-title="9.C2 GR8 Tech：AI 預測式自動擴容下的體育博彩高峰" data-link-desc="AI 預測 &#43; EKS 自動擴容怎麼在 25ms p95 下承載 54000 TPS 體育博彩峰值流量">GR8 Tech 25ms p95</a> — 把 p95 變業務 KPI 而非技術指標。</p>
<h2 id="設計責任">設計責任</h2>
<p>每個 service / endpoint 必須有獨立 RED dashboard、不能只看全站 average。Duration 必須記錄分布（histogram）而非單一 percentile、否則無法做 long-tail 分析。RED metrics 通常驅動 SLO；duration 跟 <a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">latency budget</a> 對接。</p>
]]></content:encoded></item><item><title>Workload Model</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/workload-model/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/workload-model/</guid><description>&lt;p>Workload model 的核心概念是「把 production traffic shape 量化成可重播的模型」。沒有模型、壓測結果無意義、容量規劃靠猜；有模型之後、所有效能決策都有共同的輸入。可先對照 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Workload model 至少包含五個維度：平均吞吐、peak/avg ratio、操作 mix（read / write）、cohort 分布（geographic / device / tier）、burst pattern（時間集中度）。模型可以從 production access log + APM trace 抽出來、要定期 review 因為業務變化會讓模型過時。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>模型過時的訊號是「壓測通過但 production 還是出事」。可能是 cohort 變了（VIP 用戶比例上升）、操作 mix 變了（新功能改變 read/write 比）、burst pattern 變了（新行銷活動）。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/asos-cosmos-db-black-friday/" data-link-title="9.C21 ASOS：Cosmos DB 在 Black Friday 撐 1.67 億請求" data-link-desc="ASOS 在 2016 Black Friday 用 Azure Cosmos DB 撐 24 小時 1.67 億請求、3500 req/sec、48ms 平均延遲">ASOS Black Friday 24h 1.67 億&lt;/a> 峰均比 1.81x、跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &amp;#43; 傳統伺服器當慢速消費者、承受 100K&amp;#43; 同時選位 &amp;#43; 30 秒從 6 台擴到 800 台">Tixcraft 5 分鐘賣完&lt;/a> 的極端形狀差很多。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要決定「synthetic load」vs「production traffic replay」vs「混合」。synthetic 好控制但容易脫離 reality；replay 最貼真實但消耗下游資源；混合是常見折衷。模型必須驗證：壓測 &lt;em>同時&lt;/em> 對比 production metrics、看誤差有多大。&lt;/p></description><content:encoded><![CDATA[<p>Workload model 的核心概念是「把 production traffic shape 量化成可重播的模型」。沒有模型、壓測結果無意義、容量規劃靠猜；有模型之後、所有效能決策都有共同的輸入。可先對照 <a href="/blog/backend/knowledge-cards/load-test/" data-link-title="Load Test" data-link-desc="說明在預期流量下驗證容量、延遲與降級策略的測試">Load Test</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Workload model 至少包含五個維度：平均吞吐、peak/avg ratio、操作 mix（read / write）、cohort 分布（geographic / device / tier）、burst pattern（時間集中度）。模型可以從 production access log + APM trace 抽出來、要定期 review 因為業務變化會讓模型過時。可先對照 <a href="/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>模型過時的訊號是「壓測通過但 production 還是出事」。可能是 cohort 變了（VIP 用戶比例上升）、操作 mix 變了（新功能改變 read/write 比）、burst pattern 變了（新行銷活動）。對應案例：<a href="/blog/backend/09-performance-capacity/cases/asos-cosmos-db-black-friday/" data-link-title="9.C21 ASOS：Cosmos DB 在 Black Friday 撐 1.67 億請求" data-link-desc="ASOS 在 2016 Black Friday 用 Azure Cosmos DB 撐 24 小時 1.67 億請求、3500 req/sec、48ms 平均延遲">ASOS Black Friday 24h 1.67 億</a> 峰均比 1.81x、跟 <a href="/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &#43; 傳統伺服器當慢速消費者、承受 100K&#43; 同時選位 &#43; 30 秒從 6 台擴到 800 台">Tixcraft 5 分鐘賣完</a> 的極端形狀差很多。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要決定「synthetic load」vs「production traffic replay」vs「混合」。synthetic 好控制但容易脫離 reality；replay 最貼真實但消耗下游資源；混合是常見折衷。模型必須驗證：壓測 <em>同時</em> 對比 production metrics、看誤差有多大。</p>
]]></content:encoded></item><item><title>Tail Latency</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/tail-latency/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/tail-latency/</guid><description>&lt;p>Tail latency 的核心概念是「p99 / p999 等高 percentile 的 latency 通常比 average 高一個量級、且 &lt;em>是&lt;/em> 用戶體感的決定因素」。average 看不到的 saturation、p99 早就看到了。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Tail latency 通常由以下因素貢獻：GC pause、connection pool 競爭、cache miss、cross-zone network、retry storm。average / p50 平滑掉這些 outlier、看不到 capacity 警訊；p99 / p999 直接反映「最不順的 1% / 0.1% 用戶看到什麼」。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>tail latency 飆升的訊號是「average 還行、用戶卻在抱怨慢」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/tubi-elasticache-ml-feature-store/" data-link-title="9.C25 Tubi：從 ScyllaDB 遷到 ElastiCache、ML feature store 達 sub-10ms p99" data-link-desc="Tubi 把 ML 推薦的 feature store 從 ScyllaDB 遷到 ElastiCache for Redis、99 百分位延遲降到 10ms 以下">Tubi p99 &amp;lt; 10ms&lt;/a> — ML inference 在 p99 才能控制體驗、p50 控制無意義；&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/coinbase-ultra-low-latency-exchange-2023/" data-link-title="9.C3 Coinbase International Exchange：超低延遲交易的逆向容量設計" data-link-desc="為什麼 Coinbase 國際交易所選 Cluster Placement Group &amp;#43; z1d 而不是自動擴容 — 延遲敏感型負載的容量取捨">Coinbase sub-ms&lt;/a> — RAFT 系統 p999 通常比 p99 高一個量級。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>SLO 通常訂在 p99、internal 可訂 p99.9。metrics 必須記 histogram、不是單一 percentile gauge。Java GC pause、Go GC、Node event loop lag 都可能造成 p999 異常、要單獨監控。tail latency 改善通常靠：減少 cross-zone hop、connection pool 預熱、避免 stop-the-world。&lt;/p></description><content:encoded><![CDATA[<p>Tail latency 的核心概念是「p99 / p999 等高 percentile 的 latency 通常比 average 高一個量級、且 <em>是</em> 用戶體感的決定因素」。average 看不到的 saturation、p99 早就看到了。可先對照 <a href="/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Tail latency 通常由以下因素貢獻：GC pause、connection pool 競爭、cache miss、cross-zone network、retry storm。average / p50 平滑掉這些 outlier、看不到 capacity 警訊；p99 / p999 直接反映「最不順的 1% / 0.1% 用戶看到什麼」。可先對照 <a href="/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>tail latency 飆升的訊號是「average 還行、用戶卻在抱怨慢」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/tubi-elasticache-ml-feature-store/" data-link-title="9.C25 Tubi：從 ScyllaDB 遷到 ElastiCache、ML feature store 達 sub-10ms p99" data-link-desc="Tubi 把 ML 推薦的 feature store 從 ScyllaDB 遷到 ElastiCache for Redis、99 百分位延遲降到 10ms 以下">Tubi p99 &lt; 10ms</a> — ML inference 在 p99 才能控制體驗、p50 控制無意義；<a href="/blog/backend/09-performance-capacity/cases/coinbase-ultra-low-latency-exchange-2023/" data-link-title="9.C3 Coinbase International Exchange：超低延遲交易的逆向容量設計" data-link-desc="為什麼 Coinbase 國際交易所選 Cluster Placement Group &#43; z1d 而不是自動擴容 — 延遲敏感型負載的容量取捨">Coinbase sub-ms</a> — RAFT 系統 p999 通常比 p99 高一個量級。</p>
<h2 id="設計責任">設計責任</h2>
<p>SLO 通常訂在 p99、internal 可訂 p99.9。metrics 必須記 histogram、不是單一 percentile gauge。Java GC pause、Go GC、Node event loop lag 都可能造成 p999 異常、要單獨監控。tail latency 改善通常靠：減少 cross-zone hop、connection pool 預熱、避免 stop-the-world。</p>
]]></content:encoded></item><item><title>Hot Partition</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/hot-partition/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/hot-partition/</guid><description>&lt;p>Hot partition 的核心概念是「partition 之間流量不均、最熱 partition 先 saturate、整體名義容量達不到」。partition key 設計不均勻是主因。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>DynamoDB / Cosmos DB / Bigtable / Cassandra 都用 partition 拆分資料、容量上限 = 每 partition 上限 × partition 數。但若 partition key 集中在少數 key（例如 event_id 一個演唱會、user_id 一個爆紅 KOL）、實際容量遠低於名義。Aurora / 傳統 RDB 沒 partition 抽象、但 hot row（高頻寫的單列）會引發 lock contention、效果類似。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>hot partition 的訊號是「整體 utilization 低、但 throughput 上不去 + p99 latency 飆」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/amazon-ads-dynamodb-extreme-kv/" data-link-title="9.C5 Amazon Ads：DynamoDB 9000 萬 reads/sec 的廣告事件量測" data-link-desc="Amazon Ads 在 DynamoDB 上跑 9000 萬 reads/sec &amp;#43; 500 萬 writes/sec、99.999% 可用性的廣告事件量測">Amazon Ads 9000 萬 RPS&lt;/a> — partition key 設計均勻避免 hot；&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &amp;#43; 傳統伺服器當慢速消費者、承受 100K&amp;#43; 同時選位 &amp;#43; 30 秒從 6 台擴到 800 台">Tixcraft 售票&lt;/a> — 同一場演唱會（event_id）天然容易 hot、必須用 composite key 或 write sharding 分散。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 partition key 時、要主動評估「在最壞場景下、單一 partition 會吃多少流量」。常見手段：composite key（event_id + user_id_hash）、write sharding（event_id + random_suffix）、time-bucket（event_id + minute）。發現 hot partition 後、resharding 通常是高成本工程、要在設計初期避免。&lt;/p></description><content:encoded><![CDATA[<p>Hot partition 的核心概念是「partition 之間流量不均、最熱 partition 先 saturate、整體名義容量達不到」。partition key 設計不均勻是主因。可先對照 <a href="/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>DynamoDB / Cosmos DB / Bigtable / Cassandra 都用 partition 拆分資料、容量上限 = 每 partition 上限 × partition 數。但若 partition key 集中在少數 key（例如 event_id 一個演唱會、user_id 一個爆紅 KOL）、實際容量遠低於名義。Aurora / 傳統 RDB 沒 partition 抽象、但 hot row（高頻寫的單列）會引發 lock contention、效果類似。可先對照 <a href="/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>hot partition 的訊號是「整體 utilization 低、但 throughput 上不去 + p99 latency 飆」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/amazon-ads-dynamodb-extreme-kv/" data-link-title="9.C5 Amazon Ads：DynamoDB 9000 萬 reads/sec 的廣告事件量測" data-link-desc="Amazon Ads 在 DynamoDB 上跑 9000 萬 reads/sec &#43; 500 萬 writes/sec、99.999% 可用性的廣告事件量測">Amazon Ads 9000 萬 RPS</a> — partition key 設計均勻避免 hot；<a href="/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &#43; 傳統伺服器當慢速消費者、承受 100K&#43; 同時選位 &#43; 30 秒從 6 台擴到 800 台">Tixcraft 售票</a> — 同一場演唱會（event_id）天然容易 hot、必須用 composite key 或 write sharding 分散。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 partition key 時、要主動評估「在最壞場景下、單一 partition 會吃多少流量」。常見手段：composite key（event_id + user_id_hash）、write sharding（event_id + random_suffix）、time-bucket（event_id + minute）。發現 hot partition 後、resharding 通常是高成本工程、要在設計初期避免。</p>
]]></content:encoded></item><item><title>Peak Forecast</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/peak-forecast/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/peak-forecast/</guid><description>&lt;p>Peak forecast 的核心概念是「估計未來 N 個月的峰值流量」。容量公式 = 預期峰值 × (1 + headroom)、forecast 錯了下游全部錯。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/headroom-budget/" data-link-title="Headroom Budget" data-link-desc="說明容量規劃中為應付異常 burst &amp;#43; AZ 故障 &amp;#43; forecast 誤差的安全餘量">Headroom Budget&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Forecast 方法分三層：歷史線性外推（適合 sustained growth）、季節性分解（STL，適合電商 / 串流）、業務 ML 模型（結合 marketing pipeline、新用戶獲取、留存）。最常見錯誤是「拿去年同期 × (1 + 預期成長 %)」 — 忽略產品改動 + 行銷投入變化 + 外部事件。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/headroom-budget/" data-link-title="Headroom Budget" data-link-desc="說明容量規劃中為應付異常 burst &amp;#43; AZ 故障 &amp;#43; forecast 誤差的安全餘量">Headroom Budget&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要重新 forecast 的訊號是「上次 forecast 跟實際差超過 20%」或「業務有重大改動」（新 feature、新市場、新合作）。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/disney-plus-content-metadata/" data-link-title="9.C27 Disney&amp;#43;：DynamoDB 撐每日數十億動作的觀看歷史" data-link-desc="Disney&amp;#43; 用 DynamoDB 撐每日數十億動作的觀看歷史、watchlist、播放進度等串流 metadata">Disney+ 新片發布&lt;/a> 內容型 forecast；&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/zoom-covid-surge-dynamodb/" data-link-title="9.C18 Zoom：COVID 期間從 1000 萬到 3 億 DAU 的 30 倍突發" data-link-desc="Zoom 在 2020 年 COVID 爆發時、日活從 1000 萬衝到 3 億、用 DynamoDB 撐住會議後端">Zoom 30x COVID&lt;/a> 外部衝擊讓 forecast 完全失效、必須 reset baseline。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Forecast 必須有 &lt;em>誤差範圍&lt;/em>、不能單一數字。給上下界（最壞 / 預期 / 最好）、容量規劃才能用 worst-case 訂 baseline。事件型 forecast 要按 tier 分級（regular / major / critical）、不同 tier 對應不同準備強度。Forecast 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/headroom-budget/" data-link-title="Headroom Budget" data-link-desc="說明容量規劃中為應付異常 burst &amp;#43; AZ 故障 &amp;#43; forecast 誤差的安全餘量">headroom budget&lt;/a> 一起算才有意義。&lt;/p></description><content:encoded><![CDATA[<p>Peak forecast 的核心概念是「估計未來 N 個月的峰值流量」。容量公式 = 預期峰值 × (1 + headroom)、forecast 錯了下游全部錯。可先對照 <a href="/blog/backend/knowledge-cards/headroom-budget/" data-link-title="Headroom Budget" data-link-desc="說明容量規劃中為應付異常 burst &#43; AZ 故障 &#43; forecast 誤差的安全餘量">Headroom Budget</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Forecast 方法分三層：歷史線性外推（適合 sustained growth）、季節性分解（STL，適合電商 / 串流）、業務 ML 模型（結合 marketing pipeline、新用戶獲取、留存）。最常見錯誤是「拿去年同期 × (1 + 預期成長 %)」 — 忽略產品改動 + 行銷投入變化 + 外部事件。可先對照 <a href="/blog/backend/knowledge-cards/headroom-budget/" data-link-title="Headroom Budget" data-link-desc="說明容量規劃中為應付異常 burst &#43; AZ 故障 &#43; forecast 誤差的安全餘量">Headroom Budget</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要重新 forecast 的訊號是「上次 forecast 跟實際差超過 20%」或「業務有重大改動」（新 feature、新市場、新合作）。對應案例：<a href="/blog/backend/09-performance-capacity/cases/disney-plus-content-metadata/" data-link-title="9.C27 Disney&#43;：DynamoDB 撐每日數十億動作的觀看歷史" data-link-desc="Disney&#43; 用 DynamoDB 撐每日數十億動作的觀看歷史、watchlist、播放進度等串流 metadata">Disney+ 新片發布</a> 內容型 forecast；<a href="/blog/backend/09-performance-capacity/cases/zoom-covid-surge-dynamodb/" data-link-title="9.C18 Zoom：COVID 期間從 1000 萬到 3 億 DAU 的 30 倍突發" data-link-desc="Zoom 在 2020 年 COVID 爆發時、日活從 1000 萬衝到 3 億、用 DynamoDB 撐住會議後端">Zoom 30x COVID</a> 外部衝擊讓 forecast 完全失效、必須 reset baseline。</p>
<h2 id="設計責任">設計責任</h2>
<p>Forecast 必須有 <em>誤差範圍</em>、不能單一數字。給上下界（最壞 / 預期 / 最好）、容量規劃才能用 worst-case 訂 baseline。事件型 forecast 要按 tier 分級（regular / major / critical）、不同 tier 對應不同準備強度。Forecast 跟 <a href="/blog/backend/knowledge-cards/headroom-budget/" data-link-title="Headroom Budget" data-link-desc="說明容量規劃中為應付異常 burst &#43; AZ 故障 &#43; forecast 誤差的安全餘量">headroom budget</a> 一起算才有意義。</p>
]]></content:encoded></item><item><title>Headroom Budget</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/headroom-budget/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/headroom-budget/</guid><description>&lt;p>Headroom budget 的核心概念是「預期峰值之上、額外預留多少 capacity 應付異常」。常見 30-50%、不同工作負載比例不同。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Headroom 不是 over-provisioning 浪費、是容量規劃的安全邊界。三個動機：forecast 誤差（預測本身有 ±X% 誤差）、burst pattern（瞬間 spike 超過 average peak）、AZ / region failover（一個 AZ 掛、剩下兩個要承擔全部）。Stateless service 通常 30%、DB 50%、broker 60%。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Headroom 不足的訊號是「peak 期間 utilization 接近 80%、autoscaler 還沒反應」或「single AZ 故障演練時、其他 AZ 撐不住」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/gr8-tech-ai-predicted-betting-peak/" data-link-title="9.C2 GR8 Tech：AI 預測式自動擴容下的體育博彩高峰" data-link-desc="AI 預測 &amp;#43; EKS 自動擴容怎麼在 25ms p95 下承載 54000 TPS 體育博彩峰值流量">GR8 Tech AI 預測&lt;/a> — 預測準了可以降 headroom 比例、預測不準必須拉高 headroom。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Headroom 不是越大越好、會推高成本。要算 &lt;em>under-provisioning 成本&lt;/em>（下事故的機率 × 影響）vs &lt;em>over-provisioning 成本&lt;/em>（每月多花的錢）、找平衡點。Cost-sensitive 服務可以降 headroom 但加 reactive autoscaling；critical 服務拉高 headroom + pre-provision。每季 review headroom 比例。&lt;/p></description><content:encoded><![CDATA[<p>Headroom budget 的核心概念是「預期峰值之上、額外預留多少 capacity 應付異常」。常見 30-50%、不同工作負載比例不同。可先對照 <a href="/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Headroom 不是 over-provisioning 浪費、是容量規劃的安全邊界。三個動機：forecast 誤差（預測本身有 ±X% 誤差）、burst pattern（瞬間 spike 超過 average peak）、AZ / region failover（一個 AZ 掛、剩下兩個要承擔全部）。Stateless service 通常 30%、DB 50%、broker 60%。可先對照 <a href="/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Headroom 不足的訊號是「peak 期間 utilization 接近 80%、autoscaler 還沒反應」或「single AZ 故障演練時、其他 AZ 撐不住」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/gr8-tech-ai-predicted-betting-peak/" data-link-title="9.C2 GR8 Tech：AI 預測式自動擴容下的體育博彩高峰" data-link-desc="AI 預測 &#43; EKS 自動擴容怎麼在 25ms p95 下承載 54000 TPS 體育博彩峰值流量">GR8 Tech AI 預測</a> — 預測準了可以降 headroom 比例、預測不準必須拉高 headroom。</p>
<h2 id="設計責任">設計責任</h2>
<p>Headroom 不是越大越好、會推高成本。要算 <em>under-provisioning 成本</em>（下事故的機率 × 影響）vs <em>over-provisioning 成本</em>（每月多花的錢）、找平衡點。Cost-sensitive 服務可以降 headroom 但加 reactive autoscaling；critical 服務拉高 headroom + pre-provision。每季 review headroom 比例。</p>
]]></content:encoded></item><item><title>Predictive Scaling</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/predictive-scaling/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/predictive-scaling/</guid><description>&lt;p>Predictive scaling 的核心概念是「不等流量上來、提前根據預測擴容」。跟 reactive scaling（觀察到指標飆才擴）相反、解決 reactive 在快速 burst 場景下「來不及」的問題。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/scheduled-scaling/" data-link-title="Scheduled Scaling" data-link-desc="說明按已知時間表預先擴容的 autoscaler 模式">Scheduled Scaling&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Predictive scaling 用兩類預測：歷史模式（過去幾週同時段、同 day-of-week 的流量）跟 ML 模型（多 feature 模型、結合業務 schedule、新用戶獲取）。EC2 Auto Scaling、GCP Compute Engine Predictive Autoscaler、Azure VM Scale Sets 都支援。跟 scheduled scaling 互補 — scheduled 處理「已知時間點」、predictive 處理「常態 daily / weekly pattern」。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/scheduled-scaling/" data-link-title="Scheduled Scaling" data-link-desc="說明按已知時間表預先擴容的 autoscaler 模式">Scheduled Scaling&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 predictive 的訊號是「reactive autoscaler 反應太慢、流量上升期 latency 飆」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/gr8-tech-ai-predicted-betting-peak/" data-link-title="9.C2 GR8 Tech：AI 預測式自動擴容下的體育博彩高峰" data-link-desc="AI 預測 &amp;#43; EKS 自動擴容怎麼在 25ms p95 下承載 54000 TPS 體育博彩峰值流量">GR8 Tech AI 預測&lt;/a> — 賽事高潮預測模型、把擴容窗口縮到反應時間之內；&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/aws-prime-day-extreme-scale-2025/" data-link-title="9.C1 AWS Prime Day 2025：可預期極端峰值的 dogfood" data-link-desc="Amazon 自家服務在 Prime Day 2025 的峰值數字 — 一年一次可預期峰值的容量設計參考">Prime Day pre-scaling&lt;/a> — 結合 predictive + scheduled 兩種。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Predictive scaling 預測錯了會浪費錢（預測過高、提前擴沒用到）或失效（預測過低、流量還是衝高）。要 monitor &lt;em>預測準確度&lt;/em>、超過誤差門檻時 fallback 到 reactive。三層組合最穩：scheduled（已知大事件）+ predictive（daily pattern）+ reactive（unexpected burst）。&lt;/p></description><content:encoded><![CDATA[<p>Predictive scaling 的核心概念是「不等流量上來、提前根據預測擴容」。跟 reactive scaling（觀察到指標飆才擴）相反、解決 reactive 在快速 burst 場景下「來不及」的問題。可先對照 <a href="/blog/backend/knowledge-cards/scheduled-scaling/" data-link-title="Scheduled Scaling" data-link-desc="說明按已知時間表預先擴容的 autoscaler 模式">Scheduled Scaling</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Predictive scaling 用兩類預測：歷史模式（過去幾週同時段、同 day-of-week 的流量）跟 ML 模型（多 feature 模型、結合業務 schedule、新用戶獲取）。EC2 Auto Scaling、GCP Compute Engine Predictive Autoscaler、Azure VM Scale Sets 都支援。跟 scheduled scaling 互補 — scheduled 處理「已知時間點」、predictive 處理「常態 daily / weekly pattern」。可先對照 <a href="/blog/backend/knowledge-cards/scheduled-scaling/" data-link-title="Scheduled Scaling" data-link-desc="說明按已知時間表預先擴容的 autoscaler 模式">Scheduled Scaling</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 predictive 的訊號是「reactive autoscaler 反應太慢、流量上升期 latency 飆」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/gr8-tech-ai-predicted-betting-peak/" data-link-title="9.C2 GR8 Tech：AI 預測式自動擴容下的體育博彩高峰" data-link-desc="AI 預測 &#43; EKS 自動擴容怎麼在 25ms p95 下承載 54000 TPS 體育博彩峰值流量">GR8 Tech AI 預測</a> — 賽事高潮預測模型、把擴容窗口縮到反應時間之內；<a href="/blog/backend/09-performance-capacity/cases/aws-prime-day-extreme-scale-2025/" data-link-title="9.C1 AWS Prime Day 2025：可預期極端峰值的 dogfood" data-link-desc="Amazon 自家服務在 Prime Day 2025 的峰值數字 — 一年一次可預期峰值的容量設計參考">Prime Day pre-scaling</a> — 結合 predictive + scheduled 兩種。</p>
<h2 id="設計責任">設計責任</h2>
<p>Predictive scaling 預測錯了會浪費錢（預測過高、提前擴沒用到）或失效（預測過低、流量還是衝高）。要 monitor <em>預測準確度</em>、超過誤差門檻時 fallback 到 reactive。三層組合最穩：scheduled（已知大事件）+ predictive（daily pattern）+ reactive（unexpected burst）。</p>
]]></content:encoded></item><item><title>Scheduled Scaling</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/scheduled-scaling/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/scheduled-scaling/</guid><description>&lt;p>Scheduled scaling 的核心概念是「按已知時間表預先擴容、不等流量上來才反應」。處理「已知時間點的可預期峰值」場景。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/predictive-scaling/" data-link-title="Predictive Scaling" data-link-desc="說明用歷史模式或 ML 模型預測流量、提前擴容的 autoscaler 模式">Predictive Scaling&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Scheduled scaling 適合：年度 / 季度活動（Prime Day、Black Friday、雙 11）、賽事（NFL Super Bowl、IPL 決賽）、行銷活動（產品發布、限量優惠）、內容發布（新片首映、新章節上線）。EC2 Auto Scaling 的 scheduled action、HPA 的 cron-based scaling、DynamoDB 的 scheduled capacity 都是實作。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/predictive-scaling/" data-link-title="Predictive Scaling" data-link-desc="說明用歷史模式或 ML 模型預測流量、提前擴容的 autoscaler 模式">Predictive Scaling&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 scheduled scaling 的訊號是「事件型流量上升速度比 autoscaler 反應快」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/aws-prime-day-extreme-scale-2025/" data-link-title="9.C1 AWS Prime Day 2025：可預期極端峰值的 dogfood" data-link-desc="Amazon 自家服務在 Prime Day 2025 的峰值數字 — 一年一次可預期峰值的容量設計參考">Prime Day&lt;/a> 年增率 30-77% 提前算進容量；&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &amp;#43; 傳統伺服器當慢速消費者、承受 100K&amp;#43; 同時選位 &amp;#43; 30 秒從 6 台擴到 800 台">Tixcraft 售票&lt;/a> 開賣前 30-60 分鐘 pre-scale ELB / EC2。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Scheduled scaling 必須 &lt;em>提前足夠時間&lt;/em> 啟動、不是事件當下才擴。pre-warm window 通常 30 分鐘到 2 小時（取決於 instance boot time、cache warmup、connection pool 預熱）。事件結束後也要 &lt;em>scheduled scale down&lt;/em>、避免長期 over-provision。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/predictive-scaling/" data-link-title="Predictive Scaling" data-link-desc="說明用歷史模式或 ML 模型預測流量、提前擴容的 autoscaler 模式">predictive scaling&lt;/a> 跟 reactive scaling 三層組合最穩。&lt;/p></description><content:encoded><![CDATA[<p>Scheduled scaling 的核心概念是「按已知時間表預先擴容、不等流量上來才反應」。處理「已知時間點的可預期峰值」場景。可先對照 <a href="/blog/backend/knowledge-cards/predictive-scaling/" data-link-title="Predictive Scaling" data-link-desc="說明用歷史模式或 ML 模型預測流量、提前擴容的 autoscaler 模式">Predictive Scaling</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Scheduled scaling 適合：年度 / 季度活動（Prime Day、Black Friday、雙 11）、賽事（NFL Super Bowl、IPL 決賽）、行銷活動（產品發布、限量優惠）、內容發布（新片首映、新章節上線）。EC2 Auto Scaling 的 scheduled action、HPA 的 cron-based scaling、DynamoDB 的 scheduled capacity 都是實作。可先對照 <a href="/blog/backend/knowledge-cards/predictive-scaling/" data-link-title="Predictive Scaling" data-link-desc="說明用歷史模式或 ML 模型預測流量、提前擴容的 autoscaler 模式">Predictive Scaling</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 scheduled scaling 的訊號是「事件型流量上升速度比 autoscaler 反應快」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/aws-prime-day-extreme-scale-2025/" data-link-title="9.C1 AWS Prime Day 2025：可預期極端峰值的 dogfood" data-link-desc="Amazon 自家服務在 Prime Day 2025 的峰值數字 — 一年一次可預期峰值的容量設計參考">Prime Day</a> 年增率 30-77% 提前算進容量；<a href="/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &#43; 傳統伺服器當慢速消費者、承受 100K&#43; 同時選位 &#43; 30 秒從 6 台擴到 800 台">Tixcraft 售票</a> 開賣前 30-60 分鐘 pre-scale ELB / EC2。</p>
<h2 id="設計責任">設計責任</h2>
<p>Scheduled scaling 必須 <em>提前足夠時間</em> 啟動、不是事件當下才擴。pre-warm window 通常 30 分鐘到 2 小時（取決於 instance boot time、cache warmup、connection pool 預熱）。事件結束後也要 <em>scheduled scale down</em>、避免長期 over-provision。跟 <a href="/blog/backend/knowledge-cards/predictive-scaling/" data-link-title="Predictive Scaling" data-link-desc="說明用歷史模式或 ML 模型預測流量、提前擴容的 autoscaler 模式">predictive scaling</a> 跟 reactive scaling 三層組合最穩。</p>
]]></content:encoded></item><item><title>Growth Curve</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/growth-curve/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/growth-curve/</guid><description>&lt;p>Growth curve 的核心概念是「用戶 / 流量隨時間成長的形狀分五類：linear、step、exponential、S-curve、cyclical」。不同形狀對應不同容量規劃方法、forecast 方式跟 headroom 比例。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>Linear growth&lt;/strong>：用戶月增 X%、B2B SaaS 常見、forecast 線性外推&lt;/li>
&lt;li>&lt;strong>Step growth&lt;/strong>：每次行銷 / 活動跳一階、需要 event tier 規劃&lt;/li>
&lt;li>&lt;strong>Exponential growth&lt;/strong>：早期初創、病毒擴散、forecast 容易低估&lt;/li>
&lt;li>&lt;strong>S-curve growth&lt;/strong>：成熟產品、會 saturate、需要規劃 mature stage 容量&lt;/li>
&lt;li>&lt;strong>Cyclical&lt;/strong>：電商季節性、Black Friday + Cyber Monday + Christmas&lt;/li>
&lt;/ul>
&lt;p>可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀 growth curve 的訊號是「過去 12 個月 MAU 圖形」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/zoom-covid-surge-dynamodb/" data-link-title="9.C18 Zoom：COVID 期間從 1000 萬到 3 億 DAU 的 30 倍突發" data-link-desc="Zoom 在 2020 年 COVID 爆發時、日活從 1000 萬衝到 3 億、用 DynamoDB 撐住會議後端">Zoom COVID&lt;/a> step growth（1000 萬 → 3 億）；&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/niantic-pokemon-go-fifty-x-surge-gcp/" data-link-title="9.C8 Niantic Pokémon GO：在 GCP 上承載 50 倍突發流量" data-link-desc="Pokémon GO 上線時實際流量達原始預估 50 倍、Google CRE 怎麼即時補容量">Pokemon GO 50x surge&lt;/a> exponential 之後可能 S-curve；&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/asos-cosmos-db-black-friday/" data-link-title="9.C21 ASOS：Cosmos DB 在 Black Friday 撐 1.67 億請求" data-link-desc="ASOS 在 2016 Black Friday 用 Azure Cosmos DB 撐 24 小時 1.67 億請求、3500 req/sec、48ms 平均延遲">ASOS Black Friday&lt;/a> cyclical。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計容量規劃節奏時、要先判讀 growth curve 形狀、再選 forecast 方法。Linear 適合每月 review；step 適合 &lt;em>事件前後&lt;/em> review；exponential 適合每週 review；cyclical 適合按 cycle 規劃；S-curve 要規劃 maturation 後容量保持但成長放緩。curve 形狀變了（exponential 變 linear）也是策略訊號。&lt;/p></description><content:encoded><![CDATA[<p>Growth curve 的核心概念是「用戶 / 流量隨時間成長的形狀分五類：linear、step、exponential、S-curve、cyclical」。不同形狀對應不同容量規劃方法、forecast 方式跟 headroom 比例。可先對照 <a href="/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast</a>。</p>
<h2 id="概念位置">概念位置</h2>
<ul>
<li><strong>Linear growth</strong>：用戶月增 X%、B2B SaaS 常見、forecast 線性外推</li>
<li><strong>Step growth</strong>：每次行銷 / 活動跳一階、需要 event tier 規劃</li>
<li><strong>Exponential growth</strong>：早期初創、病毒擴散、forecast 容易低估</li>
<li><strong>S-curve growth</strong>：成熟產品、會 saturate、需要規劃 mature stage 容量</li>
<li><strong>Cyclical</strong>：電商季節性、Black Friday + Cyber Monday + Christmas</li>
</ul>
<p>可先對照 <a href="/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">Peak Forecast</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀 growth curve 的訊號是「過去 12 個月 MAU 圖形」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/zoom-covid-surge-dynamodb/" data-link-title="9.C18 Zoom：COVID 期間從 1000 萬到 3 億 DAU 的 30 倍突發" data-link-desc="Zoom 在 2020 年 COVID 爆發時、日活從 1000 萬衝到 3 億、用 DynamoDB 撐住會議後端">Zoom COVID</a> step growth（1000 萬 → 3 億）；<a href="/blog/backend/09-performance-capacity/cases/niantic-pokemon-go-fifty-x-surge-gcp/" data-link-title="9.C8 Niantic Pokémon GO：在 GCP 上承載 50 倍突發流量" data-link-desc="Pokémon GO 上線時實際流量達原始預估 50 倍、Google CRE 怎麼即時補容量">Pokemon GO 50x surge</a> exponential 之後可能 S-curve；<a href="/blog/backend/09-performance-capacity/cases/asos-cosmos-db-black-friday/" data-link-title="9.C21 ASOS：Cosmos DB 在 Black Friday 撐 1.67 億請求" data-link-desc="ASOS 在 2016 Black Friday 用 Azure Cosmos DB 撐 24 小時 1.67 億請求、3500 req/sec、48ms 平均延遲">ASOS Black Friday</a> cyclical。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計容量規劃節奏時、要先判讀 growth curve 形狀、再選 forecast 方法。Linear 適合每月 review；step 適合 <em>事件前後</em> review；exponential 適合每週 review；cyclical 適合按 cycle 規劃；S-curve 要規劃 maturation 後容量保持但成長放緩。curve 形狀變了（exponential 變 linear）也是策略訊號。</p>
]]></content:encoded></item><item><title>Shadow Traffic</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/shadow-traffic/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/shadow-traffic/</guid><description>&lt;p>Shadow traffic 的核心概念是「production traffic 同時送到舊版本跟新版本、但只把舊版本的結果返回用戶、新版本的結果只用來驗證」。用戶感受不變、新版本實測 production load。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dark-launch/" data-link-title="Dark Launch" data-link-desc="新功能上線但暫不開放 UI 入口、走 production traffic 但對用戶不可見的發布模式">Dark Launch&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Shadow traffic 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/shadow-read/" data-link-title="Shadow Read" data-link-desc="說明正式讀取仍走舊路徑時如何暗中讀新路徑比對結果">shadow read&lt;/a> 不同 — shadow read 是 DB 層 replica；shadow traffic 是 application 層 traffic mirror。實作方法：GoReplay、service mesh shadow（Istio mirror）、AWS VPC Traffic Mirroring、自管 reverse proxy with mirror config。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dark-launch/" data-link-title="Dark Launch" data-link-desc="新功能上線但暫不開放 UI 入口、走 production traffic 但對用戶不可見的發布模式">Dark Launch&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 shadow traffic 的訊號是「想驗證新架構是否能撐 production load、但不能讓用戶受影響」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &amp;#43; 傳統伺服器當慢速消費者、承受 100K&amp;#43; 同時選位 &amp;#43; 30 秒從 6 台擴到 800 台">Tixcraft 10K t2.micro 壓測&lt;/a> — pre-event 壓測但走 staging；real shadow 則是 production-traffic-driven。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Shadow traffic 也消耗 production 下游資源（DB write、API call、external service）— 必須算進容量。如果新版本寫入會影響真實狀態（payment、order），必須設計成 &lt;em>dry-run&lt;/em> 或寫入 isolated sandbox。Shadow 通常跑 1-7 天看 long-tail 訊號、不是 30 分鐘就下結論。&lt;/p></description><content:encoded><![CDATA[<p>Shadow traffic 的核心概念是「production traffic 同時送到舊版本跟新版本、但只把舊版本的結果返回用戶、新版本的結果只用來驗證」。用戶感受不變、新版本實測 production load。可先對照 <a href="/blog/backend/knowledge-cards/dark-launch/" data-link-title="Dark Launch" data-link-desc="新功能上線但暫不開放 UI 入口、走 production traffic 但對用戶不可見的發布模式">Dark Launch</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Shadow traffic 跟 <a href="/blog/backend/knowledge-cards/shadow-read/" data-link-title="Shadow Read" data-link-desc="說明正式讀取仍走舊路徑時如何暗中讀新路徑比對結果">shadow read</a> 不同 — shadow read 是 DB 層 replica；shadow traffic 是 application 層 traffic mirror。實作方法：GoReplay、service mesh shadow（Istio mirror）、AWS VPC Traffic Mirroring、自管 reverse proxy with mirror config。可先對照 <a href="/blog/backend/knowledge-cards/dark-launch/" data-link-title="Dark Launch" data-link-desc="新功能上線但暫不開放 UI 入口、走 production traffic 但對用戶不可見的發布模式">Dark Launch</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 shadow traffic 的訊號是「想驗證新架構是否能撐 production load、但不能讓用戶受影響」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/tixcraft-ticketing-flash-sale-spike/" data-link-title="9.C15 拓元 Tixcraft：售票搶購的瞬間爆量架構" data-link-desc="拓元用 DynamoDB 當寫入緩衝 &#43; 傳統伺服器當慢速消費者、承受 100K&#43; 同時選位 &#43; 30 秒從 6 台擴到 800 台">Tixcraft 10K t2.micro 壓測</a> — pre-event 壓測但走 staging；real shadow 則是 production-traffic-driven。</p>
<h2 id="設計責任">設計責任</h2>
<p>Shadow traffic 也消耗 production 下游資源（DB write、API call、external service）— 必須算進容量。如果新版本寫入會影響真實狀態（payment、order），必須設計成 <em>dry-run</em> 或寫入 isolated sandbox。Shadow 通常跑 1-7 天看 long-tail 訊號、不是 30 分鐘就下結論。</p>
]]></content:encoded></item><item><title>Dark Launch</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/dark-launch/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/dark-launch/</guid><description>&lt;p>Dark launch 的核心概念是「程式碼上線、走 production traffic、但用戶看不到 UI 入口」。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/shadow-traffic/" data-link-title="Shadow Traffic" data-link-desc="把 production traffic 複製到新版本驗證、但不返回結果給用戶的測試模式">shadow traffic&lt;/a> 不同 — dark launch 是 &lt;em>真正寫入 production&lt;/em>、shadow 只是複製比對。可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Dark launch 用 feature flag 控制 UI 暴露、後端走 production traffic（從內部 API、cron job、employee-only access 等觸發）。目的是先驗證後端在 production 規模下穩定、再開放給用戶。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/shadow-traffic/" data-link-title="Shadow Traffic" data-link-desc="把 production traffic 複製到新版本驗證、但不返回結果給用戶的測試模式">shadow traffic&lt;/a> 的差別是「shadow 不寫入真實狀態、dark launch 寫入但用戶看不到」。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/canary-perf-check/" data-link-title="Canary Perf Check" data-link-desc="canary release 中針對 latency / throughput 而非 error rate 的退化檢查">Canary Perf Check&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 dark launch 的訊號是「新功能後端有風險、想先 production-validate 再 ui-launch」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/seatgeek-virtual-waiting-room/" data-link-title="9.C16 SeatGeek：DynamoDB &amp;#43; Lambda 打造的虛擬等候室" data-link-desc="SeatGeek 用 DynamoDB 4 張表 &amp;#43; Lambda Bouncer 實作 flash-sale 限流排隊機制、取代第三方 waiting room 服務">SeatGeek Virtual Waiting Room&lt;/a> 從第三方換到自建、必然有 dark launch 階段驗證 token 配發機制。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Dark launch 必須有清楚的 &lt;em>exit criteria&lt;/em>：穩定多久、誤差多少、可以開放 UI。要 monitor 後端 metric、用戶 metric 還沒意義。Dark launch 期間如果後端有 side effect（DB write、external API call），要算進容量規劃。&lt;/p></description><content:encoded><![CDATA[<p>Dark launch 的核心概念是「程式碼上線、走 production traffic、但用戶看不到 UI 入口」。跟 <a href="/blog/backend/knowledge-cards/shadow-traffic/" data-link-title="Shadow Traffic" data-link-desc="把 production traffic 複製到新版本驗證、但不返回結果給用戶的測試模式">shadow traffic</a> 不同 — dark launch 是 <em>真正寫入 production</em>、shadow 只是複製比對。可先對照 <a href="/blog/backend/knowledge-cards/feature-flag/" data-link-title="Feature Flag" data-link-desc="說明如何用可動態開關控制功能曝光與風險">Feature Flag</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Dark launch 用 feature flag 控制 UI 暴露、後端走 production traffic（從內部 API、cron job、employee-only access 等觸發）。目的是先驗證後端在 production 規模下穩定、再開放給用戶。跟 <a href="/blog/backend/knowledge-cards/shadow-traffic/" data-link-title="Shadow Traffic" data-link-desc="把 production traffic 複製到新版本驗證、但不返回結果給用戶的測試模式">shadow traffic</a> 的差別是「shadow 不寫入真實狀態、dark launch 寫入但用戶看不到」。可先對照 <a href="/blog/backend/knowledge-cards/canary-perf-check/" data-link-title="Canary Perf Check" data-link-desc="canary release 中針對 latency / throughput 而非 error rate 的退化檢查">Canary Perf Check</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 dark launch 的訊號是「新功能後端有風險、想先 production-validate 再 ui-launch」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/seatgeek-virtual-waiting-room/" data-link-title="9.C16 SeatGeek：DynamoDB &#43; Lambda 打造的虛擬等候室" data-link-desc="SeatGeek 用 DynamoDB 4 張表 &#43; Lambda Bouncer 實作 flash-sale 限流排隊機制、取代第三方 waiting room 服務">SeatGeek Virtual Waiting Room</a> 從第三方換到自建、必然有 dark launch 階段驗證 token 配發機制。</p>
<h2 id="設計責任">設計責任</h2>
<p>Dark launch 必須有清楚的 <em>exit criteria</em>：穩定多久、誤差多少、可以開放 UI。要 monitor 後端 metric、用戶 metric 還沒意義。Dark launch 期間如果後端有 side effect（DB write、external API call），要算進容量規劃。</p>
]]></content:encoded></item><item><title>Canary Perf Check</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/canary-perf-check/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/canary-perf-check/</guid><description>&lt;p>Canary perf check 的核心概念是「canary 階段不只看 error rate、也看 latency / throughput / resource utilization 退化」。傳統 canary 看 error rate、但 perf 退化通常先於 error 出現、是更早的警訊。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/profile-diff/" data-link-title="Profile Diff" data-link-desc="對比兩次 profile（如 release candidate vs baseline）找出 hottest 變化">Profile Diff&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Canary 流量導 1% / 5% / 10% 到新版本、跟 control（舊版本）流量比較 p50 / p95 / p99 / p999 latency 分布、throughput rate、resource saturation。自動 rollback 條件：canary p99 比 control 退化 &amp;gt; X%。漸進放大：通過 1% → 5% → 25% → 50% → 100%。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/profile-diff/" data-link-title="Profile Diff" data-link-desc="對比兩次 profile（如 release candidate vs baseline）找出 hottest 變化">Profile Diff&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 canary perf check 的訊號是「release 後 latency 飆但 error 沒事、用戶體驗悄悄變差」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/aws-prime-day-extreme-scale-2025/" data-link-title="9.C1 AWS Prime Day 2025：可預期極端峰值的 dogfood" data-link-desc="Amazon 自家服務在 Prime Day 2025 的峰值數字 — 一年一次可預期峰值的容量設計參考">Prime Day pre-event 驗證&lt;/a> / &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/fanduel-dual-peak-betting-streaming/" data-link-title="9.C28 FanDuel：體育直播 &amp;#43; 投注的雙重峰值" data-link-desc="FanDuel 3.5M MAU、Super Bowl 期間擴容 5-10 倍、用 AWS Local Zones &amp;#43; Wavelength &amp;#43; Outposts 處理 20&amp;#43; 州的雙重峰值">FanDuel canary across 20 州&lt;/a>。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Canary perf check 的關鍵是 &lt;em>跟 control 比、不是跟 baseline 比&lt;/em>。同樣流量同樣時段、不同版本的差才有意義。abort condition 要事前訂、不要事中決定。Canary 流量比例要看 &lt;em>退化 blast radius&lt;/em> — 1% 流量退化 30%、影響 0.3% 用戶；50% 流量退化 30%、影響 15% 用戶。&lt;/p></description><content:encoded><![CDATA[<p>Canary perf check 的核心概念是「canary 階段不只看 error rate、也看 latency / throughput / resource utilization 退化」。傳統 canary 看 error rate、但 perf 退化通常先於 error 出現、是更早的警訊。可先對照 <a href="/blog/backend/knowledge-cards/profile-diff/" data-link-title="Profile Diff" data-link-desc="對比兩次 profile（如 release candidate vs baseline）找出 hottest 變化">Profile Diff</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Canary 流量導 1% / 5% / 10% 到新版本、跟 control（舊版本）流量比較 p50 / p95 / p99 / p999 latency 分布、throughput rate、resource saturation。自動 rollback 條件：canary p99 比 control 退化 &gt; X%。漸進放大：通過 1% → 5% → 25% → 50% → 100%。可先對照 <a href="/blog/backend/knowledge-cards/profile-diff/" data-link-title="Profile Diff" data-link-desc="對比兩次 profile（如 release candidate vs baseline）找出 hottest 變化">Profile Diff</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 canary perf check 的訊號是「release 後 latency 飆但 error 沒事、用戶體驗悄悄變差」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/aws-prime-day-extreme-scale-2025/" data-link-title="9.C1 AWS Prime Day 2025：可預期極端峰值的 dogfood" data-link-desc="Amazon 自家服務在 Prime Day 2025 的峰值數字 — 一年一次可預期峰值的容量設計參考">Prime Day pre-event 驗證</a> / <a href="/blog/backend/09-performance-capacity/cases/fanduel-dual-peak-betting-streaming/" data-link-title="9.C28 FanDuel：體育直播 &#43; 投注的雙重峰值" data-link-desc="FanDuel 3.5M MAU、Super Bowl 期間擴容 5-10 倍、用 AWS Local Zones &#43; Wavelength &#43; Outposts 處理 20&#43; 州的雙重峰值">FanDuel canary across 20 州</a>。</p>
<h2 id="設計責任">設計責任</h2>
<p>Canary perf check 的關鍵是 <em>跟 control 比、不是跟 baseline 比</em>。同樣流量同樣時段、不同版本的差才有意義。abort condition 要事前訂、不要事中決定。Canary 流量比例要看 <em>退化 blast radius</em> — 1% 流量退化 30%、影響 0.3% 用戶；50% 流量退化 30%、影響 15% 用戶。</p>
]]></content:encoded></item><item><title>Canary Release</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/canary-release/</link><pubDate>Tue, 23 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/canary-release/</guid><description>&lt;p>Canary release 的核心概念是「先把小比例流量導向新版本、觀察行為、再決定是否擴大」。它把版本切換從一次性決策變成連續多批決策，每批都有明確的觀察窗口與停損條件。可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Canary release 位在 &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/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">release gate&lt;/a> 之間。Rolling update 是逐批替換實例的機制，canary 是在替換過程中加入「先驗證再擴批」的決策層。Release gate 是每批擴大前的放行條件。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/canary-perf-check/" data-link-title="Canary Perf Check" data-link-desc="canary release 中針對 latency / throughput 而非 error rate 的退化檢查">Canary Perf Check&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 canary release 的訊號是「版本切換需要控制 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius&lt;/a>」。判讀要維持 per-version 視角——只看整體平均值會掩蓋新版本的局部退化。常見 stop condition 包含 per-version error rate 偏離、p95/p99 latency 惡化、依賴 timeout 連續超門檻、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining&lt;/a> 未完成。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Canary release 要定義三件事：切換單位（比例 / 區域 / 租戶 / 路由規則）、每批觀察窗口與停損條件、回退路徑（舊版本是否仍能承接回退流量）。效能退化的檢查見 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/canary-perf-check/" data-link-title="Canary Perf Check" data-link-desc="canary release 中針對 latency / throughput 而非 error rate 的退化檢查">Canary Perf Check&lt;/a>。Canary 決策的 evidence 格式見 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">Evidence Package&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Canary release 的核心概念是「先把小比例流量導向新版本、觀察行為、再決定是否擴大」。它把版本切換從一次性決策變成連續多批決策，每批都有明確的觀察窗口與停損條件。可先對照 <a href="/blog/backend/knowledge-cards/rolling-update/" data-link-title="Rolling Update" data-link-desc="說明逐批替換服務版本的發版策略與風險控制">Rolling Update</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Canary release 位在 <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/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">release gate</a> 之間。Rolling update 是逐批替換實例的機制，canary 是在替換過程中加入「先驗證再擴批」的決策層。Release gate 是每批擴大前的放行條件。可先對照 <a href="/blog/backend/knowledge-cards/canary-perf-check/" data-link-title="Canary Perf Check" data-link-desc="canary release 中針對 latency / throughput 而非 error rate 的退化檢查">Canary Perf Check</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 canary release 的訊號是「版本切換需要控制 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius</a>」。判讀要維持 per-version 視角——只看整體平均值會掩蓋新版本的局部退化。常見 stop condition 包含 per-version error rate 偏離、p95/p99 latency 惡化、依賴 timeout 連續超門檻、<a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining</a> 未完成。</p>
<h2 id="設計責任">設計責任</h2>
<p>Canary release 要定義三件事：切換單位（比例 / 區域 / 租戶 / 路由規則）、每批觀察窗口與停損條件、回退路徑（舊版本是否仍能承接回退流量）。效能退化的檢查見 <a href="/blog/backend/knowledge-cards/canary-perf-check/" data-link-title="Canary Perf Check" data-link-desc="canary release 中針對 latency / throughput 而非 error rate 的退化檢查">Canary Perf Check</a>。Canary 決策的 evidence 格式見 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">Evidence Package</a>。</p>
]]></content:encoded></item><item><title>Profile Diff</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/profile-diff/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/profile-diff/</guid><description>&lt;p>Profile diff 的核心概念是「兩次 profile 取得後、用差分視覺化找出 &lt;em>相對變化最大&lt;/em> 的 code path」。比看絕對值更能定位退化原因。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/continuous-profiling/" data-link-title="Continuous Profiling" data-link-desc="在 production 持續取得低 overhead profile 的觀察方法">Continuous Profiling&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Profile diff 的常見實作：Brendan Gregg 的 differential flame graph、Pyroscope diff、Datadog Continuous Profiler diff、Parca compare。輸入是兩個 profile（同樣 sampling 條件下取得）、輸出是「新版本比舊版本多花了多少 CPU / memory / lock time」。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/continuous-profiling/" data-link-title="Continuous Profiling" data-link-desc="在 production 持續取得低 overhead profile 的觀察方法">Continuous Profiling&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 profile diff 的訊號是「release 後 latency 退化、不知道是哪段 code 拖累」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &amp;#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">Netflix Aurora 統一&lt;/a> — DB 層統一後 profile 變單純、profile diff 更容易識別 application 層的退化來源。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Profile diff 必須在 &lt;em>相同負載 + 相同硬體 + 相同 sampling rate&lt;/em> 下取得、否則結果無意義。看「相對變化幅度」而非絕對 CPU%。Diff 結果通常需要工程師判讀、不能純自動化判斷退化是否可接受 — 因為「多花 20% CPU 但 throughput 多 50%」可能是 &lt;em>好變化&lt;/em>。&lt;/p></description><content:encoded><![CDATA[<p>Profile diff 的核心概念是「兩次 profile 取得後、用差分視覺化找出 <em>相對變化最大</em> 的 code path」。比看絕對值更能定位退化原因。可先對照 <a href="/blog/backend/knowledge-cards/continuous-profiling/" data-link-title="Continuous Profiling" data-link-desc="在 production 持續取得低 overhead profile 的觀察方法">Continuous Profiling</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Profile diff 的常見實作：Brendan Gregg 的 differential flame graph、Pyroscope diff、Datadog Continuous Profiler diff、Parca compare。輸入是兩個 profile（同樣 sampling 條件下取得）、輸出是「新版本比舊版本多花了多少 CPU / memory / lock time」。可先對照 <a href="/blog/backend/knowledge-cards/continuous-profiling/" data-link-title="Continuous Profiling" data-link-desc="在 production 持續取得低 overhead profile 的觀察方法">Continuous Profiling</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 profile diff 的訊號是「release 後 latency 退化、不知道是哪段 code 拖累」。對應案例：<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%、串流數十億小時">Netflix Aurora 統一</a> — DB 層統一後 profile 變單純、profile diff 更容易識別 application 層的退化來源。</p>
<h2 id="設計責任">設計責任</h2>
<p>Profile diff 必須在 <em>相同負載 + 相同硬體 + 相同 sampling rate</em> 下取得、否則結果無意義。看「相對變化幅度」而非絕對 CPU%。Diff 結果通常需要工程師判讀、不能純自動化判斷退化是否可接受 — 因為「多花 20% CPU 但 throughput 多 50%」可能是 <em>好變化</em>。</p>
]]></content:encoded></item><item><title>Continuous Profiling</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/continuous-profiling/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/continuous-profiling/</guid><description>&lt;p>Continuous profiling 的核心概念是「在 production 持續以低 overhead 採集 CPU / heap / lock profile，讓 baseline 隨時可用、不需要等事故才開 profiler」。它是 &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> 之外能精確到 callstack level 的觀測訊號。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Continuous profiling 是 &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/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log&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> 之外的第四角觀測訊號。Metrics 告訴你「CPU usage 上升了」，trace 告訴你「某條 request 變慢」，profile 告訴你「變慢的那段程式碼是哪幾個 function call」。Profile 是唯一能精確到 callstack level 的觀測訊號。&lt;/p>
&lt;p>Always-on 的核心價值是 baseline — 事故時跟 baseline 做 diff（flame graph diff），看「哪些 function 的 CPU 消耗跟平時不同」。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>需要 continuous profiling 的訊號是「latency 退化常找不到原因、靠事後重現很慢」或「同一段 hot path 反覆出現在事故 RCA 中但缺 baseline 資料」。版本升級後 latency 退化時，profile diff 能直接定位是哪個 function 變慢。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Overhead 控制是 continuous profiling 可行性的前提 — CPU overhead &amp;lt; 1%、memory overhead &amp;lt; 10MB。eBPF-based profiler（Parca、Pyroscope eBPF）在 kernel 層採集、overhead 最低；language runtime 內建（Go pprof、Java JFR）居中。Profile 資料要帶 service / version / region label，讓跨版本 diff 跟 canary 對照可行。完整設計見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/continuous-profiling/" data-link-title="4.9 Continuous Profiling" data-link-desc="把 CPU / memory / lock profile 從一次性除錯升級為持續訊號">4.9 continuous profiling&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Continuous profiling 的核心概念是「在 production 持續以低 overhead 採集 CPU / heap / lock profile，讓 baseline 隨時可用、不需要等事故才開 profiler」。它是 <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> 之外能精確到 callstack level 的觀測訊號。</p>
<h2 id="概念位置">概念位置</h2>
<p>Continuous profiling 是 <a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics</a>、<a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a>、<a href="/blog/backend/knowledge-cards/trace/" data-link-title="Trace" data-link-desc="說明 trace 如何重建跨服務請求的路徑、耗時與依賴關係">trace</a> 之外的第四角觀測訊號。Metrics 告訴你「CPU usage 上升了」，trace 告訴你「某條 request 變慢」，profile 告訴你「變慢的那段程式碼是哪幾個 function call」。Profile 是唯一能精確到 callstack level 的觀測訊號。</p>
<p>Always-on 的核心價值是 baseline — 事故時跟 baseline 做 diff（flame graph diff），看「哪些 function 的 CPU 消耗跟平時不同」。</p>
<h2 id="使用情境">使用情境</h2>
<p>需要 continuous profiling 的訊號是「latency 退化常找不到原因、靠事後重現很慢」或「同一段 hot path 反覆出現在事故 RCA 中但缺 baseline 資料」。版本升級後 latency 退化時，profile diff 能直接定位是哪個 function 變慢。</p>
<h2 id="設計責任">設計責任</h2>
<p>Overhead 控制是 continuous profiling 可行性的前提 — CPU overhead &lt; 1%、memory overhead &lt; 10MB。eBPF-based profiler（Parca、Pyroscope eBPF）在 kernel 層採集、overhead 最低；language runtime 內建（Go pprof、Java JFR）居中。Profile 資料要帶 service / version / region label，讓跨版本 diff 跟 canary 對照可行。完整設計見 <a href="/blog/backend/04-observability/continuous-profiling/" data-link-title="4.9 Continuous Profiling" data-link-desc="把 CPU / memory / lock profile 從一次性除錯升級為持續訊號">4.9 continuous profiling</a>。</p>
]]></content:encoded></item><item><title>Cost Per Request</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cost-per-request/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cost-per-request/</guid><description>&lt;p>Cost per request 的核心概念是「把月帳單 / 總 RPS = 每個請求的成本」、進一步拆到每個 endpoint、每個 stage（app / DB / cache / network）。讓容量決策有 unit economics 邊界。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/headroom-budget/" data-link-title="Headroom Budget" data-link-desc="說明容量規劃中為應付異常 burst &amp;#43; AZ 故障 &amp;#43; forecast 誤差的安全餘量">Headroom Budget&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cost per request 是 FinOps 的最小單位。可以對齊業務 metric：cost per active user、cost per transaction、cost per ML inference。不同 endpoint 成本差很大：登入請求可能 $0.0001、結帳請求可能 $0.001（10x 差距）。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/headroom-budget/" data-link-title="Headroom Budget" data-link-desc="說明容量規劃中為應付異常 burst &amp;#43; AZ 故障 &amp;#43; forecast 誤差的安全餘量">Headroom Budget&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要算 cost per request 的訊號是「月帳單上升但不知道誰造成的」。對應案例：&lt;a href="https://tarrragon.github.io/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%">Zomato TiDB → DynamoDB 50% 成本降&lt;/a> — 算出每筆計費事件的成本後決定遷移；&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &amp;#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">Netflix Aurora 28% 成本降&lt;/a> — DB 層 cost-per-request 量化才能評估 consolidation 價值。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Cost per request 必須包含 &lt;em>所有 stage&lt;/em>：app compute、DB read/write、cache、network egress、第三方 API。常見漏算：跨 region egress、CloudWatch / Stackdriver / Application Insights metric 成本、log ingest 成本。每月 review、每季 right-sizing。&lt;/p></description><content:encoded><![CDATA[<p>Cost per request 的核心概念是「把月帳單 / 總 RPS = 每個請求的成本」、進一步拆到每個 endpoint、每個 stage（app / DB / cache / network）。讓容量決策有 unit economics 邊界。可先對照 <a href="/blog/backend/knowledge-cards/headroom-budget/" data-link-title="Headroom Budget" data-link-desc="說明容量規劃中為應付異常 burst &#43; AZ 故障 &#43; forecast 誤差的安全餘量">Headroom Budget</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cost per request 是 FinOps 的最小單位。可以對齊業務 metric：cost per active user、cost per transaction、cost per ML inference。不同 endpoint 成本差很大：登入請求可能 $0.0001、結帳請求可能 $0.001（10x 差距）。可先對照 <a href="/blog/backend/knowledge-cards/headroom-budget/" data-link-title="Headroom Budget" data-link-desc="說明容量規劃中為應付異常 burst &#43; AZ 故障 &#43; forecast 誤差的安全餘量">Headroom Budget</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要算 cost per request 的訊號是「月帳單上升但不知道誰造成的」。對應案例：<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%">Zomato TiDB → DynamoDB 50% 成本降</a> — 算出每筆計費事件的成本後決定遷移；<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%、串流數十億小時">Netflix Aurora 28% 成本降</a> — DB 層 cost-per-request 量化才能評估 consolidation 價值。</p>
<h2 id="設計責任">設計責任</h2>
<p>Cost per request 必須包含 <em>所有 stage</em>：app compute、DB read/write、cache、network egress、第三方 API。常見漏算：跨 region egress、CloudWatch / Stackdriver / Application Insights metric 成本、log ingest 成本。每月 review、每季 right-sizing。</p>
]]></content:encoded></item><item><title>Performance Budget</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/performance-budget/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/performance-budget/</guid><description>&lt;p>Performance budget 的核心概念是「每月有允許退化的額度、用完就 freeze new feature、focus on perf」。跟 &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> 並列、用同一套方法論處理可靠性 vs 效能。可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Performance budget 訂在 SLO baseline 之上、允許「p99 比 baseline 高 X ms 連續 Y 分鐘」這類退化額度。額度用完 → release freeze → 修完 perf 再放行。跟 error budget 互補：error budget 控制可靠性退化、performance budget 控制效能退化。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">Latency Budget&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 performance budget 的訊號是「容量規劃太死板、新功能 release 太慢」或反之「release 太快、累積 perf 退化沒人管」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/coinbase-ultra-low-latency-exchange-2023/" data-link-title="9.C3 Coinbase International Exchange：超低延遲交易的逆向容量設計" data-link-desc="為什麼 Coinbase 國際交易所選 Cluster Placement Group &amp;#43; z1d 而不是自動擴容 — 延遲敏感型負載的容量取捨">Coinbase sub-ms&lt;/a> 延遲就是收入、無 performance budget 等於無 release control；&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/fanduel-dual-peak-betting-streaming/" data-link-title="9.C28 FanDuel：體育直播 &amp;#43; 投注的雙重峰值" data-link-desc="FanDuel 3.5M MAU、Super Bowl 期間擴容 5-10 倍、用 AWS Local Zones &amp;#43; Wavelength &amp;#43; Outposts 處理 20&amp;#43; 州的雙重峰值">FanDuel 多 SLO&lt;/a> 直播 vs 投注不同 budget。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Performance budget 不是越緊越好、會 starve 產品創新。建議從 baseline + 10% headroom 開始、看 burn rate 調整。budget 用 burn rate alert（類似 error budget）、不是用門檻 alert。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">latency budget&lt;/a> 不同層：latency budget 是「每個 stage 多少 latency 配額」、performance budget 是「整體允許退化多少」。&lt;/p></description><content:encoded><![CDATA[<p>Performance budget 的核心概念是「每月有允許退化的額度、用完就 freeze new feature、focus on perf」。跟 <a href="/blog/backend/knowledge-cards/error-budget/" data-link-title="Error Budget" data-link-desc="說明 SLO 允許的失敗額度如何影響發版與可靠性投入">error budget</a> 並列、用同一套方法論處理可靠性 vs 效能。可先對照 <a href="/blog/backend/knowledge-cards/error-budget/" data-link-title="Error Budget" data-link-desc="說明 SLO 允許的失敗額度如何影響發版與可靠性投入">Error Budget</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Performance budget 訂在 SLO baseline 之上、允許「p99 比 baseline 高 X ms 連續 Y 分鐘」這類退化額度。額度用完 → release freeze → 修完 perf 再放行。跟 error budget 互補：error budget 控制可靠性退化、performance budget 控制效能退化。可先對照 <a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">Latency Budget</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 performance budget 的訊號是「容量規劃太死板、新功能 release 太慢」或反之「release 太快、累積 perf 退化沒人管」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/coinbase-ultra-low-latency-exchange-2023/" data-link-title="9.C3 Coinbase International Exchange：超低延遲交易的逆向容量設計" data-link-desc="為什麼 Coinbase 國際交易所選 Cluster Placement Group &#43; z1d 而不是自動擴容 — 延遲敏感型負載的容量取捨">Coinbase sub-ms</a> 延遲就是收入、無 performance budget 等於無 release control；<a href="/blog/backend/09-performance-capacity/cases/fanduel-dual-peak-betting-streaming/" data-link-title="9.C28 FanDuel：體育直播 &#43; 投注的雙重峰值" data-link-desc="FanDuel 3.5M MAU、Super Bowl 期間擴容 5-10 倍、用 AWS Local Zones &#43; Wavelength &#43; Outposts 處理 20&#43; 州的雙重峰值">FanDuel 多 SLO</a> 直播 vs 投注不同 budget。</p>
<h2 id="設計責任">設計責任</h2>
<p>Performance budget 不是越緊越好、會 starve 產品創新。建議從 baseline + 10% headroom 開始、看 burn rate 調整。budget 用 burn rate alert（類似 error budget）、不是用門檻 alert。跟 <a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">latency budget</a> 不同層：latency budget 是「每個 stage 多少 latency 配額」、performance budget 是「整體允許退化多少」。</p>
]]></content:encoded></item><item><title>Latency Budget</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/</guid><description>&lt;p>Latency budget 的核心概念是「給定 SLO end-to-end latency 上限、拆到每個 stage（網路 / CDN / app / cache / DB / 第三方）的配額、總和不得超過 SLO」。讓 latency 從口號變成可分解的工程目標。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/performance-budget/" data-link-title="Performance Budget" data-link-desc="跟 error budget 同類概念、但用於 latency / throughput 退化的可控額度">Performance Budget&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Latency budget 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/little-law/" data-link-title="Little&amp;#39;s Law" data-link-desc="說明系統內並發數、到達率與逗留時間三者的數學關係">Little&amp;rsquo;s Law&lt;/a> 的應用 — 給定吞吐目標 + latency 目標、反推每個 stage 的可承受 latency。常見分解：DNS 5ms + TLS 50ms + CDN 20ms + app 100ms + DB 30ms + serialization 10ms = 215ms。任何 stage 超 budget → 該 stage 必須改善。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/performance-budget/" data-link-title="Performance Budget" data-link-desc="跟 error budget 同類概念、但用於 latency / throughput 退化的可控額度">Performance Budget&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 latency budget 的訊號是「p99 latency 飆但不知道誰拖累」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/coinbase-ultra-low-latency-exchange-2023/" data-link-title="9.C3 Coinbase International Exchange：超低延遲交易的逆向容量設計" data-link-desc="為什麼 Coinbase 國際交易所選 Cluster Placement Group &amp;#43; z1d 而不是自動擴容 — 延遲敏感型負載的容量取捨">Coinbase sub-ms&lt;/a> — 從 sub-ms 反推、每個 stage 都被擠到極限（Cluster Placement Group、z1d 等）；&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/tubi-elasticache-ml-feature-store/" data-link-title="9.C25 Tubi：從 ScyllaDB 遷到 ElastiCache、ML feature store 達 sub-10ms p99" data-link-desc="Tubi 把 ML 推薦的 feature store 從 ScyllaDB 遷到 ElastiCache for Redis、99 百分位延遲降到 10ms 以下">Tubi ML p99 &amp;lt; 10ms&lt;/a> — feature lookup 10ms 內、model inference 才有預算。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Latency budget 必須 &lt;em>跟 SLO 對齊&lt;/em>、不是工程師憑感覺訂。每個 stage 的 budget 必須有 &lt;em>current measurement&lt;/em> — 不能訂了沒量。Cross-region call 自帶數十 ms 不可壓縮 latency、設計時要明確認知。任何新增 stage（middleware / sidecar / interceptor）都會吃 budget、必須評估。&lt;/p></description><content:encoded><![CDATA[<p>Latency budget 的核心概念是「給定 SLO end-to-end latency 上限、拆到每個 stage（網路 / CDN / app / cache / DB / 第三方）的配額、總和不得超過 SLO」。讓 latency 從口號變成可分解的工程目標。可先對照 <a href="/blog/backend/knowledge-cards/performance-budget/" data-link-title="Performance Budget" data-link-desc="跟 error budget 同類概念、但用於 latency / throughput 退化的可控額度">Performance Budget</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Latency budget 是 <a href="/blog/backend/knowledge-cards/little-law/" data-link-title="Little&#39;s Law" data-link-desc="說明系統內並發數、到達率與逗留時間三者的數學關係">Little&rsquo;s Law</a> 的應用 — 給定吞吐目標 + latency 目標、反推每個 stage 的可承受 latency。常見分解：DNS 5ms + TLS 50ms + CDN 20ms + app 100ms + DB 30ms + serialization 10ms = 215ms。任何 stage 超 budget → 該 stage 必須改善。可先對照 <a href="/blog/backend/knowledge-cards/performance-budget/" data-link-title="Performance Budget" data-link-desc="跟 error budget 同類概念、但用於 latency / throughput 退化的可控額度">Performance Budget</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 latency budget 的訊號是「p99 latency 飆但不知道誰拖累」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/coinbase-ultra-low-latency-exchange-2023/" data-link-title="9.C3 Coinbase International Exchange：超低延遲交易的逆向容量設計" data-link-desc="為什麼 Coinbase 國際交易所選 Cluster Placement Group &#43; z1d 而不是自動擴容 — 延遲敏感型負載的容量取捨">Coinbase sub-ms</a> — 從 sub-ms 反推、每個 stage 都被擠到極限（Cluster Placement Group、z1d 等）；<a href="/blog/backend/09-performance-capacity/cases/tubi-elasticache-ml-feature-store/" data-link-title="9.C25 Tubi：從 ScyllaDB 遷到 ElastiCache、ML feature store 達 sub-10ms p99" data-link-desc="Tubi 把 ML 推薦的 feature store 從 ScyllaDB 遷到 ElastiCache for Redis、99 百分位延遲降到 10ms 以下">Tubi ML p99 &lt; 10ms</a> — feature lookup 10ms 內、model inference 才有預算。</p>
<h2 id="設計責任">設計責任</h2>
<p>Latency budget 必須 <em>跟 SLO 對齊</em>、不是工程師憑感覺訂。每個 stage 的 budget 必須有 <em>current measurement</em> — 不能訂了沒量。Cross-region call 自帶數十 ms 不可壓縮 latency、設計時要明確認知。任何新增 stage（middleware / sidecar / interceptor）都會吃 budget、必須評估。</p>
]]></content:encoded></item><item><title>Global OLTP</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/global-oltp/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/global-oltp/</guid><description>&lt;p>Global OLTP 的核心概念是「跨 region 寫入與讀取仍維持可驗證的交易一致性」。它承擔的是跨地理距離下的正確性責任，不是單純把資料複製到多地，常依賴 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">distributed-sql&lt;/a> 或同級一致性機制。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Global OLTP 是 &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> 在多 region 場景的延伸。它通常需要 quorum、跨區時鐘或排序協議，並把跨區延遲納入設計前提。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">latency budget&lt;/a> 與可用性目標（availability target）。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 global OLTP 的訊號是「跨區交易順序錯誤會直接造成業務損失或合規風險」。例如支付、票務庫存、核心帳務。若業務可接受短暫不一致，多數情境可改用 eventual/session consistency，降低延遲與成本。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 global OLTP 時要先定義三件事：一致性目標、可接受延遲上限、區域故障下的服務策略。若無法同時滿足三者，就需要調整資料分區、交易範圍或一致性層級，而不是直接加硬體。&lt;/p></description><content:encoded><![CDATA[<p>Global OLTP 的核心概念是「跨 region 寫入與讀取仍維持可驗證的交易一致性」。它承擔的是跨地理距離下的正確性責任，不是單純把資料複製到多地，常依賴 <a href="/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">distributed-sql</a> 或同級一致性機制。</p>
<h2 id="概念位置">概念位置</h2>
<p>Global OLTP 是 <a href="/blog/backend/knowledge-cards/transaction-boundary/" data-link-title="Transaction Boundary" data-link-desc="說明哪些資料變更應在同一個交易中一起成功或一起回復">transaction boundary</a> 在多 region 場景的延伸。它通常需要 quorum、跨區時鐘或排序協議，並把跨區延遲納入設計前提。可先對照 <a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">latency budget</a> 與可用性目標（availability target）。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 global OLTP 的訊號是「跨區交易順序錯誤會直接造成業務損失或合規風險」。例如支付、票務庫存、核心帳務。若業務可接受短暫不一致，多數情境可改用 eventual/session consistency，降低延遲與成本。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 global OLTP 時要先定義三件事：一致性目標、可接受延遲上限、區域故障下的服務策略。若無法同時滿足三者，就需要調整資料分區、交易範圍或一致性層級，而不是直接加硬體。</p>
]]></content:encoded></item><item><title>SLO Baseline Drift</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/slo-baseline-drift/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/slo-baseline-drift/</guid><description>&lt;p>SLO baseline drift 的核心概念是「SLO 訂了不是永遠不動 — 業務變化、用戶習慣演變、架構升級都會讓 baseline 必須重新校準」。沒有 drift 意識、SLO 可能「太鬆失去意義」或「太緊每天 alert」。可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>SLO drift 來源：structural surge（COVID 類外部衝擊讓 baseline 永久上移）、product change（新 feature 改變用戶 journey）、architectural improvement（DB 換型、cache 加強、CDN 擴點）、user behavior（mobile share 上升、跨 region 比例變化）。drift 不是 anomaly、是 &lt;em>新常態&lt;/em>。可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要重新校準 SLO 的訊號是「最近 N 個月 burn rate 持續低於 baseline」或「持續高於 baseline 但無 incident」。對應案例：&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/zoom-covid-surge-dynamodb/" data-link-title="9.C18 Zoom：COVID 期間從 1000 萬到 3 億 DAU 的 30 倍突發" data-link-desc="Zoom 在 2020 年 COVID 爆發時、日活從 1000 萬衝到 3 億、用 DynamoDB 撐住會議後端">Zoom 30x COVID surge&lt;/a> — baseline 從 1000 萬 DAU 永久升到 3 億、SLO threshold 跟著重新校準。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>SLO 必須每季 review、不是「設定後就忘」。review 流程：拉過去 90 天 SLI 分布、看 percentile 分布是否跟 SLO 對應、看是否需要調整。drift 確認後要更新：alert threshold、autoscaler trigger、performance budget 額度、容量規劃 baseline。對應 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/performance-budget/" data-link-title="Performance Budget" data-link-desc="跟 error budget 同類概念、但用於 latency / throughput 退化的可控額度">performance budget&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>SLO baseline drift 的核心概念是「SLO 訂了不是永遠不動 — 業務變化、用戶習慣演變、架構升級都會讓 baseline 必須重新校準」。沒有 drift 意識、SLO 可能「太鬆失去意義」或「太緊每天 alert」。可先對照 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI / SLO</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>SLO drift 來源：structural surge（COVID 類外部衝擊讓 baseline 永久上移）、product change（新 feature 改變用戶 journey）、architectural improvement（DB 換型、cache 加強、CDN 擴點）、user behavior（mobile share 上升、跨 region 比例變化）。drift 不是 anomaly、是 <em>新常態</em>。可先對照 <a href="/blog/backend/knowledge-cards/sli-slo/" data-link-title="SLI / SLO" data-link-desc="說明服務品質指標與服務品質目標如何連接產品承諾">SLI / SLO</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要重新校準 SLO 的訊號是「最近 N 個月 burn rate 持續低於 baseline」或「持續高於 baseline 但無 incident」。對應案例：<a href="/blog/backend/09-performance-capacity/cases/zoom-covid-surge-dynamodb/" data-link-title="9.C18 Zoom：COVID 期間從 1000 萬到 3 億 DAU 的 30 倍突發" data-link-desc="Zoom 在 2020 年 COVID 爆發時、日活從 1000 萬衝到 3 億、用 DynamoDB 撐住會議後端">Zoom 30x COVID surge</a> — baseline 從 1000 萬 DAU 永久升到 3 億、SLO threshold 跟著重新校準。</p>
<h2 id="設計責任">設計責任</h2>
<p>SLO 必須每季 review、不是「設定後就忘」。review 流程：拉過去 90 天 SLI 分布、看 percentile 分布是否跟 SLO 對應、看是否需要調整。drift 確認後要更新：alert threshold、autoscaler trigger、performance budget 額度、容量規劃 baseline。對應 <a href="/blog/backend/knowledge-cards/error-budget/" data-link-title="Error Budget" data-link-desc="說明 SLO 允許的失敗額度如何影響發版與可靠性投入">error budget</a> 跟 <a href="/blog/backend/knowledge-cards/performance-budget/" data-link-title="Performance Budget" data-link-desc="跟 error budget 同類概念、但用於 latency / throughput 退化的可控額度">performance budget</a>。</p>
]]></content:encoded></item><item><title>Distributed SQL</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-sql/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-sql/</guid><description>&lt;p>Distributed SQL 的核心概念是「保留 SQL 與交易語意，同時把資料與計算分散到多節點」。它承擔的是一致性、擴展性與故障收斂的協調成本，並常作為 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp&lt;/a> 的資料層基礎。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Distributed SQL 介於單區域 relational database 與最終一致的 key-value 之間。它通常使用 consensus 協議、分區與複寫，來支撐 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp&lt;/a> 或高可用 OLTP。可對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 distributed SQL 的訊號是「單機或單主架構已成長瓶頸，且業務仍要求交易一致性」。常見例子是跨區帳務、全球訂單、強一致庫存。若業務主要追求吞吐且可接受不一致，NoSQL 或事件流設計通常更划算。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選 distributed SQL 要明確評估三項代價：跨節點協調延遲、容量預留、運維複雜度。若只看峰值吞吐而忽略協調成本，會在故障與擴容時暴露結構性風險。&lt;/p></description><content:encoded><![CDATA[<p>Distributed SQL 的核心概念是「保留 SQL 與交易語意，同時把資料與計算分散到多節點」。它承擔的是一致性、擴展性與故障收斂的協調成本，並常作為 <a href="/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp</a> 的資料層基礎。</p>
<h2 id="概念位置">概念位置</h2>
<p>Distributed SQL 介於單區域 relational database 與最終一致的 key-value 之間。它通常使用 consensus 協議、分區與複寫，來支撐 <a href="/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp</a> 或高可用 OLTP。可對照 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a> 與 <a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">partition</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 distributed SQL 的訊號是「單機或單主架構已成長瓶頸，且業務仍要求交易一致性」。常見例子是跨區帳務、全球訂單、強一致庫存。若業務主要追求吞吐且可接受不一致，NoSQL 或事件流設計通常更划算。</p>
<h2 id="設計責任">設計責任</h2>
<p>選 distributed SQL 要明確評估三項代價：跨節點協調延遲、容量預留、運維複雜度。若只看峰值吞吐而忽略協調成本，會在故障與擴容時暴露結構性風險。</p>
]]></content:encoded></item><item><title>Database Sharding</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/</link><pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/</guid><description>&lt;p>Database sharding 的核心概念是把同一個 logical database 或 table 依 shard key 分散到多個獨立 storage 節點，讓寫入、儲存與故障範圍水平分散。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition&lt;/a> 相鄰，但資料庫 sharding 的主要責任是 data placement、request routing、cross-shard query 與 resharding；容量失衡時要接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition&lt;/a>，一致性需求升高時要對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">Distributed SQL&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Database sharding 位在單一 primary database 與 distributed SQL 之間。MySQL + Vitess、PostgreSQL + Citus、MongoDB sharded cluster 或 application-layer sharding 都會把 shard key 變成資料路由契約；&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">Distributed SQL&lt;/a> 則把更多 routing、一致性與 failover 責任放回 database layer。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 database sharding 的訊號是單一 primary 的 write throughput、storage、maintenance window 或 tenant isolation 已成瓶頸，且 workload 可以用 tenant_id、user_id、region 或 business key 切成相對獨立的資料集合。MySQL 進入 Vitess / PlanetScale 討論時，核心問題通常是 shard key、VSchema、resharding workflow 與跨 shard transaction；PostgreSQL 進入 Citus 討論時，核心問題通常是 tenant co-location、distributed table 與 coordinator / worker topology。&lt;/p>
&lt;p>Hot shard 的訊號是整體資源還有餘裕，但少數 shard 的 write、lock、CPU 或 storage 先到上限。這時要同時看 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag&lt;/a>，避免只增加節點數卻沒有修正 key distribution。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 database sharding 要先定義 shard key、routing owner、single-shard query 比例、cross-shard query policy、cross-shard transaction policy、resharding path、backup / restore unit 與 incident owner。shard key 是長期資料契約，改動時常牽涉 backfill、dual-write、shadow read、cutover window 與 data reconciliation；因此要接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/online-migration/" data-link-title="Online Migration" data-link-desc="說明服務持續接流量時如何完成資料或 schema 遷移">Online Migration&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-window/" data-link-title="Cutover Window" data-link-desc="說明正式切換發生的觀察窗口、停止條件與回退判讀範圍">Cutover Window&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Database sharding 的核心概念是把同一個 logical database 或 table 依 shard key 分散到多個獨立 storage 節點，讓寫入、儲存與故障範圍水平分散。它和 <a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition</a> 相鄰，但資料庫 sharding 的主要責任是 data placement、request routing、cross-shard query 與 resharding；容量失衡時要接回 <a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition</a>，一致性需求升高時要對照 <a href="/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">Distributed SQL</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Database sharding 位在單一 primary database 與 distributed SQL 之間。MySQL + Vitess、PostgreSQL + Citus、MongoDB sharded cluster 或 application-layer sharding 都會把 shard key 變成資料路由契約；<a href="/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">Distributed SQL</a> 則把更多 routing、一致性與 failover 責任放回 database layer。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 database sharding 的訊號是單一 primary 的 write throughput、storage、maintenance window 或 tenant isolation 已成瓶頸，且 workload 可以用 tenant_id、user_id、region 或 business key 切成相對獨立的資料集合。MySQL 進入 Vitess / PlanetScale 討論時，核心問題通常是 shard key、VSchema、resharding workflow 與跨 shard transaction；PostgreSQL 進入 Citus 討論時，核心問題通常是 tenant co-location、distributed table 與 coordinator / worker topology。</p>
<p>Hot shard 的訊號是整體資源還有餘裕，但少數 shard 的 write、lock、CPU 或 storage 先到上限。這時要同時看 <a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition</a>、<a href="/blog/backend/knowledge-cards/saturation-point/" data-link-title="Saturation Point" data-link-desc="說明系統從線性穩態進入 latency 指數成長區的關鍵流量點">Saturation Point</a> 與 <a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag</a>，避免只增加節點數卻沒有修正 key distribution。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 database sharding 要先定義 shard key、routing owner、single-shard query 比例、cross-shard query policy、cross-shard transaction policy、resharding path、backup / restore unit 與 incident owner。shard key 是長期資料契約，改動時常牽涉 backfill、dual-write、shadow read、cutover window 與 data reconciliation；因此要接回 <a href="/blog/backend/knowledge-cards/online-migration/" data-link-title="Online Migration" data-link-desc="說明服務持續接流量時如何完成資料或 schema 遷移">Online Migration</a>、<a href="/blog/backend/knowledge-cards/cutover-window/" data-link-title="Cutover Window" data-link-desc="說明正式切換發生的觀察窗口、停止條件與回退判讀範圍">Cutover Window</a> 與 <a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation</a>。</p>
]]></content:encoded></item><item><title>PACELC</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/pacelc/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/pacelc/</guid><description>&lt;p>PACELC 的核心概念是「系統就算沒有分區，也要在延遲與一致性之間做選擇」。它讓分散式資料庫的取捨從事故時段延伸到日常時段，常用於評估 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp&lt;/a> 的可行性。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>PACELC 可讀成：若發生 partition（P），系統在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">failover&lt;/a>（A）與 consistency（C）之間取捨；否則（E），在 latency（L）與 consistency（C）之間取捨。它補足 CAP 只描述分區情境的盲點。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 PACELC 判讀的訊號是「系統平時沒有故障，但延遲或一致性目標仍互相衝突」。例如跨區強一致交易會提高延遲；低延遲讀取通常要接受 stale risk。這個框架常用於比較 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">distributed-sql&lt;/a> 與 key-value 設計。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 PACELC 時要把業務需求先量化：可接受的 stale window、p99 延遲上限、故障時可降級策略。沒有量化目標時，PACELC 會退化成抽象口號。&lt;/p></description><content:encoded><![CDATA[<p>PACELC 的核心概念是「系統就算沒有分區，也要在延遲與一致性之間做選擇」。它讓分散式資料庫的取捨從事故時段延伸到日常時段，常用於評估 <a href="/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp</a> 的可行性。</p>
<h2 id="概念位置">概念位置</h2>
<p>PACELC 可讀成：若發生 partition（P），系統在 <a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">failover</a>（A）與 consistency（C）之間取捨；否則（E），在 latency（L）與 consistency（C）之間取捨。它補足 CAP 只描述分區情境的盲點。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 PACELC 判讀的訊號是「系統平時沒有故障，但延遲或一致性目標仍互相衝突」。例如跨區強一致交易會提高延遲；低延遲讀取通常要接受 stale risk。這個框架常用於比較 <a href="/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">distributed-sql</a> 與 key-value 設計。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 PACELC 時要把業務需求先量化：可接受的 stale window、p99 延遲上限、故障時可降級策略。沒有量化目標時，PACELC 會退化成抽象口號。</p>
]]></content:encoded></item><item><title>External Consistency</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/external-consistency/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/external-consistency/</guid><description>&lt;p>External consistency 的核心概念是「系統觀察到的交易順序，必須符合外部世界的先後順序」。它比一般 strong consistency 更強，因為要求與真實時間語意對齊，常出現在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp&lt;/a> 場景。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>External consistency 常見於全球交易資料庫，需配合可驗證時間來源或排序機制。它可視為 linearizability 在跨節點、跨區域交易中的具體工程目標。可對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">transaction&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 external consistency 的訊號是「交易先後顛倒會造成帳務、合約或稽核錯誤」。例如同一帳戶的扣款與退款、同一資產的買賣成交。若業務可接受短暫重排，多數情境不必承擔此級別成本。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>採用 external consistency 要同時設計延遲預算與失效處置。跨區確認必然增加延遲，因此要先界定哪些交易必須此語意、哪些可降級為較弱一致性。&lt;/p></description><content:encoded><![CDATA[<p>External consistency 的核心概念是「系統觀察到的交易順序，必須符合外部世界的先後順序」。它比一般 strong consistency 更強，因為要求與真實時間語意對齊，常出現在 <a href="/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp</a> 場景。</p>
<h2 id="概念位置">概念位置</h2>
<p>External consistency 常見於全球交易資料庫，需配合可驗證時間來源或排序機制。它可視為 linearizability 在跨節點、跨區域交易中的具體工程目標。可對照 <a href="/blog/backend/knowledge-cards/transaction/" data-link-title="Transaction" data-link-desc="說明 transaction 如何讓一組資料變更一起成功或一起回復">transaction</a> 與 <a href="/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 external consistency 的訊號是「交易先後顛倒會造成帳務、合約或稽核錯誤」。例如同一帳戶的扣款與退款、同一資產的買賣成交。若業務可接受短暫重排，多數情境不必承擔此級別成本。</p>
<h2 id="設計責任">設計責任</h2>
<p>採用 external consistency 要同時設計延遲預算與失效處置。跨區確認必然增加延遲，因此要先界定哪些交易必須此語意、哪些可降級為較弱一致性。</p>
]]></content:encoded></item><item><title>TrueTime</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/truetime/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/truetime/</guid><description>&lt;p>TrueTime 的核心概念是「系統回傳一個帶不確定區間的時間視窗，而不是假設時間戳絕對精準」。它的責任是讓跨節點交易排序可以被驗證，而不是只靠每台機器的本地時鐘，通常和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">external-consistency&lt;/a> 一起討論。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>TrueTime 常用於 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">external-consistency&lt;/a> 的實作。它把時間誤差顯式化，讓提交順序與可見順序在工程上可檢查、可推導。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 TrueTime 類機制的訊號是「交易先後順序錯誤會造成業務不可接受後果」，例如全球帳務、跨區支付對帳。若業務可接受短暫重排，通常不需要承擔此級別時鐘成本。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 TrueTime 思路時，要同時管理時間不確定區間、提交延遲與跨區 quorum 代價。若只看一致性語意而忽略延遲成本，系統會在高峰流量下失去可用性彈性。&lt;/p></description><content:encoded><![CDATA[<p>TrueTime 的核心概念是「系統回傳一個帶不確定區間的時間視窗，而不是假設時間戳絕對精準」。它的責任是讓跨節點交易排序可以被驗證，而不是只靠每台機器的本地時鐘，通常和 <a href="/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">external-consistency</a> 一起討論。</p>
<h2 id="概念位置">概念位置</h2>
<p>TrueTime 常用於 <a href="/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp</a> 與 <a href="/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">external-consistency</a> 的實作。它把時間誤差顯式化，讓提交順序與可見順序在工程上可檢查、可推導。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 TrueTime 類機制的訊號是「交易先後順序錯誤會造成業務不可接受後果」，例如全球帳務、跨區支付對帳。若業務可接受短暫重排，通常不需要承擔此級別時鐘成本。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 TrueTime 思路時，要同時管理時間不確定區間、提交延遲與跨區 quorum 代價。若只看一致性語意而忽略延遲成本，系統會在高峰流量下失去可用性彈性。</p>
]]></content:encoded></item><item><title>Session Consistency</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/session-consistency/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/session-consistency/</guid><description>&lt;p>Session consistency 的核心概念是「同一 session 內讀到自己剛寫入的資料」，但不保證全域即時一致。它的責任是在體感一致與系統延遲之間提供可操作折衷，位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">external-consistency&lt;/a> 與 eventual consistency 之間。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Session consistency 常出現在多區域資料庫的可調一致性模型，介於 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">external-consistency&lt;/a> 與 eventual consistency 之間。它常用於高互動產品路徑，降低讀者看到「我剛改完卻看不到」的落差。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 session consistency 的訊號是「同一使用者回看自己操作結果時，短暫不一致會造成信任下降」，例如個人設定、遊戲狀態、用戶偏好。若是跨使用者共享狀態，仍要額外評估全域一致需求。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>採用 session consistency 時，要明確定義 session 邊界、token/連線續存策略與跨裝置行為。若 session 定義模糊，會讓一致性語意在不同入口不一致，反而增加除錯成本。&lt;/p></description><content:encoded><![CDATA[<p>Session consistency 的核心概念是「同一 session 內讀到自己剛寫入的資料」，但不保證全域即時一致。它的責任是在體感一致與系統延遲之間提供可操作折衷，位在 <a href="/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">external-consistency</a> 與 eventual consistency 之間。</p>
<h2 id="概念位置">概念位置</h2>
<p>Session consistency 常出現在多區域資料庫的可調一致性模型，介於 <a href="/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">external-consistency</a> 與 eventual consistency 之間。它常用於高互動產品路徑，降低讀者看到「我剛改完卻看不到」的落差。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 session consistency 的訊號是「同一使用者回看自己操作結果時，短暫不一致會造成信任下降」，例如個人設定、遊戲狀態、用戶偏好。若是跨使用者共享狀態，仍要額外評估全域一致需求。</p>
<h2 id="設計責任">設計責任</h2>
<p>採用 session consistency 時，要明確定義 session 邊界、token/連線續存策略與跨裝置行為。若 session 定義模糊，會讓一致性語意在不同入口不一致，反而增加除錯成本。</p>
]]></content:encoded></item><item><title>Bounded Staleness</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/bounded-staleness/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/bounded-staleness/</guid><description>&lt;p>Bounded staleness 的核心概念是「接受資料不是最新，但限定最多落後多少時間或多少版本」。它的責任是把一致性風險轉成可監控的上限，而不是放任不一致無邊界擴大，可搭配 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">latency-budget&lt;/a> 一起設計。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Bounded staleness 是一致性與延遲取捨的中間層，可搭配 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pacelc/" data-link-title="PACELC" data-link-desc="在 CAP 之外補上正常時段的延遲與一致性取捨框架">pacelc&lt;/a> 做設計判讀。它常用在跨區查詢、報表與次要讀路徑，降低全域強一致的延遲成本。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 bounded staleness 的訊號是「使用者可接受短暫延遲，但不能接受長時間舊資料」，例如庫存瀏覽、內容列表、營運看板。若 stale window 超標，通常會觸發告警或降級策略。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>採用 bounded staleness 時，必須定義上限值、量測方法與超標處置。沒有 tripwire 的 stale window 只是口頭承諾，無法支撐 release gate 或事故判讀。&lt;/p></description><content:encoded><![CDATA[<p>Bounded staleness 的核心概念是「接受資料不是最新，但限定最多落後多少時間或多少版本」。它的責任是把一致性風險轉成可監控的上限，而不是放任不一致無邊界擴大，可搭配 <a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">latency-budget</a> 一起設計。</p>
<h2 id="概念位置">概念位置</h2>
<p>Bounded staleness 是一致性與延遲取捨的中間層，可搭配 <a href="/blog/backend/knowledge-cards/pacelc/" data-link-title="PACELC" data-link-desc="在 CAP 之外補上正常時段的延遲與一致性取捨框架">pacelc</a> 做設計判讀。它常用在跨區查詢、報表與次要讀路徑，降低全域強一致的延遲成本。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 bounded staleness 的訊號是「使用者可接受短暫延遲，但不能接受長時間舊資料」，例如庫存瀏覽、內容列表、營運看板。若 stale window 超標，通常會觸發告警或降級策略。</p>
<h2 id="設計責任">設計責任</h2>
<p>採用 bounded staleness 時，必須定義上限值、量測方法與超標處置。沒有 tripwire 的 stale window 只是口頭承諾，無法支撐 release gate 或事故判讀。</p>
]]></content:encoded></item><item><title>CAP Theorem</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cap/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cap/</guid><description>&lt;p>CAP theorem 的核心概念是「當發生網路分區時，系統無法同時保證強一致與完全可用」。它的責任是限制設計者在故障情境下的承諾邊界，而不是提供日常延遲優化答案。可搭配 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pacelc/" data-link-title="PACELC" data-link-desc="在 CAP 之外補上正常時段的延遲與一致性取捨框架">pacelc&lt;/a> 一起判讀。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>CAP 只討論 partition 發生時的取捨，不直接回答「平時要快還是要一致」。因此實作決策通常要和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">eventual-consistency&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">external-consistency&lt;/a> 一起看，才不會把框架誤用成口號。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 CAP 判讀的訊號是「跨節點連線不穩時，團隊還在要求同時零錯誤與零拒絕」。例如跨區交易系統在區域斷鏈時，若仍要求所有讀寫立即一致又完全不中斷，最終會讓故障處置策略自相矛盾。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>使用 CAP 時要先定義 partition 下的降級策略：拒絕寫入、接受舊資料、或只保留局部能力。沒有預先定義，事件當下就會把架構問題轉成人工決策壓力。&lt;/p></description><content:encoded><![CDATA[<p>CAP theorem 的核心概念是「當發生網路分區時，系統無法同時保證強一致與完全可用」。它的責任是限制設計者在故障情境下的承諾邊界，而不是提供日常延遲優化答案。可搭配 <a href="/blog/backend/knowledge-cards/pacelc/" data-link-title="PACELC" data-link-desc="在 CAP 之外補上正常時段的延遲與一致性取捨框架">pacelc</a> 一起判讀。</p>
<h2 id="概念位置">概念位置</h2>
<p>CAP 只討論 partition 發生時的取捨，不直接回答「平時要快還是要一致」。因此實作決策通常要和 <a href="/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">eventual-consistency</a> 或 <a href="/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">external-consistency</a> 一起看，才不會把框架誤用成口號。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 CAP 判讀的訊號是「跨節點連線不穩時，團隊還在要求同時零錯誤與零拒絕」。例如跨區交易系統在區域斷鏈時，若仍要求所有讀寫立即一致又完全不中斷，最終會讓故障處置策略自相矛盾。</p>
<h2 id="設計責任">設計責任</h2>
<p>使用 CAP 時要先定義 partition 下的降級策略：拒絕寫入、接受舊資料、或只保留局部能力。沒有預先定義，事件當下就會把架構問題轉成人工決策壓力。</p>
]]></content:encoded></item><item><title>Linearizability</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/linearizability/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/linearizability/</guid><description>&lt;p>Linearizability 的核心概念是「每次讀寫都像在單一時間線上立刻生效，且順序對所有節點一致」。它的責任是提供可直覺驗證的操作語意，常作為 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">external-consistency&lt;/a> 的基礎概念。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Linearizability 比 eventual 或 session consistency 更強，通常需要跨節點協調與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">quorum&lt;/a>。它常用於金融帳務、票務庫存與交易撮合這類不能接受順序錯亂的路徑。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 linearizability 的訊號是「操作先後顛倒會造成不可逆後果」。例如扣款與退款順序錯亂，會讓對帳失敗或合約狀態錯誤。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>採用 linearizability 時要同步管理兩件事：跨區延遲成本與失效時的可用性策略。只保證語意、不設回退與降級，會在網路抖動時讓服務品質急劇下降。&lt;/p></description><content:encoded><![CDATA[<p>Linearizability 的核心概念是「每次讀寫都像在單一時間線上立刻生效，且順序對所有節點一致」。它的責任是提供可直覺驗證的操作語意，常作為 <a href="/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">external-consistency</a> 的基礎概念。</p>
<h2 id="概念位置">概念位置</h2>
<p>Linearizability 比 eventual 或 session consistency 更強，通常需要跨節點協調與 <a href="/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">quorum</a>。它常用於金融帳務、票務庫存與交易撮合這類不能接受順序錯亂的路徑。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 linearizability 的訊號是「操作先後顛倒會造成不可逆後果」。例如扣款與退款順序錯亂，會讓對帳失敗或合約狀態錯誤。</p>
<h2 id="設計責任">設計責任</h2>
<p>採用 linearizability 時要同步管理兩件事：跨區延遲成本與失效時的可用性策略。只保證語意、不設回退與降級，會在網路抖動時讓服務品質急劇下降。</p>
]]></content:encoded></item><item><title>Quorum</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/quorum/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/quorum/</guid><description>&lt;p>Quorum 的核心概念是「操作要被接受，必須取得最小同意門檻」。它的責任是把一致性從單節點保證轉成多節點共識機制，常用於 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/linearizability/" data-link-title="Linearizability" data-link-desc="每次操作看起來都在單一全域順序中即時生效的一致性語意">linearizability&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>在多區域系統裡，quorum 直接決定兩個結果：提交延遲下限與故障時可用範圍。節點距離越遠、同意門檻越高，延遲通常越高；但容錯能力也會提升。這層取捨通常要和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">latency-budget&lt;/a> 一起評估。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 quorum 判讀的訊號是「跨區資料正確性要求高，但延遲目標仍按單區設定」。例如要求全球強一致卻同時要求跨洲 p99 低於 50ms，通常與 quorum 物理成本衝突。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 quorum 時要明確寫下節點分布、門檻策略與區域失效劇本。這些條件若只存在於腦中，事件期間很容易出現錯誤切換或過度擴散的回退操作。&lt;/p></description><content:encoded><![CDATA[<p>Quorum 的核心概念是「操作要被接受，必須取得最小同意門檻」。它的責任是把一致性從單節點保證轉成多節點共識機制，常用於 <a href="/blog/backend/knowledge-cards/linearizability/" data-link-title="Linearizability" data-link-desc="每次操作看起來都在單一全域順序中即時生效的一致性語意">linearizability</a> 與 <a href="/blog/backend/knowledge-cards/global-oltp/" data-link-title="Global OLTP" data-link-desc="跨地理區域仍維持交易一致性的 OLTP 設計責任與代價">global-oltp</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>在多區域系統裡，quorum 直接決定兩個結果：提交延遲下限與故障時可用範圍。節點距離越遠、同意門檻越高，延遲通常越高；但容錯能力也會提升。這層取捨通常要和 <a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">latency-budget</a> 一起評估。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 quorum 判讀的訊號是「跨區資料正確性要求高，但延遲目標仍按單區設定」。例如要求全球強一致卻同時要求跨洲 p99 低於 50ms，通常與 quorum 物理成本衝突。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 quorum 時要明確寫下節點分布、門檻策略與區域失效劇本。這些條件若只存在於腦中，事件期間很容易出現錯誤切換或過度擴散的回退操作。</p>
]]></content:encoded></item><item><title>Eventual Consistency</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/eventual-consistency/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/eventual-consistency/</guid><description>&lt;p>Eventual consistency 的核心概念是「節點可以暫時看到不同資料，但在沒有新寫入時最終會收斂一致」。它的責任是用一致性延遲換取可用性與吞吐，常和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/session-consistency/" data-link-title="Session Consistency" data-link-desc="同一使用者工作階段內維持讀寫一致、跨工作階段允許短暫不一致">session-consistency&lt;/a> 對照使用。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Eventual consistency 常見於多區域 NoSQL、快取同步與讀寫分離系統。它不是「資料可以一直錯」，而是要明確定義可接受的收斂窗口，並以 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/bounded-staleness/" data-link-title="Bounded Staleness" data-link-desc="允許資料延遲，但把落後上限限制在可量化範圍內的一致性語意">bounded-staleness&lt;/a> 或告警閾值管理風險。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合 eventual consistency 的訊號是「短暫舊資料可接受，但系統需要高可用與跨區吞吐」。例如社群動態、商品評論、推薦內容。若是支付、庫存扣減這類路徑，通常需要更強語意。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>採用 eventual consistency 時，必須定義補償與對帳機制，讓「最終一致」可驗證。沒有驗證路徑時，最終一致會退化成無法證明的假設。&lt;/p></description><content:encoded><![CDATA[<p>Eventual consistency 的核心概念是「節點可以暫時看到不同資料，但在沒有新寫入時最終會收斂一致」。它的責任是用一致性延遲換取可用性與吞吐，常和 <a href="/blog/backend/knowledge-cards/session-consistency/" data-link-title="Session Consistency" data-link-desc="同一使用者工作階段內維持讀寫一致、跨工作階段允許短暫不一致">session-consistency</a> 對照使用。</p>
<h2 id="概念位置">概念位置</h2>
<p>Eventual consistency 常見於多區域 NoSQL、快取同步與讀寫分離系統。它不是「資料可以一直錯」，而是要明確定義可接受的收斂窗口，並以 <a href="/blog/backend/knowledge-cards/bounded-staleness/" data-link-title="Bounded Staleness" data-link-desc="允許資料延遲，但把落後上限限制在可量化範圍內的一致性語意">bounded-staleness</a> 或告警閾值管理風險。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合 eventual consistency 的訊號是「短暫舊資料可接受，但系統需要高可用與跨區吞吐」。例如社群動態、商品評論、推薦內容。若是支付、庫存扣減這類路徑，通常需要更強語意。</p>
<h2 id="設計責任">設計責任</h2>
<p>採用 eventual consistency 時，必須定義補償與對帳機制，讓「最終一致」可驗證。沒有驗證路徑時，最終一致會退化成無法證明的假設。</p>
]]></content:encoded></item><item><title>Consistency Level</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/consistency-level/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/consistency-level/</guid><description>&lt;p>Consistency level 的核心概念是「系統對同一筆資料在不同節點可見性的承諾強度」。它的責任是把一致性從抽象口號轉成可配置語意，常用於 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">eventual-consistency&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/session-consistency/" data-link-title="Session Consistency" data-link-desc="同一使用者工作階段內維持讀寫一致、跨工作階段允許短暫不一致">session-consistency&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/linearizability/" data-link-title="Linearizability" data-link-desc="每次操作看起來都在單一全域順序中即時生效的一致性語意">linearizability&lt;/a> 之間的取捨。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Consistency level 通常出現在多區域資料庫、快取同步與讀寫分離架構。它會直接影響延遲、可用性與資料新鮮度，因此要和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">latency-budget&lt;/a> 一起設計。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 consistency level 判讀的訊號是「同一條業務路徑同時要求低延遲與強一致，但沒有分層策略」。例如把結帳交易與商品瀏覽套同一一致性設定，常會讓其中一邊承受不必要成本。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>定義 consistency level 時要先按業務路徑分層：哪些操作必須強一致、哪些可容忍短暫舊資料、超標時怎麼降級。沒有分層會讓整體設定退化成最保守或最冒險的單一極端。&lt;/p></description><content:encoded><![CDATA[<p>Consistency level 的核心概念是「系統對同一筆資料在不同節點可見性的承諾強度」。它的責任是把一致性從抽象口號轉成可配置語意，常用於 <a href="/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">eventual-consistency</a>、<a href="/blog/backend/knowledge-cards/session-consistency/" data-link-title="Session Consistency" data-link-desc="同一使用者工作階段內維持讀寫一致、跨工作階段允許短暫不一致">session-consistency</a> 與 <a href="/blog/backend/knowledge-cards/linearizability/" data-link-title="Linearizability" data-link-desc="每次操作看起來都在單一全域順序中即時生效的一致性語意">linearizability</a> 之間的取捨。</p>
<h2 id="概念位置">概念位置</h2>
<p>Consistency level 通常出現在多區域資料庫、快取同步與讀寫分離架構。它會直接影響延遲、可用性與資料新鮮度，因此要和 <a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">latency-budget</a> 一起設計。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 consistency level 判讀的訊號是「同一條業務路徑同時要求低延遲與強一致，但沒有分層策略」。例如把結帳交易與商品瀏覽套同一一致性設定，常會讓其中一邊承受不必要成本。</p>
<h2 id="設計責任">設計責任</h2>
<p>定義 consistency level 時要先按業務路徑分層：哪些操作必須強一致、哪些可容忍短暫舊資料、超標時怎麼降級。沒有分層會讓整體設定退化成最保守或最冒險的單一極端。</p>
]]></content:encoded></item><item><title>Control Plane</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/control-plane/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/control-plane/</guid><description>&lt;p>Control plane 的核心概念是「管理系統行為的決策層」，負責下發策略、配置與流量規則。它的責任是控制系統怎麼運作，而不是直接承載業務資料讀寫。可對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/management-plane/" data-link-title="Management Plane" data-link-desc="說明管理平面如何與業務流量平面分離，避免高權限入口擴散">management-plane&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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Control plane 常見於 service mesh、load balancer、Kubernetes 與 API gateway。它影響 data path 的行為，因此任何變更都可能造成大範圍連動，要和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast-radius&lt;/a> 一起治理。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 control plane 判讀的訊號是「小配置變更引發大面積錯誤」。例如路由規則更新後，多個服務同時 5xx，通常是控制層變更把錯誤快速擴散到資料路徑。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>控制層變更要有分批發布、回退窗口與生效可觀測性。沒有這三項，控制層會變成高權限單點風險，事件時難以定位責任邊界。&lt;/p></description><content:encoded><![CDATA[<p>Control plane 的核心概念是「管理系統行為的決策層」，負責下發策略、配置與流量規則。它的責任是控制系統怎麼運作，而不是直接承載業務資料讀寫。可對照 <a href="/blog/backend/knowledge-cards/management-plane/" data-link-title="Management Plane" data-link-desc="說明管理平面如何與業務流量平面分離，避免高權限入口擴散">management-plane</a> 與 <a href="/blog/backend/knowledge-cards/request-routing/" data-link-title="Request Routing" data-link-desc="說明入口流量如何依規則被導向不同服務或處理路徑">request-routing</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Control plane 常見於 service mesh、load balancer、Kubernetes 與 API gateway。它影響 data path 的行為，因此任何變更都可能造成大範圍連動，要和 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast-radius</a> 一起治理。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 control plane 判讀的訊號是「小配置變更引發大面積錯誤」。例如路由規則更新後，多個服務同時 5xx，通常是控制層變更把錯誤快速擴散到資料路徑。</p>
<h2 id="設計責任">設計責任</h2>
<p>控制層變更要有分批發布、回退窗口與生效可觀測性。沒有這三項，控制層會變成高權限單點風險，事件時難以定位責任邊界。</p>
]]></content:encoded></item><item><title>Release Gate</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/release-gate/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/release-gate/</guid><description>&lt;p>Release Gate 的核心概念是「在變更進入正式環境前，用明確條件決定能不能放行」。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Release Gate 位在 migration、schema change、deployment、error budget 與 incident policy 之間。它把驗證結果轉成可執行的放行決策，並常搭配 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal&lt;/a> 確認放行前後都能回復。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 release gate 的訊號是：&lt;/p>
&lt;ul>
&lt;li>變更會影響使用者可用性或資料正確性&lt;/li>
&lt;li>新舊版本會並存一段時間&lt;/li>
&lt;li>團隊需要在 release 前確認檢查項都過關&lt;/li>
&lt;li>發版失敗時要有明確阻擋條件&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>Schema migration 要先確認相容性與 backfill 結果再放行；高風險設定變更要通過 security review 與 drift check；error budget 快耗盡時，團隊可以暫停高風險變更，直到風險恢復到可接受範圍。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Release Gate 要定義檢查項、擁有者、通過條件、阻擋條件與例外流程。它是把風險控制流程標準化的機制，單純的批准按鈕無法達到同等效果。&lt;/p></description><content:encoded><![CDATA[<p>Release Gate 的核心概念是「在變更進入正式環境前，用明確條件決定能不能放行」。 可先對照 <a href="/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Release Gate 位在 migration、schema change、deployment、error budget 與 incident policy 之間。它把驗證結果轉成可執行的放行決策，並常搭配 <a href="/blog/backend/knowledge-cards/rollback-rehearsal/" data-link-title="Rollback Rehearsal" data-link-desc="說明如何在正式事故前演練回滾流程">Rollback Rehearsal</a> 確認放行前後都能回復。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 release gate 的訊號是：</p>
<ul>
<li>變更會影響使用者可用性或資料正確性</li>
<li>新舊版本會並存一段時間</li>
<li>團隊需要在 release 前確認檢查項都過關</li>
<li>發版失敗時要有明確阻擋條件</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>Schema migration 要先確認相容性與 backfill 結果再放行；高風險設定變更要通過 security review 與 drift check；error budget 快耗盡時，團隊可以暫停高風險變更，直到風險恢復到可接受範圍。</p>
<h2 id="設計責任">設計責任</h2>
<p>Release Gate 要定義檢查項、擁有者、通過條件、阻擋條件與例外流程。它是把風險控制流程標準化的機制，單純的批准按鈕無法達到同等效果。</p>
]]></content:encoded></item><item><title>Federation</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/federation/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/federation/</guid><description>&lt;p>Federation 的核心概念是「不同身份或資源系統之間建立可驗證信任關係，讓授權資訊可被交換使用」。它的責任是縮短跨域整合成本，同時維持邊界可追蹤。可對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/workload-identity/" data-link-title="Workload Identity" data-link-desc="用於機器工作負載的身份語意與授權邊界">workload-identity&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trust-boundary/" data-link-title="Trust Boundary" data-link-desc="說明系統哪些位置開始不能沿用原本的信任假設">trust-boundary&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Federation 常出現在 SSO、跨雲工作負載授權與第三方服務整合。它把外部事件導入內部授權鏈，因此要和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/token-revocation/" data-link-title="Token Revocation" data-link-desc="說明事件中如何撤銷 token，縮短可利用窗口">token-revocation&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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 federation 判讀的訊號是「外部身份事件發生後，內部權限收斂速度慢且回查困難」。例如供應商事件後，聯邦 token 仍在非預期服務活躍。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>聯邦信任要有定期重評估、分域撤銷與最小授權範圍。若只建立信任不做持續治理，federation 會把整合便利轉成長期風險擴散通道。&lt;/p></description><content:encoded><![CDATA[<p>Federation 的核心概念是「不同身份或資源系統之間建立可驗證信任關係，讓授權資訊可被交換使用」。它的責任是縮短跨域整合成本，同時維持邊界可追蹤。可對照 <a href="/blog/backend/knowledge-cards/workload-identity/" data-link-title="Workload Identity" data-link-desc="用於機器工作負載的身份語意與授權邊界">workload-identity</a> 與 <a href="/blog/backend/knowledge-cards/trust-boundary/" data-link-title="Trust Boundary" data-link-desc="說明系統哪些位置開始不能沿用原本的信任假設">trust-boundary</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Federation 常出現在 SSO、跨雲工作負載授權與第三方服務整合。它把外部事件導入內部授權鏈，因此要和 <a href="/blog/backend/knowledge-cards/token-revocation/" data-link-title="Token Revocation" data-link-desc="說明事件中如何撤銷 token，縮短可利用窗口">token-revocation</a> 與 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit-log</a> 共同設計。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 federation 判讀的訊號是「外部身份事件發生後，內部權限收斂速度慢且回查困難」。例如供應商事件後，聯邦 token 仍在非預期服務活躍。</p>
<h2 id="設計責任">設計責任</h2>
<p>聯邦信任要有定期重評估、分域撤銷與最小授權範圍。若只建立信任不做持續治理，federation 會把整合便利轉成長期風險擴散通道。</p>
]]></content:encoded></item><item><title>Tripwire</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/tripwire/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/tripwire/</guid><description>&lt;p>Tripwire 的核心概念是「用可量測訊號讓風險決策在條件變化時回到評估流程」。它把治理決策從一次性同意，轉成可持續更新的閉環。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/security-exception/" data-link-title="Security Exception" data-link-desc="說明資安風險例外如何以期限、補償控制與關閉條件管理">Security Exception&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Tripwire 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/security-exception/" data-link-title="Security Exception" data-link-desc="說明資安風險例外如何以期限、補償控制與關閉條件管理">Security Exception&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/release-freeze/" data-link-title="Release Freeze" data-link-desc="說明高風險期間如何以凍結策略保護正式環境">Release Freeze&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">Escalation Policy&lt;/a> 之間。它把監控與流程訊號轉成「何時重新決策」的共通語言。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 tripwire 的訊號是：&lt;/p>
&lt;ul>
&lt;li>例外決策存在到期與重評估需求&lt;/li>
&lt;li>風險條件會隨版本、漏洞、外部公告持續變化&lt;/li>
&lt;li>團隊需要在訊號達門檻時自動升級處理&lt;/li>
&lt;li>治理決策需要可追蹤的觸發紀錄&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>供應鏈治理中，artifact 驗證失敗率連續超過門檻，tripwire 會觸發 release freeze 重評估；身分治理中，特權操作異常增長，tripwire 會觸發 exception 審查與權限收斂。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Tripwire 要定義 trigger signal、threshold、escalation owner、decision route 與關閉條件。設計重點是訊號可量測、門檻可稽核、觸發後流程可執行。&lt;/p></description><content:encoded><![CDATA[<p>Tripwire 的核心概念是「用可量測訊號讓風險決策在條件變化時回到評估流程」。它把治理決策從一次性同意，轉成可持續更新的閉環。 可先對照 <a href="/blog/backend/knowledge-cards/security-exception/" data-link-title="Security Exception" data-link-desc="說明資安風險例外如何以期限、補償控制與關閉條件管理">Security Exception</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Tripwire 位在 <a href="/blog/backend/knowledge-cards/security-exception/" data-link-title="Security Exception" data-link-desc="說明資安風險例外如何以期限、補償控制與關閉條件管理">Security Exception</a>、<a href="/blog/backend/knowledge-cards/release-freeze/" data-link-title="Release Freeze" data-link-desc="說明高風險期間如何以凍結策略保護正式環境">Release Freeze</a> 與 <a href="/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">Escalation Policy</a> 之間。它把監控與流程訊號轉成「何時重新決策」的共通語言。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 tripwire 的訊號是：</p>
<ul>
<li>例外決策存在到期與重評估需求</li>
<li>風險條件會隨版本、漏洞、外部公告持續變化</li>
<li>團隊需要在訊號達門檻時自動升級處理</li>
<li>治理決策需要可追蹤的觸發紀錄</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>供應鏈治理中，artifact 驗證失敗率連續超過門檻，tripwire 會觸發 release freeze 重評估；身分治理中，特權操作異常增長，tripwire 會觸發 exception 審查與權限收斂。</p>
<h2 id="設計責任">設計責任</h2>
<p>Tripwire 要定義 trigger signal、threshold、escalation owner、decision route 與關閉條件。設計重點是訊號可量測、門檻可稽核、觸發後流程可執行。</p>
]]></content:encoded></item><item><title>In-Flight Work</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/in-flight/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/in-flight/</guid><description>&lt;p>In-flight work 的核心概念是「系統已接收、正在處理、但尚未完成的工作集合」。它的責任是量化即時壓力，支援容量控制與回退判讀。可對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/in-flight-message/" data-link-title="In-Flight Message" data-link-desc="說明已交給 consumer 但尚未完成確認的訊息狀態">in-flight-message&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="概念位置">概念位置&lt;/h2>
&lt;p>In-flight 是跨語境訊號：HTTP request、queue message、batch task 都可以有 in-flight。它和 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 in-flight 判讀的訊號是「延遲上升但不確定是入口太快還是處理太慢」。例如 queue depth 平穩，但 in-flight 長期偏高，通常代表 worker 端處理速度下滑或下游依賴變慢。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>In-flight 需要可觀測上限與降載策略。沒有上限時，系統容易在壓力期把暫存資源耗盡，最後演變成全域超時或雪崩式重試。&lt;/p></description><content:encoded><![CDATA[<p>In-flight work 的核心概念是「系統已接收、正在處理、但尚未完成的工作集合」。它的責任是量化即時壓力，支援容量控制與回退判讀。可對照 <a href="/blog/backend/knowledge-cards/in-flight-message/" data-link-title="In-Flight Message" data-link-desc="說明已交給 consumer 但尚未完成確認的訊息狀態">in-flight-message</a> 與 <a href="/blog/backend/knowledge-cards/worker-pool/" data-link-title="Worker Pool" data-link-desc="說明一組 worker 如何限制同時處理量並保護下游資源">worker-pool</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>In-flight 是跨語境訊號：HTTP request、queue message、batch task 都可以有 in-flight。它和 <a href="/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">queue-depth</a> 一起看時，能區分「排隊壓力」與「處理壓力」的來源。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 in-flight 判讀的訊號是「延遲上升但不確定是入口太快還是處理太慢」。例如 queue depth 平穩，但 in-flight 長期偏高，通常代表 worker 端處理速度下滑或下游依賴變慢。</p>
<h2 id="設計責任">設計責任</h2>
<p>In-flight 需要可觀測上限與降載策略。沒有上限時，系統容易在壓力期把暫存資源耗盡，最後演變成全域超時或雪崩式重試。</p>
]]></content:encoded></item><item><title>Security Exception</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/security-exception/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/security-exception/</guid><description>&lt;p>Security exception 的核心概念是「在明確邊界內接受短期風險，並用協議管理收斂路徑」。它讓風險接受決策可追蹤、可關閉、可回寫。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Security exception 位在 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/release-freeze/" data-link-title="Release Freeze" data-link-desc="說明高風險期間如何以凍結策略保護正式環境">Release Freeze&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tripwire/" data-link-title="Tripwire" data-link-desc="說明風險決策在條件變化時如何自動回到評估流程">Tripwire&lt;/a> 之間。它承接治理層決策，並把決策資訊交給部署與 incident workflow。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 security exception 的訊號是：&lt;/p>
&lt;ul>
&lt;li>修補窗口與業務時程暫時不一致&lt;/li>
&lt;li>高風險項目需要短期過渡方案&lt;/li>
&lt;li>團隊需要紀錄接受範圍與期限&lt;/li>
&lt;li>關閉條件需要跨角色共識與可驗證證據&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>新漏洞公告後，某服務在修補完成前以例外方式允許受控上線，同步啟用補償控制（流量限制、額外審計、強化告警），並設定到期日與重評估會議時間。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Security exception 要定義 risk scope、expiry、compensating controls、owner、close criteria 與 write-back target。例外成立的同時，也要同步設計關閉節奏與回寫路徑。&lt;/p></description><content:encoded><![CDATA[<p>Security exception 的核心概念是「在明確邊界內接受短期風險，並用協議管理收斂路徑」。它讓風險接受決策可追蹤、可關閉、可回寫。 可先對照 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Security exception 位在 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a>、<a href="/blog/backend/knowledge-cards/release-freeze/" data-link-title="Release Freeze" data-link-desc="說明高風險期間如何以凍結策略保護正式環境">Release Freeze</a> 與 <a href="/blog/backend/knowledge-cards/tripwire/" data-link-title="Tripwire" data-link-desc="說明風險決策在條件變化時如何自動回到評估流程">Tripwire</a> 之間。它承接治理層決策，並把決策資訊交給部署與 incident workflow。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 security exception 的訊號是：</p>
<ul>
<li>修補窗口與業務時程暫時不一致</li>
<li>高風險項目需要短期過渡方案</li>
<li>團隊需要紀錄接受範圍與期限</li>
<li>關閉條件需要跨角色共識與可驗證證據</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>新漏洞公告後，某服務在修補完成前以例外方式允許受控上線，同步啟用補償控制（流量限制、額外審計、強化告警），並設定到期日與重評估會議時間。</p>
<h2 id="設計責任">設計責任</h2>
<p>Security exception 要定義 risk scope、expiry、compensating controls、owner、close criteria 與 write-back target。例外成立的同時，也要同步設計關閉節奏與回寫路徑。</p>
]]></content:encoded></item><item><title>Stale Read</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/stale-read/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/stale-read/</guid><description>&lt;p>Stale read 的核心概念是「讀到的資料不是最新提交狀態」。它的責任是揭露一致性延遲在讀路徑的實際影響，常用於 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">eventual-consistency&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/bounded-staleness/" data-link-title="Bounded Staleness" data-link-desc="允許資料延遲，但把落後上限限制在可量化範圍內的一致性語意">bounded-staleness&lt;/a> 的風險判讀。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Stale read 常出現在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">replication-lag&lt;/a> 拉開的 read replica、跨區同步、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-aside/" data-link-title="Cache Aside" data-link-desc="說明 application 如何在讀取時自行管理快取與正式資料來源">cache-aside&lt;/a> 與異步 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">projection&lt;/a>。它需要先定義可接受窗口與超標處置、是否構成錯誤取決於業務容忍度；判讀粒度跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consistency-level/" data-link-title="Consistency Level" data-link-desc="資料系統對讀寫一致性語意的可選擇層級">consistency-level&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/bounded-staleness/" data-link-title="Bounded Staleness" data-link-desc="允許資料延遲，但把落後上限限制在可量化範圍內的一致性語意">bounded-staleness&lt;/a> 對齊。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 stale read 判讀的訊號是「使用者剛完成操作，下一次查詢卻看不到結果」。例如付款成功後，訂單狀態頁仍顯示未付款，通常是讀路徑落後寫入收斂。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>處理 stale read 要同時提供技術與產品策略：技術上可用讀回主庫、版本比對或延遲容忍設計；產品上要明確呈現狀態轉換，避免把短暫收斂延遲誤解成資料錯誤。&lt;/p></description><content:encoded><![CDATA[<p>Stale read 的核心概念是「讀到的資料不是最新提交狀態」。它的責任是揭露一致性延遲在讀路徑的實際影響，常用於 <a href="/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">eventual-consistency</a> 與 <a href="/blog/backend/knowledge-cards/bounded-staleness/" data-link-title="Bounded Staleness" data-link-desc="允許資料延遲，但把落後上限限制在可量化範圍內的一致性語意">bounded-staleness</a> 的風險判讀。</p>
<h2 id="概念位置">概念位置</h2>
<p>Stale read 常出現在 <a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">replication-lag</a> 拉開的 read replica、跨區同步、<a href="/blog/backend/knowledge-cards/cache-aside/" data-link-title="Cache Aside" data-link-desc="說明 application 如何在讀取時自行管理快取與正式資料來源">cache-aside</a> 與異步 <a href="/blog/backend/knowledge-cards/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">projection</a>。它需要先定義可接受窗口與超標處置、是否構成錯誤取決於業務容忍度；判讀粒度跟 <a href="/blog/backend/knowledge-cards/consistency-level/" data-link-title="Consistency Level" data-link-desc="資料系統對讀寫一致性語意的可選擇層級">consistency-level</a> 跟 <a href="/blog/backend/knowledge-cards/bounded-staleness/" data-link-title="Bounded Staleness" data-link-desc="允許資料延遲，但把落後上限限制在可量化範圍內的一致性語意">bounded-staleness</a> 對齊。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 stale read 判讀的訊號是「使用者剛完成操作，下一次查詢卻看不到結果」。例如付款成功後，訂單狀態頁仍顯示未付款，通常是讀路徑落後寫入收斂。</p>
<h2 id="設計責任">設計責任</h2>
<p>處理 stale read 要同時提供技術與產品策略：技術上可用讀回主庫、版本比對或延遲容忍設計；產品上要明確呈現狀態轉換，避免把短暫收斂延遲誤解成資料錯誤。</p>
]]></content:encoded></item><item><title>Release Freeze</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/release-freeze/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/release-freeze/</guid><description>&lt;p>Release freeze 的核心概念是「在高風險期間暫停特定變更，保護正式環境穩定與資料安全」。它是風險治理節奏的一部分，不是永久狀態。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Release freeze 位在 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/allowlist/" data-link-title="Allowlist" data-link-desc="說明如何用明確允許條件控制例外放行範圍">Allowlist&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/tripwire/" data-link-title="Tripwire" data-link-desc="說明風險決策在條件變化時如何自動回到評估流程">Tripwire&lt;/a> 之間。它決定哪些變更先暫停、哪些必要變更可受控放行。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 release freeze 的訊號是：&lt;/p>
&lt;ul>
&lt;li>漏洞修補、供應鏈事件或事故復原正在進行&lt;/li>
&lt;li>關鍵控制面驗證尚未達到放行標準&lt;/li>
&lt;li>高風險變更可能擴大影響範圍&lt;/li>
&lt;li>團隊需要在短時間內穩定風險面&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>供應鏈事件期間，團隊暫停所有非必要版本更新，只允許修補與回復相關變更進入正式環境；每次放行都通過額外驗證與雙人審核。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Release freeze 要定義 freeze scope、allowlist policy、validation gate、unfreeze condition 與例外審查流程，並把解除條件連回治理決策會議。&lt;/p></description><content:encoded><![CDATA[<p>Release freeze 的核心概念是「在高風險期間暫停特定變更，保護正式環境穩定與資料安全」。它是風險治理節奏的一部分，不是永久狀態。 可先對照 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Release freeze 位在 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a>、<a href="/blog/backend/knowledge-cards/allowlist/" data-link-title="Allowlist" data-link-desc="說明如何用明確允許條件控制例外放行範圍">Allowlist</a> 與 <a href="/blog/backend/knowledge-cards/tripwire/" data-link-title="Tripwire" data-link-desc="說明風險決策在條件變化時如何自動回到評估流程">Tripwire</a> 之間。它決定哪些變更先暫停、哪些必要變更可受控放行。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 release freeze 的訊號是：</p>
<ul>
<li>漏洞修補、供應鏈事件或事故復原正在進行</li>
<li>關鍵控制面驗證尚未達到放行標準</li>
<li>高風險變更可能擴大影響範圍</li>
<li>團隊需要在短時間內穩定風險面</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>供應鏈事件期間，團隊暫停所有非必要版本更新，只允許修補與回復相關變更進入正式環境；每次放行都通過額外驗證與雙人審核。</p>
<h2 id="設計責任">設計責任</h2>
<p>Release freeze 要定義 freeze scope、allowlist policy、validation gate、unfreeze condition 與例外審查流程，並把解除條件連回治理決策會議。</p>
]]></content:encoded></item><item><title>Workload Identity</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/workload-identity/</link><pubDate>Wed, 13 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/workload-identity/</guid><description>&lt;p>Workload identity 的核心概念是「把機器身份與人類身份分開治理」。它的責任是讓服務到服務授權可追蹤、可撤銷，避免長期共享憑證造成高權限擴散。可對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">credential&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/federation/" data-link-title="Federation" data-link-desc="跨系統信任與授權交換的聯邦機制">federation&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Workload identity 常見於 Kubernetes、跨雲服務整合與 CI/CD 自動化、跟 &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/token-revocation/" data-link-title="Token Revocation" data-link-desc="說明事件中如何撤銷 token，縮短可利用窗口">token-revocation&lt;/a> 的短時 token 與 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 workload identity 判讀的訊號是「機器授權來源不清、scope 過寬、事件後難以分域回收」。例如供應商事件後，內部多個服務仍使用同一聯邦 token 存活。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 workload identity 時要定義三件事：簽發責任主體、token 生命周期、事件後收斂流程。缺少任一項，都會把身份治理退化成不可驗證的長期信任假設。&lt;/p></description><content:encoded><![CDATA[<p>Workload identity 的核心概念是「把機器身份與人類身份分開治理」。它的責任是讓服務到服務授權可追蹤、可撤銷，避免長期共享憑證造成高權限擴散。可對照 <a href="/blog/backend/knowledge-cards/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">credential</a> 與 <a href="/blog/backend/knowledge-cards/federation/" data-link-title="Federation" data-link-desc="跨系統信任與授權交換的聯邦機制">federation</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Workload identity 常見於 Kubernetes、跨雲服務整合與 CI/CD 自動化、跟 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">authentication</a> 對人類身份的處理對稱。它通常搭配 <a href="/blog/backend/knowledge-cards/token-revocation/" data-link-title="Token Revocation" data-link-desc="說明事件中如何撤銷 token，縮短可利用窗口">token-revocation</a> 的短時 token 與 <a href="/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">least-privilege</a> 的最小授權範圍、降低憑證被竊取後的利用窗口。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 workload identity 判讀的訊號是「機器授權來源不清、scope 過寬、事件後難以分域回收」。例如供應商事件後，內部多個服務仍使用同一聯邦 token 存活。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 workload identity 時要定義三件事：簽發責任主體、token 生命周期、事件後收斂流程。缺少任一項，都會把身份治理退化成不可驗證的長期信任假設。</p>
]]></content:encoded></item><item><title>Allowlist</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/allowlist/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/allowlist/</guid><description>&lt;p>Allowlist 的核心概念是「以明確條件列出可放行項目，讓例外放行保持可控邊界」。它把放行決策從口頭同意轉成可稽核政策。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/input-validation/" data-link-title="Input Validation" data-link-desc="說明進入系統的資料如何先被檢查格式、範圍與語意">Input Validation&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Allowlist 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/input-validation/" data-link-title="Input Validation" data-link-desc="說明進入系統的資料如何先被檢查格式、範圍與語意">Input Validation&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/release-freeze/" data-link-title="Release Freeze" data-link-desc="說明高風險期間如何以凍結策略保護正式環境">Release Freeze&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;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 allowlist 的訊號是：&lt;/p>
&lt;ul>
&lt;li>需要在凍結期間保留少量必要變更&lt;/li>
&lt;li>高風險操作需要先符合條件才能執行&lt;/li>
&lt;li>團隊需要限制可用來源、版本或操作集合&lt;/li>
&lt;li>放行規則需要可追蹤與可回顧&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>release freeze 期間，只允許安全修補版本與回復工具變更進入正式環境；資料匯出流程只允許特定角色與核准任務編號觸發。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Allowlist 要定義允許對象、限制條件、有效期限、審查者與撤銷機制。放行條件要能被系統驗證，而不是依賴人工記憶。&lt;/p></description><content:encoded><![CDATA[<p>Allowlist 的核心概念是「以明確條件列出可放行項目，讓例外放行保持可控邊界」。它把放行決策從口頭同意轉成可稽核政策。 可先對照 <a href="/blog/backend/knowledge-cards/input-validation/" data-link-title="Input Validation" data-link-desc="說明進入系統的資料如何先被檢查格式、範圍與語意">Input Validation</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Allowlist 位在 <a href="/blog/backend/knowledge-cards/input-validation/" data-link-title="Input Validation" data-link-desc="說明進入系統的資料如何先被檢查格式、範圍與語意">Input Validation</a>、<a href="/blog/backend/knowledge-cards/release-freeze/" data-link-title="Release Freeze" data-link-desc="說明高風險期間如何以凍結策略保護正式環境">Release Freeze</a> 與 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a> 之間。它可以同時用於請求治理、變更治理與資源治理。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 allowlist 的訊號是：</p>
<ul>
<li>需要在凍結期間保留少量必要變更</li>
<li>高風險操作需要先符合條件才能執行</li>
<li>團隊需要限制可用來源、版本或操作集合</li>
<li>放行規則需要可追蹤與可回顧</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>release freeze 期間，只允許安全修補版本與回復工具變更進入正式環境；資料匯出流程只允許特定角色與核准任務編號觸發。</p>
<h2 id="設計責任">設計責任</h2>
<p>Allowlist 要定義允許對象、限制條件、有效期限、審查者與撤銷機制。放行條件要能被系統驗證，而不是依賴人工記憶。</p>
]]></content:encoded></item><item><title>Artifact Provenance</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/artifact-provenance/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/artifact-provenance/</guid><description>&lt;p>Artifact provenance 的核心概念是「證明交付物來源、建置路徑與完整性，讓部署決策有可驗證信任基礎」。它把供應鏈信任從假設改成證據。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Artifact provenance 位在 &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/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">Credential&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;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 artifact provenance 的訊號是：&lt;/p>
&lt;ul>
&lt;li>需要確認 artifact 來源是否來自受信建置流程&lt;/li>
&lt;li>部署前需要驗證簽章、摘要與版本關聯&lt;/li>
&lt;li>供應鏈事件後需要快速判讀受影響範圍&lt;/li>
&lt;li>團隊需要可追溯證據支援稽核與復盤&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>團隊在發佈前驗證 artifact 簽章與 digest，並比對建置紀錄與 commit 來源；若 provenance 證據缺口出現，release gate 直接阻擋放行並觸發治理流程。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Artifact provenance 要定義來源證據欄位、簽章驗證流程、失敗處理路徑與證據保留策略，並把驗證結果寫入 release governance 與 incident workflow。&lt;/p></description><content:encoded><![CDATA[<p>Artifact provenance 的核心概念是「證明交付物來源、建置路徑與完整性，讓部署決策有可驗證信任基礎」。它把供應鏈信任從假設改成證據。 可先對照 <a href="/blog/backend/knowledge-cards/ci-pipeline/" data-link-title="CI Pipeline" data-link-desc="說明持續整合流程如何在合併前驗證品質與相容性">CI Pipeline</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Artifact provenance 位在 <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/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">Credential</a> 與 <a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a> 之間。它連接建置流程、簽章機制與正式放行決策。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 artifact provenance 的訊號是：</p>
<ul>
<li>需要確認 artifact 來源是否來自受信建置流程</li>
<li>部署前需要驗證簽章、摘要與版本關聯</li>
<li>供應鏈事件後需要快速判讀受影響範圍</li>
<li>團隊需要可追溯證據支援稽核與復盤</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>團隊在發佈前驗證 artifact 簽章與 digest，並比對建置紀錄與 commit 來源；若 provenance 證據缺口出現，release gate 直接阻擋放行並觸發治理流程。</p>
<h2 id="設計責任">設計責任</h2>
<p>Artifact provenance 要定義來源證據欄位、簽章驗證流程、失敗處理路徑與證據保留策略，並把驗證結果寫入 release governance 與 incident workflow。</p>
]]></content:encoded></item><item><title>Management Plane</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/management-plane/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/management-plane/</guid><description>&lt;p>Management plane 的核心概念是「承載高權限控制操作的系統平面」。它通常包含管理介面、配置變更入口、平台控制 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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Management plane 位在 &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/trust-boundary/" data-link-title="Trust Boundary" data-link-desc="說明系統哪些位置開始不能沿用原本的信任假設">trust-boundary&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/runtime-config/" data-link-title="Runtime Config" data-link-desc="說明服務在啟動與執行時如何讀取與組合設定">runtime-config&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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要管理平面治理的訊號是管理入口可由一般流量路徑到達，或管理操作缺少獨立稽核。邊界設備、雲端控制台、平台管控 API 都屬於管理平面。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>管理平面要定義存取邊界、操作審核、變更時序與責任鏈。事件發生時要能快速鎖定高風險操作入口，避免控制能力被橫向擴散。&lt;/p></description><content:encoded><![CDATA[<p>Management plane 的核心概念是「承載高權限控制操作的系統平面」。它通常包含管理介面、配置變更入口、平台控制 API 與維運工具。 可先對照 <a href="/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Management plane 位在 <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/trust-boundary/" data-link-title="Trust Boundary" data-link-desc="說明系統哪些位置開始不能沿用原本的信任假設">trust-boundary</a>、<a href="/blog/backend/knowledge-cards/runtime-config/" data-link-title="Runtime Config" data-link-desc="說明服務在啟動與執行時如何讀取與組合設定">runtime-config</a> 與 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">audit-log</a> 之間。它需要和業務流量平面維持清楚邊界。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要管理平面治理的訊號是管理入口可由一般流量路徑到達，或管理操作缺少獨立稽核。邊界設備、雲端控制台、平台管控 API 都屬於管理平面。</p>
<h2 id="設計責任">設計責任</h2>
<p>管理平面要定義存取邊界、操作審核、變更時序與責任鏈。事件發生時要能快速鎖定高風險操作入口，避免控制能力被橫向擴散。</p>
]]></content:encoded></item><item><title>Session Invalidation</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/session-invalidation/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/session-invalidation/</guid><description>&lt;p>Session invalidation 的核心概念是「使既有會話在定義時間內失去可用性」。它是事件收斂的重要步驟，常與憑證輪替同時執行。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Session invalidation 位在 &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/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">credential&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident-timeline&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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要會話失效機制的訊號是修補完成後仍觀察到可疑會話、異常登入地理分布或持續重放行為。邊界設備事件與 SSO 事件常需要全域會話失效。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>會話失效要定義觸發條件、覆蓋範圍、失效時序與驗證方式。設計上需要兼顧安全收斂速度與業務可用性。&lt;/p></description><content:encoded><![CDATA[<p>Session invalidation 的核心概念是「使既有會話在定義時間內失去可用性」。它是事件收斂的重要步驟，常與憑證輪替同時執行。 可先對照 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">Authentication</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Session invalidation 位在 <a href="/blog/backend/knowledge-cards/authentication/" data-link-title="Authentication" data-link-desc="說明系統如何確認呼叫者身份">authentication</a>、<a href="/blog/backend/knowledge-cards/credential/" data-link-title="Credential" data-link-desc="整理身分驗證與系統存取用秘密資料">credential</a>、<a href="/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident-timeline</a> 與 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 之間。它承接身分事件後的收斂節奏。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要會話失效機制的訊號是修補完成後仍觀察到可疑會話、異常登入地理分布或持續重放行為。邊界設備事件與 SSO 事件常需要全域會話失效。</p>
<h2 id="設計責任">設計責任</h2>
<p>會話失效要定義觸發條件、覆蓋範圍、失效時序與驗證方式。設計上需要兼顧安全收斂速度與業務可用性。</p>
]]></content:encoded></item><item><title>Token Revocation</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/token-revocation/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/token-revocation/</guid><description>&lt;p>Token revocation 的核心概念是「在事件節奏內讓既有 token 失去授權效力」。它是第三方事件與身分事件中的關鍵收斂能力。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Token revocation 位在 &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/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/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident-severity&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> 之間。它常與 token 分域策略一起使用。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 token 撤銷能力的訊號是供應商事件後 token 仍可存取敏感資產，或可疑 token 在事件後持續被使用。OAuth token、API token 與 service token 都屬於常見對象。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>token 撤銷要定義分域、優先級、批次策略與可回查紀錄。事件中要能先撤銷高風險 token，再依業務優先級逐步恢復必要授權。&lt;/p></description><content:encoded><![CDATA[<p>Token revocation 的核心概念是「在事件節奏內讓既有 token 失去授權效力」。它是第三方事件與身分事件中的關鍵收斂能力。 可先對照 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Token revocation 位在 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">authorization</a>、<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/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident-severity</a> 與 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 之間。它常與 token 分域策略一起使用。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 token 撤銷能力的訊號是供應商事件後 token 仍可存取敏感資產，或可疑 token 在事件後持續被使用。OAuth token、API token 與 service token 都屬於常見對象。</p>
<h2 id="設計責任">設計責任</h2>
<p>token 撤銷要定義分域、優先級、批次策略與可回查紀錄。事件中要能先撤銷高風險 token，再依業務優先級逐步恢復必要授權。</p>
]]></content:encoded></item><item><title>Containment</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/containment/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/containment/</guid><description>&lt;p>Containment 的核心概念是「在事故期間限制風險擴散，維持可控處置空間」。它是止血、隔離與收斂節奏的上位概念。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Containment 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident-severity&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback-strategy&lt;/a> 之間。它先回答保護邊界，再回答恢復順序。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 containment 的訊號是影響面快速擴大、異常行為跨服務傳播、或回復決策尚未完成。常見動作包含入口隔離、權限收斂、會話失效與流量切換。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>containment 要定義觸發條件、執行順序、停止條件與驗證關閉標準。它應該讓團隊在壓力下快速做出一致決策。&lt;/p></description><content:encoded><![CDATA[<p>Containment 的核心概念是「在事故期間限制風險擴散，維持可控處置空間」。它是止血、隔離與收斂節奏的上位概念。 可先對照 <a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">Incident Severity</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Containment 位在 <a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident-severity</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> 與 <a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">rollback-strategy</a> 之間。它先回答保護邊界，再回答恢復順序。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 containment 的訊號是影響面快速擴大、異常行為跨服務傳播、或回復決策尚未完成。常見動作包含入口隔離、權限收斂、會話失效與流量切換。</p>
<h2 id="設計責任">設計責任</h2>
<p>containment 要定義觸發條件、執行順序、停止條件與驗證關閉標準。它應該讓團隊在壓力下快速做出一致決策。</p>
]]></content:encoded></item><item><title>Impact Scope</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/impact-scope/</link><pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/impact-scope/</guid><description>&lt;p>Impact scope 的核心概念是「用一致規則界定事故影響到哪些資產、流程與利害關係人」。它是事故通報與回復排序的共用基礎。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">Blast Radius&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Impact scope 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast-radius&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident-timeline&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/mttr/" data-link-title="MTTR" data-link-desc="說明平均修復時間如何作為事故處理能力指標">mttr&lt;/a> 之間。它把技術事件映射到業務影響。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要影響面盤點的訊號是技術異常已確認，但受影響名單與業務衝擊仍不清楚。資料外送事件、供應鏈事件與跨部門中斷都需要 impact scope。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>影響面盤點要定義盤點粒度、資料來源、更新節奏與責任角色。事件中應先完成最小可用清單，再持續擴充精度。&lt;/p></description><content:encoded><![CDATA[<p>Impact scope 的核心概念是「用一致規則界定事故影響到哪些資產、流程與利害關係人」。它是事故通報與回復排序的共用基礎。 可先對照 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">Blast Radius</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Impact scope 位在 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast-radius</a>、<a href="/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident-timeline</a>、<a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review</a> 與 <a href="/blog/backend/knowledge-cards/mttr/" data-link-title="MTTR" data-link-desc="說明平均修復時間如何作為事故處理能力指標">mttr</a> 之間。它把技術事件映射到業務影響。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要影響面盤點的訊號是技術異常已確認，但受影響名單與業務衝擊仍不清楚。資料外送事件、供應鏈事件與跨部門中斷都需要 impact scope。</p>
<h2 id="設計責任">設計責任</h2>
<p>影響面盤點要定義盤點粒度、資料來源、更新節奏與責任角色。事件中應先完成最小可用清單，再持續擴充精度。</p>
]]></content:encoded></item><item><title>Status Page</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/status-page/</link><pubDate>Sat, 02 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/status-page/</guid><description>&lt;p>Status page 的核心概念是「把事故影響、處理節奏與回復進度公開成單一對外契約」。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-communication-channel/" data-link-title="Incident Communication Channel" data-link-desc="說明事故期間內外部溝通要使用哪些固定通道與節奏">incident communication channel&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity&lt;/a> 一起決定外部看到的真實版本。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Status page 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-communication-channel/" data-link-title="Incident Communication Channel" data-link-desc="說明事故期間內外部溝通要使用哪些固定通道與節奏">incident communication channel&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stakeholder-mapping/" data-link-title="Stakeholder Mapping" data-link-desc="說明事故期間如何把通報對象分層與對應 owner">stakeholder mapping&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review&lt;/a> 之間。它把內部節奏轉成客戶可讀的更新，並把 ETA、影響範圍與下一次更新時間固定下來。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 status page 的訊號是事故已經影響外部使用者，但內部的戰情室節奏還不能直接交給客戶。常見例子包括區域性 outage、身份平台失效、外部供應商中斷與多租戶服務退化。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Status page 要定義更新頻率、發佈責任、嚴重度標示、影響範圍與下一次更新承諾。它是外部信任的最小承諾面，用公關模板的心態維護會失去可信度。&lt;/p></description><content:encoded><![CDATA[<p>Status page 的核心概念是「把事故影響、處理節奏與回復進度公開成單一對外契約」。它和 <a href="/blog/backend/knowledge-cards/incident-communication-channel/" data-link-title="Incident Communication Channel" data-link-desc="說明事故期間內外部溝通要使用哪些固定通道與節奏">incident communication channel</a> 與 <a href="/blog/backend/knowledge-cards/incident-severity/" data-link-title="Incident Severity" data-link-desc="說明事故分級如何把產品影響轉成對應處置節奏">incident severity</a> 一起決定外部看到的真實版本。</p>
<h2 id="概念位置">概念位置</h2>
<p>Status page 位在 <a href="/blog/backend/knowledge-cards/incident-communication-channel/" data-link-title="Incident Communication Channel" data-link-desc="說明事故期間內外部溝通要使用哪些固定通道與節奏">incident communication channel</a>、<a href="/blog/backend/knowledge-cards/stakeholder-mapping/" data-link-title="Stakeholder Mapping" data-link-desc="說明事故期間如何把通報對象分層與對應 owner">stakeholder mapping</a> 與 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review</a> 之間。它把內部節奏轉成客戶可讀的更新，並把 ETA、影響範圍與下一次更新時間固定下來。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 status page 的訊號是事故已經影響外部使用者，但內部的戰情室節奏還不能直接交給客戶。常見例子包括區域性 outage、身份平台失效、外部供應商中斷與多租戶服務退化。</p>
<h2 id="設計責任">設計責任</h2>
<p>Status page 要定義更新頻率、發佈責任、嚴重度標示、影響範圍與下一次更新承諾。它是外部信任的最小承諾面，用公關模板的心態維護會失去可信度。</p>
]]></content:encoded></item><item><title>Stakeholder Mapping</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/stakeholder-mapping/</link><pubDate>Sat, 02 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/stakeholder-mapping/</guid><description>&lt;p>Stakeholder mapping 的核心概念是「把誰需要知道什麼、由誰負責、在什麼節奏通知」先畫清楚。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-communication-channel/" data-link-title="Incident Communication Channel" data-link-desc="說明事故期間內外部溝通要使用哪些固定通道與節奏">incident communication channel&lt;/a> 以及 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/status-page/" data-link-title="Status Page" data-link-desc="說明事故期間對外狀態頁如何承接可用性承諾">status page&lt;/a> 一起決定通報的分層。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Stakeholder mapping 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-communication-channel/" data-link-title="Incident Communication Channel" data-link-desc="說明事故期間內外部溝通要使用哪些固定通道與節奏">incident communication channel&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review&lt;/a> 之間。它把內部、客戶、管理層、法務與監管需求拆開，避免事故中漏通知或重複通知。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 stakeholder mapping 的訊號是事故時通知對象不固定、每次都靠記憶補。常見例子包括：客戶已受影響但 account team 沒收到、法務通報窗口被錯過、或補償政策需要臨時討論。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Stakeholder mapping 要定義角色群組、owner、通知頻率、升級條件與例外處理。它的目標是把責任鏈固定下來，名單長度本身沒有意義。&lt;/p></description><content:encoded><![CDATA[<p>Stakeholder mapping 的核心概念是「把誰需要知道什麼、由誰負責、在什麼節奏通知」先畫清楚。它和 <a href="/blog/backend/knowledge-cards/incident-communication-channel/" data-link-title="Incident Communication Channel" data-link-desc="說明事故期間內外部溝通要使用哪些固定通道與節奏">incident communication channel</a> 以及 <a href="/blog/backend/knowledge-cards/status-page/" data-link-title="Status Page" data-link-desc="說明事故期間對外狀態頁如何承接可用性承諾">status page</a> 一起決定通報的分層。</p>
<h2 id="概念位置">概念位置</h2>
<p>Stakeholder mapping 位在 <a href="/blog/backend/knowledge-cards/incident-communication-channel/" data-link-title="Incident Communication Channel" data-link-desc="說明事故期間內外部溝通要使用哪些固定通道與節奏">incident communication channel</a>、<a href="/blog/backend/knowledge-cards/escalation-policy/" data-link-title="Escalation Policy" data-link-desc="說明事故升級鏈與值班轉接規則">escalation policy</a> 與 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review</a> 之間。它把內部、客戶、管理層、法務與監管需求拆開，避免事故中漏通知或重複通知。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 stakeholder mapping 的訊號是事故時通知對象不固定、每次都靠記憶補。常見例子包括：客戶已受影響但 account team 沒收到、法務通報窗口被錯過、或補償政策需要臨時討論。</p>
<h2 id="設計責任">設計責任</h2>
<p>Stakeholder mapping 要定義角色群組、owner、通知頻率、升級條件與例外處理。它的目標是把責任鏈固定下來，名單長度本身沒有意義。</p>
]]></content:encoded></item><item><title>Toil</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/toil/</link><pubDate>Sat, 02 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/toil/</guid><description>&lt;p>Toil 的核心概念是「重複、手動、無永久價值、可自動化的工作」。它通常和 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">alert fatigue&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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Toil 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">alert-fatigue&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/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review&lt;/a> 之間。它把反覆出現的手動修復工作，轉成能被自動化或系統性消除的治理對象。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 toil 治理的訊號是值班時間被重複修復工作吃掉，且每次事故後都只是多一個手動步驟。常見例子包括固定重啟、手動 replay、人工清 queue、或每週都要補同一份報表。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Toil 治理要定義可自動化優先序、移除條件、owner 與替代路徑。它的目標是把沒有長期價值的重複成本逐步壓下來，消滅所有手工流程既不必要也不現實。&lt;/p></description><content:encoded><![CDATA[<p>Toil 的核心概念是「重複、手動、無永久價值、可自動化的工作」。它通常和 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a> 壓力、<a href="/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">alert fatigue</a> 與 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 綁在一起。</p>
<h2 id="概念位置">概念位置</h2>
<p>Toil 位在 <a href="/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">alert-fatigue</a>、<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a> 與 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident-review</a> 之間。它把反覆出現的手動修復工作，轉成能被自動化或系統性消除的治理對象。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 toil 治理的訊號是值班時間被重複修復工作吃掉，且每次事故後都只是多一個手動步驟。常見例子包括固定重啟、手動 replay、人工清 queue、或每週都要補同一份報表。</p>
<h2 id="設計責任">設計責任</h2>
<p>Toil 治理要定義可自動化優先序、移除條件、owner 與替代路徑。它的目標是把沒有長期價值的重複成本逐步壓下來，消滅所有手工流程既不必要也不現實。</p>
]]></content:encoded></item><item><title>Action Item Closure</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/action-item-closure/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/action-item-closure/</guid><description>&lt;p>Action item closure 的核心概念是「把復盤行動項變成可驗證完成的工程責任」。它承接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review&lt;/a> 的產出，關心的是每一項是否有 owner、完成標準、驗證方式與截止時間，而非列出多少待辦。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Action item closure 連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review&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>（行動項可能是更新 runbook）、&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/signal-governance-loop/" data-link-title="4.8 訊號治理閉環" data-link-desc="把 postmortem 揭露的偵測缺口回寫成新訊號、讓觀測能力隨事故學習成長">4.8 訊號治理閉環&lt;/a>（行動項可能是新增 alert / metric / dashboard）。&lt;/p>
&lt;p>Detection gap 類的行動項（「事故中缺少某個 alert / metric」）應指派給觀測系統的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ownership/" data-link-title="Ownership" data-link-desc="說明 ownership 如何把問題、決策與交接責任固定到可執行角色">owner&lt;/a>，帶明確的變更規格（新增哪個 metric、alert 閾值多少、連到哪個 runbook）。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>系統需要 action item closure 流程的訊號是事故復盤後大量 open items 超過 90 天仍未關閉，或同類事故重複發生但上次復盤的改善項還沒完成。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>每個 action item 定義：owner（誰負責完成）、完成標準（什麼狀態算 done — 不是「已開始」而是「已部署、已驗證」）、驗證方式（怎麼確認完成 — 跑一次演練、查 dashboard 確認 metric 存在）、截止時間（兩週內 close）。逾期的 action item 自動升級到管理層 — 這個升級機制是 closure 流程的背壓。&lt;/p></description><content:encoded><![CDATA[<p>Action item closure 的核心概念是「把復盤行動項變成可驗證完成的工程責任」。它承接 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review</a> 的產出，關心的是每一項是否有 owner、完成標準、驗證方式與截止時間，而非列出多少待辦。</p>
<h2 id="概念位置">概念位置</h2>
<p>Action item closure 連接 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review</a>（產出行動項）、<a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a>（行動項可能是更新 runbook）、<a href="/blog/backend/04-observability/signal-governance-loop/" data-link-title="4.8 訊號治理閉環" data-link-desc="把 postmortem 揭露的偵測缺口回寫成新訊號、讓觀測能力隨事故學習成長">4.8 訊號治理閉環</a>（行動項可能是新增 alert / metric / dashboard）。</p>
<p>Detection gap 類的行動項（「事故中缺少某個 alert / metric」）應指派給觀測系統的 <a href="/blog/backend/knowledge-cards/ownership/" data-link-title="Ownership" data-link-desc="說明 ownership 如何把問題、決策與交接責任固定到可執行角色">owner</a>，帶明確的變更規格（新增哪個 metric、alert 閾值多少、連到哪個 runbook）。</p>
<h2 id="使用情境">使用情境</h2>
<p>系統需要 action item closure 流程的訊號是事故復盤後大量 open items 超過 90 天仍未關閉，或同類事故重複發生但上次復盤的改善項還沒完成。</p>
<h2 id="設計責任">設計責任</h2>
<p>每個 action item 定義：owner（誰負責完成）、完成標準（什麼狀態算 done — 不是「已開始」而是「已部署、已驗證」）、驗證方式（怎麼確認完成 — 跑一次演練、查 dashboard 確認 metric 存在）、截止時間（兩週內 close）。逾期的 action item 自動升級到管理層 — 這個升級機制是 closure 流程的背壓。</p>
]]></content:encoded></item><item><title>Evidence Package</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/</link><pubDate>Thu, 07 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/</guid><description>&lt;p>Evidence package 的核心概念是「把查詢、時間窗、資料品質限制與 owner 打包成可交接證據」。它連接 &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/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/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline&lt;/a>，讓事故與驗證能回放同一組事實。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Evidence package 位在 &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/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/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review&lt;/a> 之間。Dashboard 提供操作視角，SLO 提供判讀門檻，evidence package 保存支撐判斷的來源、時間窗、查詢入口與限制。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 evidence package 的訊號是同一段事故證據在交班、release gate 或復盤時反覆被重新查證。常見例子是只保存截圖，下一班 on-call 看得到圖表形狀，卻缺少 query、time range、sampling ratio、ingest delay 與 owner，導致決策背景需要重新建立。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Evidence package 要包含 source、time range、query link、owner、data quality、confidence、known gap 與 retention。它的責任是讓證據可查、可解釋、可重跑，並能交給 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/action-item-closure/" data-link-title="Action Item Closure" data-link-desc="說明事故行動項如何被驗證完成，而不是只停留在待辦清單">action item closure&lt;/a> 使用。&lt;/p></description><content:encoded><![CDATA[<p>Evidence package 的核心概念是「把查詢、時間窗、資料品質限制與 owner 打包成可交接證據」。它連接 <a href="/blog/backend/knowledge-cards/log/" data-link-title="Log" data-link-desc="說明 log 如何記錄單一事件的上下文並支援事故排查">log</a>、<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/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline</a>，讓事故與驗證能回放同一組事實。</p>
<h2 id="概念位置">概念位置</h2>
<p>Evidence package 位在 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</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/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review</a> 之間。Dashboard 提供操作視角，SLO 提供判讀門檻，evidence package 保存支撐判斷的來源、時間窗、查詢入口與限制。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 evidence package 的訊號是同一段事故證據在交班、release gate 或復盤時反覆被重新查證。常見例子是只保存截圖，下一班 on-call 看得到圖表形狀，卻缺少 query、time range、sampling ratio、ingest delay 與 owner，導致決策背景需要重新建立。</p>
<h2 id="設計責任">設計責任</h2>
<p>Evidence package 要包含 source、time range、query link、owner、data quality、confidence、known gap 與 retention。它的責任是讓證據可查、可解釋、可重跑，並能交給 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a>、<a href="/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state</a> 或 <a href="/blog/backend/knowledge-cards/action-item-closure/" data-link-title="Action Item Closure" data-link-desc="說明事故行動項如何被驗證完成，而不是只停留在待辦清單">action item closure</a> 使用。</p>
]]></content:encoded></item><item><title>Time Range</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/time-range/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/time-range/</guid><description>&lt;p>Time range 的核心概念是「證據或查詢對應的明確時間窗」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state&lt;/a>，讓同一組資料能被事中交班、release gate 與事後復盤一致解讀。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Time range 位在 &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/query-link/" data-link-title="Query Link" data-link-desc="說明證據包如何保存可重跑查詢入口，而不是只保留截圖或口頭結論">query link&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a> 之間。Dashboard 顯示狀態，query link 保留查詢入口，time range 則定義這次判讀看的時間範圍。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 time range 的訊號是：&lt;/p>
&lt;ul>
&lt;li>同一張圖在不同時間重跑會得到不同結果&lt;/li>
&lt;li>release gate 要判斷某批 rollout 是否已穩定&lt;/li>
&lt;li>事故交班需要知道某個 evidence 觀察的是哪段時間&lt;/li>
&lt;li>復盤要對齊 deploy、alert、customer report 與 rollback 的先後&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>資料庫 migration 的 validation query 若標示 &lt;code>2026-05-11T02:10:00Z/2026-05-11T02:20:00Z&lt;/code>，下一班 on-call 就能把 mismatch、replication lag 與 slow query 放回同一個 backfill batch 判讀。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Time range 要定義開始時間、結束時間、時區、資料延遲限制與關聯事件。它應進入 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-condition/" data-link-title="Rollback Condition" data-link-desc="說明決策執行後出現哪些訊號時要撤回、回退或改路線">rollback condition&lt;/a>，避免團隊用不同時間窗比較同一個決策。&lt;/p></description><content:encoded><![CDATA[<p>Time range 的核心概念是「證據或查詢對應的明確時間窗」。它連接 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a>、<a href="/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline</a> 與 <a href="/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state</a>，讓同一組資料能被事中交班、release gate 與事後復盤一致解讀。</p>
<h2 id="概念位置">概念位置</h2>
<p>Time range 位在 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a>、<a href="/blog/backend/knowledge-cards/query-link/" data-link-title="Query Link" data-link-desc="說明證據包如何保存可重跑查詢入口，而不是只保留截圖或口頭結論">query link</a> 與 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a> 之間。Dashboard 顯示狀態，query link 保留查詢入口，time range 則定義這次判讀看的時間範圍。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 time range 的訊號是：</p>
<ul>
<li>同一張圖在不同時間重跑會得到不同結果</li>
<li>release gate 要判斷某批 rollout 是否已穩定</li>
<li>事故交班需要知道某個 evidence 觀察的是哪段時間</li>
<li>復盤要對齊 deploy、alert、customer report 與 rollback 的先後</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>資料庫 migration 的 validation query 若標示 <code>2026-05-11T02:10:00Z/2026-05-11T02:20:00Z</code>，下一班 on-call 就能把 mismatch、replication lag 與 slow query 放回同一個 backfill batch 判讀。</p>
<h2 id="設計責任">設計責任</h2>
<p>Time range 要定義開始時間、結束時間、時區、資料延遲限制與關聯事件。它應進入 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a> 與 <a href="/blog/backend/knowledge-cards/rollback-condition/" data-link-title="Rollback Condition" data-link-desc="說明決策執行後出現哪些訊號時要撤回、回退或改路線">rollback condition</a>，避免團隊用不同時間窗比較同一個決策。</p>
]]></content:encoded></item><item><title>Incident Decision Log</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/</link><pubDate>Thu, 07 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/</guid><description>&lt;p>Incident decision log 的核心概念是「把事故期間的已決事項與證據鏈保存成可回放紀錄」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">incident command system&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a>，讓事中交班與事後復盤使用同一組決策背景。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Incident decision log 位在 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-communication-channel/" data-link-title="Incident Communication Channel" data-link-desc="說明事故期間內外部溝通要使用哪些固定通道與節奏">incident communication channel&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review&lt;/a> 之間。它保存的是決策內容、時間、證據、owner、預期效果與回退條件，timeline 則保存事故事件順序。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 incident decision log 的訊號是事故結束後很難說清楚某次 rollback、degradation 或 vendor escalation 的決策依據。常見例子是聊天頻道有大量討論，但缺少明確的「何時決定、基於哪些 evidence、誰執行、什麼條件下改路線」。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Incident decision log 要支援 handoff、multi-incident coordination、stakeholder update 與 post-incident review。它的欄位應足夠輕量，讓事故現場能持續更新，同時足夠完整，能把缺口回寫到 &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/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/action-item-closure/" data-link-title="Action Item Closure" data-link-desc="說明事故行動項如何被驗證完成，而不是只停留在待辦清單">action item closure&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Incident decision log 的核心概念是「把事故期間的已決事項與證據鏈保存成可回放紀錄」。它連接 <a href="/blog/backend/knowledge-cards/incident-command-system/" data-link-title="Incident Command System" data-link-desc="說明事故期間的指揮角色、決策邊界與協作方式">incident command system</a>、<a href="/blog/backend/knowledge-cards/incident-timeline/" data-link-title="Incident Timeline" data-link-desc="說明事故時間線如何支援判斷、溝通與復盤">incident timeline</a> 與 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a>，讓事中交班與事後復盤使用同一組決策背景。</p>
<h2 id="概念位置">概念位置</h2>
<p>Incident decision log 位在 <a href="/blog/backend/knowledge-cards/on-call/" data-link-title="On-Call" data-link-desc="說明值班制度如何承接告警、事故分級與升級流程">on-call</a>、<a href="/blog/backend/knowledge-cards/incident-communication-channel/" data-link-title="Incident Communication Channel" data-link-desc="說明事故期間內外部溝通要使用哪些固定通道與節奏">incident communication channel</a> 與 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review</a> 之間。它保存的是決策內容、時間、證據、owner、預期效果與回退條件，timeline 則保存事故事件順序。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 incident decision log 的訊號是事故結束後很難說清楚某次 rollback、degradation 或 vendor escalation 的決策依據。常見例子是聊天頻道有大量討論，但缺少明確的「何時決定、基於哪些 evidence、誰執行、什麼條件下改路線」。</p>
<h2 id="設計責任">設計責任</h2>
<p>Incident decision log 要支援 handoff、multi-incident coordination、stakeholder update 與 post-incident review。它的欄位應足夠輕量，讓事故現場能持續更新，同時足夠完整，能把缺口回寫到 <a href="/blog/backend/knowledge-cards/runbook/" data-link-title="Runbook" data-link-desc="說明 runbook 如何把事故判斷與操作步驟標準化">runbook</a>、<a href="/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state</a> 與 <a href="/blog/backend/knowledge-cards/action-item-closure/" data-link-title="Action Item Closure" data-link-desc="說明事故行動項如何被驗證完成，而不是只停留在待辦清單">action item closure</a>。</p>
]]></content:encoded></item><item><title>Query Link</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/query-link/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/query-link/</guid><description>&lt;p>Query link 的核心概念是「保存可重跑的查詢入口」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/time-range/" data-link-title="Time Range" data-link-desc="說明證據、查詢與事故判讀如何用時間窗保留可回放上下文">time range&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-quality/" data-link-title="Data Quality" data-link-desc="說明證據欄位如何標示 completeness、freshness、sampling 與資料限制">data quality&lt;/a>，讓後續接手者能重新驗證同一個判讀。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Query link 位在 &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/validation-query/" data-link-title="Validation Query" data-link-desc="說明遷移、回填與修復期間如何用查詢證明資料語意是否一致">validation query&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a> 之間。截圖適合溝通當下狀態，query link 則保留可回放、可調整、可驗證的入口。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 query link 的訊號是：&lt;/p>
&lt;ul>
&lt;li>事故交班時下一班需要重跑同一個判讀&lt;/li>
&lt;li>release gate 要引用具體查詢結果，而不是貼圖表摘要&lt;/li>
&lt;li>PIR reviewer 需要查證當時資料限制&lt;/li>
&lt;li>dashboard panel 版本變動可能改變圖表語意&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>Checkout API evidence package 可以保存錯誤率 query、p95 latency query 與 provider timeout query 的連結。資料庫 migration evidence package 則可以保存 row count、mismatch sample 與 replication lag query link。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Query link 要保留查詢版本、參數、time range、資料來源與 owner。它要搭配 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/known-gap/" data-link-title="Known Gap" data-link-desc="說明證據包如何明確保存已知缺口，避免下游高估證據完整性">known gap&lt;/a> 記錄查詢未覆蓋的資料範圍，避免截圖或 dashboard 名稱被誤當成完整證據。&lt;/p></description><content:encoded><![CDATA[<p>Query link 的核心概念是「保存可重跑的查詢入口」。它連接 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a>、<a href="/blog/backend/knowledge-cards/time-range/" data-link-title="Time Range" data-link-desc="說明證據、查詢與事故判讀如何用時間窗保留可回放上下文">time range</a> 與 <a href="/blog/backend/knowledge-cards/data-quality/" data-link-title="Data Quality" data-link-desc="說明證據欄位如何標示 completeness、freshness、sampling 與資料限制">data quality</a>，讓後續接手者能重新驗證同一個判讀。</p>
<h2 id="概念位置">概念位置</h2>
<p>Query link 位在 <a href="/blog/backend/knowledge-cards/dashboard/" data-link-title="Dashboard" data-link-desc="說明 dashboard 如何把關鍵訊號組成可判讀的服務狀態畫面">dashboard</a>、<a href="/blog/backend/knowledge-cards/validation-query/" data-link-title="Validation Query" data-link-desc="說明遷移、回填與修復期間如何用查詢證明資料語意是否一致">validation query</a> 與 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a> 之間。截圖適合溝通當下狀態，query link 則保留可回放、可調整、可驗證的入口。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 query link 的訊號是：</p>
<ul>
<li>事故交班時下一班需要重跑同一個判讀</li>
<li>release gate 要引用具體查詢結果，而不是貼圖表摘要</li>
<li>PIR reviewer 需要查證當時資料限制</li>
<li>dashboard panel 版本變動可能改變圖表語意</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>Checkout API evidence package 可以保存錯誤率 query、p95 latency query 與 provider timeout query 的連結。資料庫 migration evidence package 則可以保存 row count、mismatch sample 與 replication lag query link。</p>
<h2 id="設計責任">設計責任</h2>
<p>Query link 要保留查詢版本、參數、time range、資料來源與 owner。它要搭配 <a href="/blog/backend/knowledge-cards/known-gap/" data-link-title="Known Gap" data-link-desc="說明證據包如何明確保存已知缺口，避免下游高估證據完整性">known gap</a> 記錄查詢未覆蓋的資料範圍，避免截圖或 dashboard 名稱被誤當成完整證據。</p>
]]></content:encoded></item><item><title>Steady State</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/steady-state/</link><pubDate>Thu, 07 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/steady-state/</guid><description>&lt;p>Steady state 的核心概念是「系統在正常或受控退化期間仍應維持的服務能力」。它連接 &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/chaos-test/" data-link-title="Chaos Test" data-link-desc="說明透過受控故障注入驗證系統在異常條件下的恢復能力">chaos test&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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Steady state 位在 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius&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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>系統需要 steady state 的訊號是 chaos、failover 或 DR drill 只描述故障動作，缺少成功判準。常見例子是節點被關閉後 health check 仍為綠燈，但 checkout success、queue lag 或 client-side error rate 已經偏離使用者可接受範圍。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Steady state 要包含 success rate、latency、queue lag、data correctness、customer impact 與 recovery complete 門檻。它的責任是支援 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&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>Steady state 的核心概念是「系統在正常或受控退化期間仍應維持的服務能力」。它連接 <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/chaos-test/" data-link-title="Chaos Test" data-link-desc="說明透過受控故障注入驗證系統在異常條件下的恢復能力">chaos test</a> 與 <a href="/blog/backend/knowledge-cards/degradation/" data-link-title="Degradation" data-link-desc="說明服務部分能力失效時如何保留核心功能與控制風險">degradation</a>，讓實驗與事故共用同一組成功條件。</p>
<h2 id="概念位置">概念位置</h2>
<p>Steady state 位在 <a href="/blog/backend/knowledge-cards/error-budget/" data-link-title="Error Budget" data-link-desc="說明 SLO 允許的失敗額度如何影響發版與可靠性投入">error budget</a>、<a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius</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> 之間。它把可靠性承諾轉成可量測訊號，並說明故障期間哪些能力要維持、哪些能力可以受控退化。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>系統需要 steady state 的訊號是 chaos、failover 或 DR drill 只描述故障動作，缺少成功判準。常見例子是節點被關閉後 health check 仍為綠燈，但 checkout success、queue lag 或 client-side error rate 已經偏離使用者可接受範圍。</p>
<h2 id="設計責任">設計責任</h2>
<p>Steady state 要包含 success rate、latency、queue lag、data correctness、customer impact 與 recovery complete 門檻。它的責任是支援 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a>、<a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a> 與 <a href="/blog/backend/knowledge-cards/game-day/" data-link-title="Game Day" data-link-desc="說明事故演練如何驗證流程、工具與團隊協作">game day</a> 判斷實驗是否通過、事故是否恢復。</p>
]]></content:encoded></item><item><title>Static Stability</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/static-stability/</link><pubDate>Tue, 23 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/static-stability/</guid><description>&lt;p>Static stability 的核心概念是「資料面在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/control-plane/" data-link-title="Control Plane" data-link-desc="負責下發策略、配置與路由決策的控制層">control plane&lt;/a> 失效時仍能維持服務」。設計約束是資料面必須快取控制面最後已知的好配置，並在控制面不可用時用快取繼續運作，不依賴控制面即時回應。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Static stability 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/control-plane/" data-link-title="Control Plane" data-link-desc="負責下發策略、配置與路由決策的控制層">control plane&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius&lt;/a> 之間。它把控制面失效的影響限制在「新配置無法推送」，而非「現有服務中斷」。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state&lt;/a> 的關係是：static stability 定義了控制面失效期間的 degraded steady state — 服務能力受限但仍在可接受範圍。&lt;/p>
&lt;h2 id="核心機制">核心機制&lt;/h2>
&lt;p>Static stability 依賴三個機制：快取最後已知好配置（控制面失效時不嘗試重新取得）、預計算 fallback 路徑（控制面在線時就 build 好備用配置）、constant work pattern（失敗模式下的工作量跟正常時相同，避免 retry storm 放大負載）。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 static stability 設計的訊號是控制面重啟或網路隔離時，資料面同時不可用。典型例子是 service mesh 的 control plane 掛掉後 sidecar 無法取得路由表、導致所有服務間通訊中斷；static stability 設計讓 sidecar 用快取的路由表繼續服務。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Static stability 的責任是讓 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">DR&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> 的關係是：static stability 是 readiness review 的前置項 — 若資料面沒有控制面失效時的自主能力，readiness 就有結構性缺口。&lt;/p></description><content:encoded><![CDATA[<p>Static stability 的核心概念是「資料面在 <a href="/blog/backend/knowledge-cards/control-plane/" data-link-title="Control Plane" data-link-desc="負責下發策略、配置與路由決策的控制層">control plane</a> 失效時仍能維持服務」。設計約束是資料面必須快取控制面最後已知的好配置，並在控制面不可用時用快取繼續運作，不依賴控制面即時回應。</p>
<h2 id="概念位置">概念位置</h2>
<p>Static stability 位在 <a href="/blog/backend/knowledge-cards/control-plane/" data-link-title="Control Plane" data-link-desc="負責下發策略、配置與路由決策的控制層">control plane</a> 與 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius</a> 之間。它把控制面失效的影響限制在「新配置無法推送」，而非「現有服務中斷」。跟 <a href="/blog/backend/knowledge-cards/steady-state/" data-link-title="Steady State" data-link-desc="說明可靠性實驗與事故恢復如何定義系統應維持的可接受狀態">steady state</a> 的關係是：static stability 定義了控制面失效期間的 degraded steady state — 服務能力受限但仍在可接受範圍。</p>
<h2 id="核心機制">核心機制</h2>
<p>Static stability 依賴三個機制：快取最後已知好配置（控制面失效時不嘗試重新取得）、預計算 fallback 路徑（控制面在線時就 build 好備用配置）、constant work pattern（失敗模式下的工作量跟正常時相同，避免 retry storm 放大負載）。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 static stability 設計的訊號是控制面重啟或網路隔離時，資料面同時不可用。典型例子是 service mesh 的 control plane 掛掉後 sidecar 無法取得路由表、導致所有服務間通訊中斷；static stability 設計讓 sidecar 用快取的路由表繼續服務。</p>
<h2 id="設計責任">設計責任</h2>
<p>Static stability 的責任是讓 <a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">DR</a> 設計不依賴已故障的控制面。它跟 <a href="/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness</a> 的關係是：static stability 是 readiness review 的前置項 — 若資料面沒有控制面失效時的自主能力，readiness 就有結構性缺口。</p>
]]></content:encoded></item><item><title>Data Quality</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/data-quality/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/data-quality/</guid><description>&lt;p>Data quality 的核心概念是「證據資料本身的完整度、新鮮度與限制」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="說明觀測資料如何抽樣以控制成本並保留診斷能力">sampling&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/known-gap/" data-link-title="Known Gap" data-link-desc="說明證據包如何明確保存已知缺口，避免下游高估證據完整性">known gap&lt;/a>，讓下游知道這份 evidence 能支持到哪個判斷範圍。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Data quality 位在 &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/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a> 之間。Metric、log、trace、audit log 都可能有延遲、抽樣、drop、masking 或 schema drift，這些限制要跟證據一起交接。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 data quality 的訊號是：&lt;/p>
&lt;ul>
&lt;li>trace sampling 讓某些 request path 無法完整重建&lt;/li>
&lt;li>log pipeline 有 ingest delay 或 drop&lt;/li>
&lt;li>query 只跑 primary、replica 或部分 tenant&lt;/li>
&lt;li>dashboard 結論需要標示 freshness 或 completeness 限制&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>資料庫 migration 的 evidence package 可以標示 &lt;code>primary only; replica lag still recovering&lt;/code>，表示 validation query 可信，但 replica 讀取路徑還不能用同一份 evidence 直接放行。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Data quality 要標示 completeness、freshness、sampling、masking、retention 與 owner。它要支援 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/confidence/" data-link-title="Confidence" data-link-desc="說明證據包如何標示 confirmed、suspected 或 needs follow-up 的判讀信心">confidence&lt;/a> 判讀，避免 release gate 或 incident decision log 把有限資料誤當成完整事實。&lt;/p></description><content:encoded><![CDATA[<p>Data quality 的核心概念是「證據資料本身的完整度、新鮮度與限制」。它連接 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a>、<a href="/blog/backend/knowledge-cards/sampling/" data-link-title="Sampling" data-link-desc="說明觀測資料如何抽樣以控制成本並保留診斷能力">sampling</a> 與 <a href="/blog/backend/knowledge-cards/known-gap/" data-link-title="Known Gap" data-link-desc="說明證據包如何明確保存已知缺口，避免下游高估證據完整性">known gap</a>，讓下游知道這份 evidence 能支持到哪個判斷範圍。</p>
<h2 id="概念位置">概念位置</h2>
<p>Data quality 位在 <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/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a> 之間。Metric、log、trace、audit log 都可能有延遲、抽樣、drop、masking 或 schema drift，這些限制要跟證據一起交接。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 data quality 的訊號是：</p>
<ul>
<li>trace sampling 讓某些 request path 無法完整重建</li>
<li>log pipeline 有 ingest delay 或 drop</li>
<li>query 只跑 primary、replica 或部分 tenant</li>
<li>dashboard 結論需要標示 freshness 或 completeness 限制</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>資料庫 migration 的 evidence package 可以標示 <code>primary only; replica lag still recovering</code>，表示 validation query 可信，但 replica 讀取路徑還不能用同一份 evidence 直接放行。</p>
<h2 id="設計責任">設計責任</h2>
<p>Data quality 要標示 completeness、freshness、sampling、masking、retention 與 owner。它要支援 <a href="/blog/backend/knowledge-cards/confidence/" data-link-title="Confidence" data-link-desc="說明證據包如何標示 confirmed、suspected 或 needs follow-up 的判讀信心">confidence</a> 判讀，避免 release gate 或 incident decision log 把有限資料誤當成完整事實。</p>
]]></content:encoded></item><item><title>Resiliency Matrix</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/resiliency-matrix/</link><pubDate>Tue, 23 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/resiliency-matrix/</guid><description>&lt;p>Resiliency matrix 的核心概念是「用 service × failure mode 的交叉矩陣，把系統的防護狀態從隱性假設變成可檢查資產」。每個交叉點標記 covered（有防護且已驗證）、gap（已知缺口待補）或 in-progress（防護建置中），讓團隊能系統性地追蹤 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius&lt;/a> 覆蓋。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Resiliency matrix 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius&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> 之間。它把失敗模式盤點（FMEA / pre-mortem）的產出結構化成可追蹤矩陣，並驅動 &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> 演練題目的選擇 — gap 欄直接成為演練的優先目標。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 resiliency matrix 的訊號是團隊知道有風險但不確定哪些已有防護。典型例子是高峰活動前的準備流程：把所有關鍵服務列成行、所有失敗模式（依賴斷線 / 容量超限 / 資料污染 / 配置漂移）列成列，逐格檢查防護狀態。Shopify 在 BFCM 準備中使用這個工具把年度驗證進度視覺化。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Resiliency matrix 的責任是把 reliability debt 從模糊的「我們知道有缺口」變成可排序、可追蹤的清單。它的維護節奏跟 &lt;a href="https://tarrragon.github.io/blog/backend/06-reliability/reliability-debt-backlog/" data-link-title="6.21 Reliability Debt Backlog" data-link-desc="把反覆事故、演練缺口與手動修復累積成可排序、可關閉的 reliability debt">6.21 reliability debt backlog&lt;/a> 對齊 — 每次演練後更新 matrix 的 gap/covered 狀態，每季 review matrix 的完整性。matrix 變成文件而不是工具（超過 6 個月未更新、gap 無 owner）是治理失敗的訊號。&lt;/p></description><content:encoded><![CDATA[<p>Resiliency matrix 的核心概念是「用 service × failure mode 的交叉矩陣，把系統的防護狀態從隱性假設變成可檢查資產」。每個交叉點標記 covered（有防護且已驗證）、gap（已知缺口待補）或 in-progress（防護建置中），讓團隊能系統性地追蹤 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius</a> 覆蓋。</p>
<h2 id="概念位置">概念位置</h2>
<p>Resiliency matrix 位在 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">blast radius</a> 與 <a href="/blog/backend/knowledge-cards/readiness/" data-link-title="Readiness" data-link-desc="說明 instance 何時可以安全接收流量，以及 readiness 如何和部署平台協作">readiness</a> 之間。它把失敗模式盤點（FMEA / pre-mortem）的產出結構化成可追蹤矩陣，並驅動 <a href="/blog/backend/knowledge-cards/game-day/" data-link-title="Game Day" data-link-desc="說明事故演練如何驗證流程、工具與團隊協作">game day</a> 演練題目的選擇 — gap 欄直接成為演練的優先目標。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 resiliency matrix 的訊號是團隊知道有風險但不確定哪些已有防護。典型例子是高峰活動前的準備流程：把所有關鍵服務列成行、所有失敗模式（依賴斷線 / 容量超限 / 資料污染 / 配置漂移）列成列，逐格檢查防護狀態。Shopify 在 BFCM 準備中使用這個工具把年度驗證進度視覺化。</p>
<h2 id="設計責任">設計責任</h2>
<p>Resiliency matrix 的責任是把 reliability debt 從模糊的「我們知道有缺口」變成可排序、可追蹤的清單。它的維護節奏跟 <a href="/blog/backend/06-reliability/reliability-debt-backlog/" data-link-title="6.21 Reliability Debt Backlog" data-link-desc="把反覆事故、演練缺口與手動修復累積成可排序、可關閉的 reliability debt">6.21 reliability debt backlog</a> 對齊 — 每次演練後更新 matrix 的 gap/covered 狀態，每季 review matrix 的完整性。matrix 變成文件而不是工具（超過 6 個月未更新、gap 無 owner）是治理失敗的訊號。</p>
]]></content:encoded></item><item><title>Confidence</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/confidence/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/confidence/</guid><description>&lt;p>Confidence 的核心概念是「標示目前證據能支持決策的信心等級」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-quality/" data-link-title="Data Quality" data-link-desc="說明證據欄位如何標示 completeness、freshness、sampling 與資料限制">data quality&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/gate-decision/" data-link-title="Gate Decision" data-link-desc="說明 release gate 如何把證據轉成放行、暫停、回退或補證據的決策">gate decision&lt;/a>，讓團隊能區分 confirmed、suspected 與 needs follow-up。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Confidence 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/query-link/" data-link-title="Query Link" data-link-desc="說明證據包如何保存可重跑查詢入口，而不是只保留截圖或口頭結論">query link&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/known-gap/" data-link-title="Known Gap" data-link-desc="說明證據包如何明確保存已知缺口，避免下游高估證據完整性">known gap&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log&lt;/a> 之間。它不是情緒性的「我覺得」，而是基於證據完整度、資料限制與反向驗證狀態的判讀欄位。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 confidence 的訊號是：&lt;/p>
&lt;ul>
&lt;li>evidence 足以支持繼續 backfill，但不足以支持使用者可見 cutover&lt;/li>
&lt;li>事故中某個根因還在 suspected 狀態&lt;/li>
&lt;li>release gate 需要分辨可以放行、暫停或補證據&lt;/li>
&lt;li>stakeholder update 需要避免把未確認資訊說成事實&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>資料庫 migration 的 evidence package 可以把 &lt;code>confidence&lt;/code> 標成 &lt;code>suspected&lt;/code>：validation query 顯示 mismatch 低於門檻，但 manual refund repair path 尚未被抽樣，因此只放行下一批 backfill，不放行使用者可見讀取 cutover。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Confidence 要定義等級、證據依據、限制與下一步。它要與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/known-gap/" data-link-title="Known Gap" data-link-desc="說明證據包如何明確保存已知缺口，避免下游高估證據完整性">known gap&lt;/a> 和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-condition/" data-link-title="Rollback Condition" data-link-desc="說明決策執行後出現哪些訊號時要撤回、回退或改路線">rollback condition&lt;/a> 一起保存，避免團隊把暫時結論當成穩定事實。&lt;/p></description><content:encoded><![CDATA[<p>Confidence 的核心概念是「標示目前證據能支持決策的信心等級」。它連接 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a>、<a href="/blog/backend/knowledge-cards/data-quality/" data-link-title="Data Quality" data-link-desc="說明證據欄位如何標示 completeness、freshness、sampling 與資料限制">data quality</a> 與 <a href="/blog/backend/knowledge-cards/gate-decision/" data-link-title="Gate Decision" data-link-desc="說明 release gate 如何把證據轉成放行、暫停、回退或補證據的決策">gate decision</a>，讓團隊能區分 confirmed、suspected 與 needs follow-up。</p>
<h2 id="概念位置">概念位置</h2>
<p>Confidence 位在 <a href="/blog/backend/knowledge-cards/query-link/" data-link-title="Query Link" data-link-desc="說明證據包如何保存可重跑查詢入口，而不是只保留截圖或口頭結論">query link</a>、<a href="/blog/backend/knowledge-cards/known-gap/" data-link-title="Known Gap" data-link-desc="說明證據包如何明確保存已知缺口，避免下游高估證據完整性">known gap</a> 與 <a href="/blog/backend/knowledge-cards/incident-decision-log/" data-link-title="Incident Decision Log" data-link-desc="說明事故期間如何保留決策、證據、owner 與回退條件">incident decision log</a> 之間。它不是情緒性的「我覺得」，而是基於證據完整度、資料限制與反向驗證狀態的判讀欄位。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 confidence 的訊號是：</p>
<ul>
<li>evidence 足以支持繼續 backfill，但不足以支持使用者可見 cutover</li>
<li>事故中某個根因還在 suspected 狀態</li>
<li>release gate 需要分辨可以放行、暫停或補證據</li>
<li>stakeholder update 需要避免把未確認資訊說成事實</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>資料庫 migration 的 evidence package 可以把 <code>confidence</code> 標成 <code>suspected</code>：validation query 顯示 mismatch 低於門檻，但 manual refund repair path 尚未被抽樣，因此只放行下一批 backfill，不放行使用者可見讀取 cutover。</p>
<h2 id="設計責任">設計責任</h2>
<p>Confidence 要定義等級、證據依據、限制與下一步。它要與 <a href="/blog/backend/knowledge-cards/known-gap/" data-link-title="Known Gap" data-link-desc="說明證據包如何明確保存已知缺口，避免下游高估證據完整性">known gap</a> 和 <a href="/blog/backend/knowledge-cards/rollback-condition/" data-link-title="Rollback Condition" data-link-desc="說明決策執行後出現哪些訊號時要撤回、回退或改路線">rollback condition</a> 一起保存，避免團隊把暫時結論當成穩定事實。</p>
]]></content:encoded></item><item><title>Known Gap</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/known-gap/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/known-gap/</guid><description>&lt;p>Known gap 的核心概念是「把已知但尚未覆蓋的證據缺口寫進 artifact」。它連接 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-quality/" data-link-title="Data Quality" data-link-desc="說明證據欄位如何標示 completeness、freshness、sampling 與資料限制">data quality&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/action-item-closure/" data-link-title="Action Item Closure" data-link-desc="說明事故行動項如何被驗證完成，而不是只停留在待辦清單">action item closure&lt;/a>，讓缺口能被追蹤、交班與回寫。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Known gap 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/confidence/" data-link-title="Confidence" data-link-desc="說明證據包如何標示 confirmed、suspected 或 needs follow-up 的判讀信心">confidence&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/query-link/" data-link-title="Query Link" data-link-desc="說明證據包如何保存可重跑查詢入口，而不是只保留截圖或口頭結論">query link&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review&lt;/a> 之間。Data quality 說明資料限制，known gap 則列出目前尚未被證據覆蓋的具體範圍。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 known gap 的訊號是：&lt;/p>
&lt;ul>
&lt;li>某些 tenant、region、callback path 或 manual repair path 未被抽樣&lt;/li>
&lt;li>trace 或 log 缺少關鍵 span / field&lt;/li>
&lt;li>release gate 放行時仍有需要 follow-up 的證據缺口&lt;/li>
&lt;li>PIR 需要把缺口回寫成 readiness 或 observability 改善項&lt;/li>
&lt;/ul>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>資料庫 migration evidence package 可以記錄 &lt;code>manual refund repair path not yet sampled&lt;/code>。這個 known gap 會限制 cutover decision，並回寫成後續 validation query 或 audit log coverage 的改善項。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Known gap 要描述缺口內容、影響範圍、目前風險、owner 與 follow-up。它要支援 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/confidence/" data-link-title="Confidence" data-link-desc="說明證據包如何標示 confirmed、suspected 或 needs follow-up 的判讀信心">confidence&lt;/a> 分級，避免 evidence package 看起來完整，但實際漏掉高風險路徑。&lt;/p></description><content:encoded><![CDATA[<p>Known gap 的核心概念是「把已知但尚未覆蓋的證據缺口寫進 artifact」。它連接 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">evidence package</a>、<a href="/blog/backend/knowledge-cards/data-quality/" data-link-title="Data Quality" data-link-desc="說明證據欄位如何標示 completeness、freshness、sampling 與資料限制">data quality</a> 與 <a href="/blog/backend/knowledge-cards/action-item-closure/" data-link-title="Action Item Closure" data-link-desc="說明事故行動項如何被驗證完成，而不是只停留在待辦清單">action item closure</a>，讓缺口能被追蹤、交班與回寫。</p>
<h2 id="概念位置">概念位置</h2>
<p>Known gap 位在 <a href="/blog/backend/knowledge-cards/confidence/" data-link-title="Confidence" data-link-desc="說明證據包如何標示 confirmed、suspected 或 needs follow-up 的判讀信心">confidence</a>、<a href="/blog/backend/knowledge-cards/query-link/" data-link-title="Query Link" data-link-desc="說明證據包如何保存可重跑查詢入口，而不是只保留截圖或口頭結論">query link</a> 與 <a href="/blog/backend/knowledge-cards/post-incident-review/" data-link-title="Post-Incident Review" data-link-desc="說明事故後如何完成復盤、學習與改進閉環">post-incident review</a> 之間。Data quality 說明資料限制，known gap 則列出目前尚未被證據覆蓋的具體範圍。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 known gap 的訊號是：</p>
<ul>
<li>某些 tenant、region、callback path 或 manual repair path 未被抽樣</li>
<li>trace 或 log 缺少關鍵 span / field</li>
<li>release gate 放行時仍有需要 follow-up 的證據缺口</li>
<li>PIR 需要把缺口回寫成 readiness 或 observability 改善項</li>
</ul>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>資料庫 migration evidence package 可以記錄 <code>manual refund repair path not yet sampled</code>。這個 known gap 會限制 cutover decision，並回寫成後續 validation query 或 audit log coverage 的改善項。</p>
<h2 id="設計責任">設計責任</h2>
<p>Known gap 要描述缺口內容、影響範圍、目前風險、owner 與 follow-up。它要支援 <a href="/blog/backend/knowledge-cards/confidence/" data-link-title="Confidence" data-link-desc="說明證據包如何標示 confirmed、suspected 或 needs follow-up 的判讀信心">confidence</a> 分級，避免 evidence package 看起來完整，但實際漏掉高風險路徑。</p>
]]></content:encoded></item><item><title>Write-Ahead Log</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/write-ahead-log/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/write-ahead-log/</guid><description>&lt;p>Write-Ahead Log（WAL）的核心概念是把每筆寫入先 append 到一個循序 log，再由背景程序合併回主要資料檔。這個順序讓資料庫在 crash 後能用 log 重放回到一致狀態，也讓 reader 與 writer 的衝突降低。WAL 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/single-writer-model/" data-link-title="Single Writer Model" data-link-desc="說明單寫者模型如何序列化寫入，並成為系統的容量邊界">Single Writer Model&lt;/a> 的持久化基礎、是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-slot/" data-link-title="Replication Slot" data-link-desc="說明邏輯複製如何用 slot 追蹤消費進度，並對來源端造成保留壓力">Replication Slot&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture&lt;/a> 的事件來源，累積的 log 由 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間處理流程如何記錄可恢復進度">Checkpoint&lt;/a> 收斂。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>WAL 位在資料庫的 durability 與 recovery 機制核心。SQLite 的 WAL mode、PostgreSQL 的 WAL、MySQL InnoDB 的 redo log 都是同一個 write-ahead 原則的實作。它和記錄業務歷史的 &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> 是不同層：WAL 是引擎內部的 recovery 結構，&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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要理解 WAL 的訊號是寫入延遲、磁碟用量或 crash recovery 時間出現異常。WAL 檔持續長大通常代表 checkpoint 落後，或有長交易、inactive replication slot 卡住 log 回收；crash 後啟動變慢通常代表要重放的 WAL 區段過大。電商在尖峰寫入時若 WAL 成長速度超過 checkpoint，磁碟會先到上限。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計上要決定 WAL 的 checkpoint 頻率、保留長度、磁碟容量餘裕與監控指標。WAL 同時被 crash recovery、replication 與 CDC 三條路徑依賴，保留策略要同時滿足三者：保留太短會讓 replica 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-slot/" data-link-title="Replication Slot" data-link-desc="說明邏輯複製如何用 slot 追蹤消費進度，並對來源端造成保留壓力">Replication Slot&lt;/a> 追不上，保留太長會占用磁碟。observability 要看 WAL 生成速率、checkpoint lag 與最舊仍被保留的 log 位置。&lt;/p></description><content:encoded><![CDATA[<p>Write-Ahead Log（WAL）的核心概念是把每筆寫入先 append 到一個循序 log，再由背景程序合併回主要資料檔。這個順序讓資料庫在 crash 後能用 log 重放回到一致狀態，也讓 reader 與 writer 的衝突降低。WAL 是 <a href="/blog/backend/knowledge-cards/single-writer-model/" data-link-title="Single Writer Model" data-link-desc="說明單寫者模型如何序列化寫入，並成為系統的容量邊界">Single Writer Model</a> 的持久化基礎、是 <a href="/blog/backend/knowledge-cards/replication-slot/" data-link-title="Replication Slot" data-link-desc="說明邏輯複製如何用 slot 追蹤消費進度，並對來源端造成保留壓力">Replication Slot</a> 與 <a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture</a> 的事件來源，累積的 log 由 <a href="/blog/backend/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間處理流程如何記錄可恢復進度">Checkpoint</a> 收斂。</p>
<h2 id="概念位置">概念位置</h2>
<p>WAL 位在資料庫的 durability 與 recovery 機制核心。SQLite 的 WAL mode、PostgreSQL 的 WAL、MySQL InnoDB 的 redo log 都是同一個 write-ahead 原則的實作。它和記錄業務歷史的 <a href="/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">Event Log</a> 是不同層：WAL 是引擎內部的 recovery 結構，<a href="/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">Event Log</a> 是應用層可重播的事件流。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要理解 WAL 的訊號是寫入延遲、磁碟用量或 crash recovery 時間出現異常。WAL 檔持續長大通常代表 checkpoint 落後，或有長交易、inactive replication slot 卡住 log 回收；crash 後啟動變慢通常代表要重放的 WAL 區段過大。電商在尖峰寫入時若 WAL 成長速度超過 checkpoint，磁碟會先到上限。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計上要決定 WAL 的 checkpoint 頻率、保留長度、磁碟容量餘裕與監控指標。WAL 同時被 crash recovery、replication 與 CDC 三條路徑依賴，保留策略要同時滿足三者：保留太短會讓 replica 或 <a href="/blog/backend/knowledge-cards/replication-slot/" data-link-title="Replication Slot" data-link-desc="說明邏輯複製如何用 slot 追蹤消費進度，並對來源端造成保留壓力">Replication Slot</a> 追不上，保留太長會占用磁碟。observability 要看 WAL 生成速率、checkpoint lag 與最舊仍被保留的 log 位置。</p>
]]></content:encoded></item><item><title>Recording Rule</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/recording-rule/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/recording-rule/</guid><description>&lt;p>Recording rule 把重複的聚合計算從查詢時推到寫入時。當 dashboard 或 alert 反覆對同一組 raw &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics&lt;/a> 做 rate / sum / histogram_quantile，每次查詢都重新掃描原始資料；recording rule 把計算結果預先寫成新的 time series，查詢時直接讀取結果。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Recording rule 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics&lt;/a> 讀取路徑的效能工具。它在 TSDB 層（如 Prometheus、Thanos、Mimir）定期執行 query expression，把結果作為新 series 寫入儲存。概念上類似 OLAP 的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/materialized-view/" data-link-title="Materialized View" data-link-desc="說明預先計算並儲存查詢結果以加速讀取的資料結構">materialized view&lt;/a>，但作用在時間序列而非關聯式資料。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 recording rule 時要定義計算表達式、執行間隔、命名慣例與維護責任。命名慣例通常遵循 &lt;code>level:metric:operations&lt;/code> 格式（如 &lt;code>job:http_requests_total:rate5m&lt;/code>），讓讀者從名稱判斷來源、粒度與計算方式。&lt;/p>
&lt;p>Recording rule 產生的 series 本身也佔儲存空間與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">cardinality&lt;/a>。規則數量增長時，要監控 rule evaluation duration 跟 rule group lag，避免 rule 跑不完的情況讓 dashboard 看到過期資料。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>需要 recording rule 的訊號是 dashboard panel 載入時間持續退化、或 alert rule 因為 query timeout 而漏發。把 SLO burn rate 計算、高流量 endpoint 的 rate 與 error ratio 預先聚合成 recording rule，是最常見的起點。&lt;/p>
&lt;p>Recording rule 與 raw query 的分工：高頻讀取（dashboard 自動刷新、alert 每分鐘 evaluate）適合 recording rule；低頻即席查詢（事故時的 ad-hoc 切片）直接查 raw series，保留完整維度。&lt;/p>
&lt;p>在觀測領域的應用見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">4.2 metrics 聚合查詢&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/observability-query-design/" data-link-title="4.23 觀測查詢設計" data-link-desc="把觀測資料的讀取路徑當系統設計問題處理：三種查詢模式、storage tiering、pre-aggregation 與資源治理">4.23 觀測查詢設計&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Recording rule 把重複的聚合計算從查詢時推到寫入時。當 dashboard 或 alert 反覆對同一組 raw <a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics</a> 做 rate / sum / histogram_quantile，每次查詢都重新掃描原始資料；recording rule 把計算結果預先寫成新的 time series，查詢時直接讀取結果。</p>
<h2 id="概念位置">概念位置</h2>
<p>Recording rule 是 <a href="/blog/backend/knowledge-cards/metrics/" data-link-title="Metrics" data-link-desc="說明指標如何描述服務趨勢、容量與健康狀態">metrics</a> 讀取路徑的效能工具。它在 TSDB 層（如 Prometheus、Thanos、Mimir）定期執行 query expression，把結果作為新 series 寫入儲存。概念上類似 OLAP 的 <a href="/blog/backend/knowledge-cards/materialized-view/" data-link-title="Materialized View" data-link-desc="說明預先計算並儲存查詢結果以加速讀取的資料結構">materialized view</a>，但作用在時間序列而非關聯式資料。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 recording rule 時要定義計算表達式、執行間隔、命名慣例與維護責任。命名慣例通常遵循 <code>level:metric:operations</code> 格式（如 <code>job:http_requests_total:rate5m</code>），讓讀者從名稱判斷來源、粒度與計算方式。</p>
<p>Recording rule 產生的 series 本身也佔儲存空間與 <a href="/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">cardinality</a>。規則數量增長時，要監控 rule evaluation duration 跟 rule group lag，避免 rule 跑不完的情況讓 dashboard 看到過期資料。</p>
<h2 id="使用情境">使用情境</h2>
<p>需要 recording rule 的訊號是 dashboard panel 載入時間持續退化、或 alert rule 因為 query timeout 而漏發。把 SLO burn rate 計算、高流量 endpoint 的 rate 與 error ratio 預先聚合成 recording rule，是最常見的起點。</p>
<p>Recording rule 與 raw query 的分工：高頻讀取（dashboard 自動刷新、alert 每分鐘 evaluate）適合 recording rule；低頻即席查詢（事故時的 ad-hoc 切片）直接查 raw series，保留完整維度。</p>
<p>在觀測領域的應用見 <a href="/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">4.2 metrics 聚合查詢</a> 跟 <a href="/blog/backend/04-observability/observability-query-design/" data-link-title="4.23 觀測查詢設計" data-link-desc="把觀測資料的讀取路徑當系統設計問題處理：三種查詢模式、storage tiering、pre-aggregation 與資源治理">4.23 觀測查詢設計</a>。</p>
]]></content:encoded></item><item><title>Metadata Lock</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/metadata-lock/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/metadata-lock/</guid><description>&lt;p>Metadata Lock 的核心概念是資料庫為了保護 table 結構，在 DDL 與既有交易之間建立的相容鎖。任何讀寫某張表的交易都會持有該表的 metadata 讀鎖，DDL 需要 metadata 寫鎖；當一個長交易尚未結束，DDL 會排隊等待，而排在 DDL 後面的新查詢也會一起被擋住。它和處理 row 層並發的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">Isolation Level&lt;/a> 是不同層的鎖；要安全執行 schema 變更時要接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">Schema Migration&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/online-migration/" data-link-title="Online Migration" data-link-desc="說明服務持續接流量時如何完成資料或 schema 遷移">Online Migration&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Metadata Lock 位在 DDL workflow 與 DML transaction 的交界。MySQL 的 metadata lock、PostgreSQL 的 ACCESS EXCLUSIVE lock 都是同一類機制 — 它讓一個看似輕量的 ALTER 在有長交易時放大成全表查詢停滯。它和 &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> 直接相關：交易開得越久，越容易成為 DDL 的阻塞源。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要注意 metadata lock 的訊號是執行一個 ALTER 後，原本正常的查詢突然大量逾時或排隊。觀察 metadata lock 類系統表會看到 DDL 在等某個長交易、後面跟著一串 waiting 查詢。常見場景是部署期間跑 migration，剛好有一個忘了 commit 的交易或一個慢報表查詢，DDL 卡住、服務讀寫一起雪崩。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 schema 變更要先定義 DDL window、lock wait timeout 與長交易的處理策略。安全做法是在低流量窗口執行、設定 DDL 逾時讓它快速失敗而非無限等待、並先找出與終止 blocker 交易。大表結構變更應改用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/online-migration/" data-link-title="Online Migration" data-link-desc="說明服務持續接流量時如何完成資料或 schema 遷移">Online Migration&lt;/a> 工具，把一次性鎖換成可控的漸進搬移。runbook 要能快速定位「DDL 在等誰」與「誰被 DDL 擋住」。&lt;/p></description><content:encoded><![CDATA[<p>Metadata Lock 的核心概念是資料庫為了保護 table 結構，在 DDL 與既有交易之間建立的相容鎖。任何讀寫某張表的交易都會持有該表的 metadata 讀鎖，DDL 需要 metadata 寫鎖；當一個長交易尚未結束，DDL 會排隊等待，而排在 DDL 後面的新查詢也會一起被擋住。它和處理 row 層並發的 <a href="/blog/backend/knowledge-cards/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">Isolation Level</a> 是不同層的鎖；要安全執行 schema 變更時要接回 <a href="/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">Schema Migration</a> 與 <a href="/blog/backend/knowledge-cards/online-migration/" data-link-title="Online Migration" data-link-desc="說明服務持續接流量時如何完成資料或 schema 遷移">Online Migration</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Metadata Lock 位在 DDL workflow 與 DML transaction 的交界。MySQL 的 metadata lock、PostgreSQL 的 ACCESS EXCLUSIVE lock 都是同一類機制 — 它讓一個看似輕量的 ALTER 在有長交易時放大成全表查詢停滯。它和 <a href="/blog/backend/knowledge-cards/transaction-boundary/" data-link-title="Transaction Boundary" data-link-desc="說明哪些資料變更應在同一個交易中一起成功或一起回復">Transaction Boundary</a> 直接相關：交易開得越久，越容易成為 DDL 的阻塞源。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要注意 metadata lock 的訊號是執行一個 ALTER 後，原本正常的查詢突然大量逾時或排隊。觀察 metadata lock 類系統表會看到 DDL 在等某個長交易、後面跟著一串 waiting 查詢。常見場景是部署期間跑 migration，剛好有一個忘了 commit 的交易或一個慢報表查詢，DDL 卡住、服務讀寫一起雪崩。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 schema 變更要先定義 DDL window、lock wait timeout 與長交易的處理策略。安全做法是在低流量窗口執行、設定 DDL 逾時讓它快速失敗而非無限等待、並先找出與終止 blocker 交易。大表結構變更應改用 <a href="/blog/backend/knowledge-cards/online-migration/" data-link-title="Online Migration" data-link-desc="說明服務持續接流量時如何完成資料或 schema 遷移">Online Migration</a> 工具，把一次性鎖換成可控的漸進搬移。runbook 要能快速定位「DDL 在等誰」與「誰被 DDL 擋住」。</p>
]]></content:encoded></item><item><title>Rollup / Downsampling</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/rollup/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/rollup/</guid><description>&lt;p>Rollup 用降低時間精度換取儲存成本與查詢效能。原始資料以秒級或分鐘級採集，隨時間推移被聚合成更粗的粒度（5 分鐘、1 小時、1 天），舊的高精度資料可以刪除或歸檔。它是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/storage-tiering/" data-link-title="Storage Tiering" data-link-desc="說明按資料熱度分層儲存以平衡查詢速度、儲存成本與保留完整性的機制">storage tiering&lt;/a> 在時間維度的具體實作，跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule&lt;/a> 分工互補。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Rollup 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/storage-tiering/" data-link-title="Storage Tiering" data-link-desc="說明按資料熱度分層儲存以平衡查詢速度、儲存成本與保留完整性的機制">storage tiering&lt;/a> 在時間維度的具體實作。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule&lt;/a> 的差別在於：recording rule 是降維度（把多個 label 聚合成一條 series），rollup 是降時間精度（把 15 秒的點變成 5 分鐘的點）。兩者經常搭配使用。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 rollup 時要定義每一層的精度、保留期、聚合函數與查詢路由規則。聚合函數的選擇影響查詢語意：對 counter 做 sum 跟對 gauge 做 average 是合理的；但對 histogram 做 average 會失去分布資訊。&lt;/p>
&lt;p>查詢路由是 rollup 設計的關鍵配套。使用者查詢 7 天範圍時系統自動路由到 5 分鐘粒度、查詢 90 天範圍時路由到 1 小時粒度。若路由不透明，使用者會對精度差異產生困惑。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>需要 rollup 的訊號是 TSDB 儲存成本持續成長、長時間範圍的 dashboard panel 查詢逾時、或保留政策因為儲存限制被迫縮短。Thanos compactor、Cortex/Mimir compactor、VictoriaMetrics downsampling 都是常見實作。&lt;/p>
&lt;p>在觀測領域的查詢設計見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">4.2 metrics 聚合查詢&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/observability-query-design/" data-link-title="4.23 觀測查詢設計" data-link-desc="把觀測資料的讀取路徑當系統設計問題處理：三種查詢模式、storage tiering、pre-aggregation 與資源治理">4.23 觀測查詢設計&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Rollup 用降低時間精度換取儲存成本與查詢效能。原始資料以秒級或分鐘級採集，隨時間推移被聚合成更粗的粒度（5 分鐘、1 小時、1 天），舊的高精度資料可以刪除或歸檔。它是 <a href="/blog/backend/knowledge-cards/storage-tiering/" data-link-title="Storage Tiering" data-link-desc="說明按資料熱度分層儲存以平衡查詢速度、儲存成本與保留完整性的機制">storage tiering</a> 在時間維度的具體實作，跟 <a href="/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule</a> 分工互補。</p>
<h2 id="概念位置">概念位置</h2>
<p>Rollup 是 <a href="/blog/backend/knowledge-cards/storage-tiering/" data-link-title="Storage Tiering" data-link-desc="說明按資料熱度分層儲存以平衡查詢速度、儲存成本與保留完整性的機制">storage tiering</a> 在時間維度的具體實作。它跟 <a href="/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule</a> 的差別在於：recording rule 是降維度（把多個 label 聚合成一條 series），rollup 是降時間精度（把 15 秒的點變成 5 分鐘的點）。兩者經常搭配使用。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 rollup 時要定義每一層的精度、保留期、聚合函數與查詢路由規則。聚合函數的選擇影響查詢語意：對 counter 做 sum 跟對 gauge 做 average 是合理的；但對 histogram 做 average 會失去分布資訊。</p>
<p>查詢路由是 rollup 設計的關鍵配套。使用者查詢 7 天範圍時系統自動路由到 5 分鐘粒度、查詢 90 天範圍時路由到 1 小時粒度。若路由不透明，使用者會對精度差異產生困惑。</p>
<h2 id="使用情境">使用情境</h2>
<p>需要 rollup 的訊號是 TSDB 儲存成本持續成長、長時間範圍的 dashboard panel 查詢逾時、或保留政策因為儲存限制被迫縮短。Thanos compactor、Cortex/Mimir compactor、VictoriaMetrics downsampling 都是常見實作。</p>
<p>在觀測領域的查詢設計見 <a href="/blog/backend/04-observability/metrics-basics/" data-link-title="4.2 metrics 與 SLI/SLO" data-link-desc="整理 counter、gauge、histogram 與服務健康指標">4.2 metrics 聚合查詢</a> 跟 <a href="/blog/backend/04-observability/observability-query-design/" data-link-title="4.23 觀測查詢設計" data-link-desc="把觀測資料的讀取路徑當系統設計問題處理：三種查詢模式、storage tiering、pre-aggregation 與資源治理">4.23 觀測查詢設計</a>。</p>
]]></content:encoded></item><item><title>Read-Write Split</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/read-write-split/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/read-write-split/</guid><description>&lt;p>Read-Write Split 的核心概念是把寫入導向 primary、把讀取導向一個或多個 replica，用 replica 擴展讀取容量。它讓讀多寫少的服務把壓力分散開，而不必全部集中在 primary，代價是 replica 有 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag&lt;/a>，剛寫入的資料可能還沒同步。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/transaction-pooling/" data-link-title="Transaction Pooling" data-link-desc="說明 connection pooler 的 transaction 綁定模式如何壓縮連線並改變 session 語意">Transaction Pooling&lt;/a> 一起決定連線怎麼分配；判斷讀到舊資料的後果時要接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Read-Write Split 位在 application 與資料庫拓撲之間的路由層。它可以由 proxy、driver 或 application 自己實作；路由規則要分辨 write、一般 read、交易內讀取與需要強一致的讀取（例如 SELECT &amp;hellip; FOR UPDATE）。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag&lt;/a> 直接耦合 — lag 越大，分流到 replica 的讀取看到舊資料的窗口越長。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合 read-write split 的訊號是 primary 的讀取壓力遠大於寫入、且多數讀取可以接受秒級延遲的資料。要特別處理的是「寫入後立刻讀」的流程：使用者送出訂單後馬上看訂單列表、後台改完權限馬上驗證，這些 read-after-write 路徑分到 replica 會讀到舊狀態。常見做法是讓這類路徑強制走 primary，或加一層 lag guard。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義路由規則、哪些讀取必須走 primary、交易內讀取如何 pin 在同一連線、以及 replica lag 超標時的降級策略。session 一致性要寫清楚：同一使用者的 read-after-write 是否保證。observability 要看 primary 與 replica 的讀寫分佈、replica lag，以及被 lag guard 擋回 primary 的比例。&lt;/p></description><content:encoded><![CDATA[<p>Read-Write Split 的核心概念是把寫入導向 primary、把讀取導向一個或多個 replica，用 replica 擴展讀取容量。它讓讀多寫少的服務把壓力分散開，而不必全部集中在 primary，代價是 replica 有 <a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag</a>，剛寫入的資料可能還沒同步。它和 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool</a>、<a href="/blog/backend/knowledge-cards/transaction-pooling/" data-link-title="Transaction Pooling" data-link-desc="說明 connection pooler 的 transaction 綁定模式如何壓縮連線並改變 session 語意">Transaction Pooling</a> 一起決定連線怎麼分配；判斷讀到舊資料的後果時要接回 <a href="/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Read-Write Split 位在 application 與資料庫拓撲之間的路由層。它可以由 proxy、driver 或 application 自己實作；路由規則要分辨 write、一般 read、交易內讀取與需要強一致的讀取（例如 SELECT &hellip; FOR UPDATE）。它和 <a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag</a> 直接耦合 — lag 越大，分流到 replica 的讀取看到舊資料的窗口越長。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合 read-write split 的訊號是 primary 的讀取壓力遠大於寫入、且多數讀取可以接受秒級延遲的資料。要特別處理的是「寫入後立刻讀」的流程：使用者送出訂單後馬上看訂單列表、後台改完權限馬上驗證，這些 read-after-write 路徑分到 replica 會讀到舊狀態。常見做法是讓這類路徑強制走 primary，或加一層 lag guard。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義路由規則、哪些讀取必須走 primary、交易內讀取如何 pin 在同一連線、以及 replica lag 超標時的降級策略。session 一致性要寫清楚：同一使用者的 read-after-write 是否保證。observability 要看 primary 與 replica 的讀寫分佈、replica lag，以及被 lag guard 擋回 primary 的比例。</p>
]]></content:encoded></item><item><title>Storage Tiering</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/storage-tiering/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/storage-tiering/</guid><description>&lt;p>Storage tiering 按資料被查詢的頻率與時間壓力，把資料放在不同速度與成本的儲存層。最近的資料放在快速儲存（hot tier），較舊的資料依序移到較慢但便宜的儲存（warm tier、cold tier），最終可歸檔到 object storage 或離線備份。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup&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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Storage tiering 是觀測資料管理的基礎設施層決策，影響查詢能力、成本結構與保留政策。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup&lt;/a> 的分工是：tiering 決定資料放在哪種儲存、rollup 決定資料以什麼精度存放。兩者共同構成觀測資料的生命週期管理。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 tiering 時要定義每一層的查詢 SLA、儲存成本、資料轉移觸發條件與跨層查詢行為。&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>Hot&lt;/td>
 &lt;td>SSD / in-memory TSDB&lt;/td>
 &lt;td>毫秒到秒&lt;/td>
 &lt;td>原始精度&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Warm&lt;/td>
 &lt;td>HDD / 分散式儲存&lt;/td>
 &lt;td>秒到十秒&lt;/td>
 &lt;td>原始或輕度 rollup&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cold&lt;/td>
 &lt;td>Object storage / S3&lt;/td>
 &lt;td>十秒到分鐘&lt;/td>
 &lt;td>rollup 或歸檔&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>跨層查詢是 tiering 設計的關鍵問題。當查詢範圍橫跨 hot 跟 warm 兩層時，回應時間由最慢的那層決定。使用者在 dashboard 把時間範圍從「最近 1 小時」拉到「最近 7 天」時，查詢延遲可能從毫秒跳到秒級，體驗落差需要在 UI 或文件中說明。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>需要 tiering 的訊號是觀測儲存成本持續成長但大部分查詢只命中最近的資料、或保留期因為成本壓力被迫縮短導致鑑識與稽核需求無法滿足。Elasticsearch ILM、Loki 的 chunk storage 分層、Thanos / Cortex 的 object storage backend 都是常見實作。&lt;/p>
&lt;p>Tiering 對查詢能力的影響見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/cardinality-cost-governance/" data-link-title="4.7 Cardinality 治理與成本邊界" data-link-desc="把 metric / log / trace 的 cardinality 與成本作為平台一級治理議題">4.7 cardinality 治理&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/observability-query-design/" data-link-title="4.23 觀測查詢設計" data-link-desc="把觀測資料的讀取路徑當系統設計問題處理：三種查詢模式、storage tiering、pre-aggregation 與資源治理">4.23 觀測查詢設計&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Storage tiering 按資料被查詢的頻率與時間壓力，把資料放在不同速度與成本的儲存層。最近的資料放在快速儲存（hot tier），較舊的資料依序移到較慢但便宜的儲存（warm tier、cold tier），最終可歸檔到 object storage 或離線備份。它跟 <a href="/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup</a> 共同構成觀測資料的生命週期管理，受 <a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">retention</a> 期限驅動。</p>
<h2 id="概念位置">概念位置</h2>
<p>Storage tiering 是觀測資料管理的基礎設施層決策，影響查詢能力、成本結構與保留政策。它跟 <a href="/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup</a> 的分工是：tiering 決定資料放在哪種儲存、rollup 決定資料以什麼精度存放。兩者共同構成觀測資料的生命週期管理。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 tiering 時要定義每一層的查詢 SLA、儲存成本、資料轉移觸發條件與跨層查詢行為。</p>
<table>
  <thead>
      <tr>
          <th>層級</th>
          <th>典型儲存</th>
          <th>查詢延遲</th>
          <th>資料精度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Hot</td>
          <td>SSD / in-memory TSDB</td>
          <td>毫秒到秒</td>
          <td>原始精度</td>
      </tr>
      <tr>
          <td>Warm</td>
          <td>HDD / 分散式儲存</td>
          <td>秒到十秒</td>
          <td>原始或輕度 rollup</td>
      </tr>
      <tr>
          <td>Cold</td>
          <td>Object storage / S3</td>
          <td>十秒到分鐘</td>
          <td>rollup 或歸檔</td>
      </tr>
  </tbody>
</table>
<p>跨層查詢是 tiering 設計的關鍵問題。當查詢範圍橫跨 hot 跟 warm 兩層時，回應時間由最慢的那層決定。使用者在 dashboard 把時間範圍從「最近 1 小時」拉到「最近 7 天」時，查詢延遲可能從毫秒跳到秒級，體驗落差需要在 UI 或文件中說明。</p>
<h2 id="使用情境">使用情境</h2>
<p>需要 tiering 的訊號是觀測儲存成本持續成長但大部分查詢只命中最近的資料、或保留期因為成本壓力被迫縮短導致鑑識與稽核需求無法滿足。Elasticsearch ILM、Loki 的 chunk storage 分層、Thanos / Cortex 的 object storage backend 都是常見實作。</p>
<p>Tiering 對查詢能力的影響見 <a href="/blog/backend/04-observability/cardinality-cost-governance/" data-link-title="4.7 Cardinality 治理與成本邊界" data-link-desc="把 metric / log / trace 的 cardinality 與成本作為平台一級治理議題">4.7 cardinality 治理</a> 跟 <a href="/blog/backend/04-observability/observability-query-design/" data-link-title="4.23 觀測查詢設計" data-link-desc="把觀測資料的讀取路徑當系統設計問題處理：三種查詢模式、storage tiering、pre-aggregation 與資源治理">4.23 觀測查詢設計</a>。</p>
]]></content:encoded></item><item><title>Replication Slot</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/replication-slot/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/replication-slot/</guid><description>&lt;p>Replication Slot 的核心概念是來源資料庫為每個下游 consumer 保留的進度標記 — 它記錄 consumer 確認到哪個位置，並據此保留尚未被消費的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/write-ahead-log/" data-link-title="Write-Ahead Log" data-link-desc="說明資料庫如何先寫入 log 再合併回主資料，以提供持久性與崩潰復原">Write-Ahead Log&lt;/a>。slot 讓 consumer 斷線後仍能從正確位置續傳，代價是 consumer 停擺時 log 會在來源端持續累積。它是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture&lt;/a> 與邏輯複製的進度基礎，和 messaging 的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">Offset&lt;/a> 相鄰但責任不同。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Replication Slot 位在來源資料庫與下游 consumer 之間，是一個有狀態的 production resource。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">Offset&lt;/a> 都是消費進度，差別在反壓方向：offset 落後不會壓垮 producer，slot 落後會讓來源端為了保留 WAL 而吃光磁碟。PostgreSQL 的 replication slot 是典型例子，&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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要監控 slot 的訊號是來源資料庫磁碟用量上升、但寫入量沒有等比增加。常見原因是 Debezium connector 或 replica 離線，slot 仍在保留 WAL。一個 inactive slot 在高寫入服務上可以在數小時內撐爆 primary 磁碟，屬於高優先事故訊號。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>每個 slot 要有明確 owner、健康 SLO 與 drop condition。設計上要監控每個 slot 的 retained WAL 大小與 confirmed 位置，對 inactive slot 設告警，並定義「consumer 永久退場時誰負責 drop slot」。slot 數量與保留策略要納入來源端的容量規劃，讓複製能力不會反過來成為來源資料庫的可用性風險。&lt;/p></description><content:encoded><![CDATA[<p>Replication Slot 的核心概念是來源資料庫為每個下游 consumer 保留的進度標記 — 它記錄 consumer 確認到哪個位置，並據此保留尚未被消費的 <a href="/blog/backend/knowledge-cards/write-ahead-log/" data-link-title="Write-Ahead Log" data-link-desc="說明資料庫如何先寫入 log 再合併回主資料，以提供持久性與崩潰復原">Write-Ahead Log</a>。slot 讓 consumer 斷線後仍能從正確位置續傳，代價是 consumer 停擺時 log 會在來源端持續累積。它是 <a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture</a> 與邏輯複製的進度基礎，和 messaging 的 <a href="/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">Offset</a> 相鄰但責任不同。</p>
<h2 id="概念位置">概念位置</h2>
<p>Replication Slot 位在來源資料庫與下游 consumer 之間，是一個有狀態的 production resource。它和 <a href="/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">Offset</a> 都是消費進度，差別在反壓方向：offset 落後不會壓垮 producer，slot 落後會讓來源端為了保留 WAL 而吃光磁碟。PostgreSQL 的 replication slot 是典型例子，<a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">Consumer Lag</a> 是它對應的健康指標。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要監控 slot 的訊號是來源資料庫磁碟用量上升、但寫入量沒有等比增加。常見原因是 Debezium connector 或 replica 離線，slot 仍在保留 WAL。一個 inactive slot 在高寫入服務上可以在數小時內撐爆 primary 磁碟，屬於高優先事故訊號。</p>
<h2 id="設計責任">設計責任</h2>
<p>每個 slot 要有明確 owner、健康 SLO 與 drop condition。設計上要監控每個 slot 的 retained WAL 大小與 confirmed 位置，對 inactive slot 設告警，並定義「consumer 永久退場時誰負責 drop slot」。slot 數量與保留策略要納入來源端的容量規劃，讓複製能力不會反過來成為來源資料庫的可用性風險。</p>
]]></content:encoded></item><item><title>Materialized View</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/materialized-view/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/materialized-view/</guid><description>&lt;p>Materialized view 把查詢結果預先計算並持久儲存，是 &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> 的一種實作方式。它跟一般 view 的差別在於 materialized view 有實體儲存，查詢時讀取的是快照而非即時計算。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Materialized view 是 &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> 的一種實作方式。在關聯式資料庫中它是 SQL-level 的物化查詢；在觀測領域，&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule&lt;/a> 扮演類似角色 — 把聚合計算的結果寫成新的 time series。兩者的共同設計問題是更新頻率、一致性延遲與維護成本。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 materialized view 時要定義刷新策略（定時 / 觸發 / 手動）、資料新鮮度容忍上限、儲存成本與失效重建流程。刷新頻率決定讀取的 freshness — 每分鐘刷新的 materialized view 最多落後一分鐘，對 dashboard 場景通常足夠，對即席事故診斷可能不夠。&lt;/p>
&lt;h2 id="使用情境">使用情境&lt;/h2>
&lt;p>需要 materialized view 的訊號是同一個複雜查詢被多個消費者反覆執行（dashboard panel、定期報表、alert rule），而且每次查詢的計算成本高到影響原始資料源的效能。在觀測場景中，SLO burn rate、跨服務 error ratio、多維度 latency percentile 是常見的 materialization 候選。&lt;/p>
&lt;p>在資料庫的應用見 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/state-ownership-query-boundary/" data-link-title="1.8 State Ownership 與 Query Boundary" data-link-desc="正式狀態 vs 派生狀態的責任分層、CQRS / event sourcing / materialized view、四種 query 邊界">1.8 State Ownership&lt;/a>。在觀測領域的應用見 &lt;a href="https://tarrragon.github.io/blog/backend/04-observability/observability-query-design/" data-link-title="4.23 觀測查詢設計" data-link-desc="把觀測資料的讀取路徑當系統設計問題處理：三種查詢模式、storage tiering、pre-aggregation 與資源治理">4.23 觀測查詢設計&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Materialized view 把查詢結果預先計算並持久儲存，是 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a> 的一種實作方式。它跟一般 view 的差別在於 materialized view 有實體儲存，查詢時讀取的是快照而非即時計算。</p>
<h2 id="概念位置">概念位置</h2>
<p>Materialized view 是 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a> 的一種實作方式。在關聯式資料庫中它是 SQL-level 的物化查詢；在觀測領域，<a href="/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule</a> 扮演類似角色 — 把聚合計算的結果寫成新的 time series。兩者的共同設計問題是更新頻率、一致性延遲與維護成本。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 materialized view 時要定義刷新策略（定時 / 觸發 / 手動）、資料新鮮度容忍上限、儲存成本與失效重建流程。刷新頻率決定讀取的 freshness — 每分鐘刷新的 materialized view 最多落後一分鐘，對 dashboard 場景通常足夠，對即席事故診斷可能不夠。</p>
<h2 id="使用情境">使用情境</h2>
<p>需要 materialized view 的訊號是同一個複雜查詢被多個消費者反覆執行（dashboard panel、定期報表、alert rule），而且每次查詢的計算成本高到影響原始資料源的效能。在觀測場景中，SLO burn rate、跨服務 error ratio、多維度 latency percentile 是常見的 materialization 候選。</p>
<p>在資料庫的應用見 <a href="/blog/backend/01-database/state-ownership-query-boundary/" data-link-title="1.8 State Ownership 與 Query Boundary" data-link-desc="正式狀態 vs 派生狀態的責任分層、CQRS / event sourcing / materialized view、四種 query 邊界">1.8 State Ownership</a>。在觀測領域的應用見 <a href="/blog/backend/04-observability/observability-query-design/" data-link-title="4.23 觀測查詢設計" data-link-desc="把觀測資料的讀取路徑當系統設計問題處理：三種查詢模式、storage tiering、pre-aggregation 與資源治理">4.23 觀測查詢設計</a>。</p>
]]></content:encoded></item><item><title>Transaction Pooling</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/transaction-pooling/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/transaction-pooling/</guid><description>&lt;p>Transaction Pooling 的核心概念是 connection pooler 把後端連線的綁定縮到單一 transaction 期間 — transaction 一結束，後端連線就還回池子給其他 client 用。它把連線壓縮做到最大，代價是 session 狀態無法跨 transaction 保留。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool&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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Transaction Pooling 位在 application 與資料庫之間的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool&lt;/a> 內。相對於 session pooling（連線綁定整個 client session）與 statement pooling（綁定單一語句），transaction pooling 在壓縮率與相容性之間取中間值。選它就要把 search_path、prepared statement、暫存表、advisory lock、SET 等 session 層設定全部改成 transaction-scoped。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合 transaction pooling 的訊號是大量短連線、client 連線數遠超過資料庫能承受的後端連線上限。要特別注意依賴 session 狀態的功能：用 SET 設定的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/row-level-security/" data-link-title="Row-Level Security" data-link-desc="說明資料庫如何用 policy 限制同一張表中哪些 row 對某個角色可見或可寫">Row-Level Security&lt;/a> session 變數若不是 transaction-scoped，會漂到下一個 client 的 transaction，造成跨租戶資料外洩。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要先盤點 application 用到哪些 session 層機制，再決定 pooling 模式。選 transaction pooling 時要把租戶識別、權限變數、時區等設定改用 SET LOCAL 綁在 transaction 內。observability 要看後端連線使用率、client 等待時間，以及和 pooling 模式相關的錯誤。&lt;/p></description><content:encoded><![CDATA[<p>Transaction Pooling 的核心概念是 connection pooler 把後端連線的綁定縮到單一 transaction 期間 — transaction 一結束，後端連線就還回池子給其他 client 用。它把連線壓縮做到最大，代價是 session 狀態無法跨 transaction 保留。它和 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool</a> 是同一條線上的不同精細度，並和 <a href="/blog/backend/knowledge-cards/transaction-boundary/" data-link-title="Transaction Boundary" data-link-desc="說明哪些資料變更應在同一個交易中一起成功或一起回復">Transaction Boundary</a> 直接耦合。</p>
<h2 id="概念位置">概念位置</h2>
<p>Transaction Pooling 位在 application 與資料庫之間的 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool</a> 內。相對於 session pooling（連線綁定整個 client session）與 statement pooling（綁定單一語句），transaction pooling 在壓縮率與相容性之間取中間值。選它就要把 search_path、prepared statement、暫存表、advisory lock、SET 等 session 層設定全部改成 transaction-scoped。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合 transaction pooling 的訊號是大量短連線、client 連線數遠超過資料庫能承受的後端連線上限。要特別注意依賴 session 狀態的功能：用 SET 設定的 <a href="/blog/backend/knowledge-cards/row-level-security/" data-link-title="Row-Level Security" data-link-desc="說明資料庫如何用 policy 限制同一張表中哪些 row 對某個角色可見或可寫">Row-Level Security</a> session 變數若不是 transaction-scoped，會漂到下一個 client 的 transaction，造成跨租戶資料外洩。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要先盤點 application 用到哪些 session 層機制，再決定 pooling 模式。選 transaction pooling 時要把租戶識別、權限變數、時區等設定改用 SET LOCAL 綁在 transaction 內。observability 要看後端連線使用率、client 等待時間，以及和 pooling 模式相關的錯誤。</p>
]]></content:encoded></item><item><title>CQRS</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cqrs/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cqrs/</guid><description>&lt;p>CQRS（Command Query Responsibility Segregation）的核心概念是「把寫入路徑跟讀取路徑拆成各自獨立的模型，各自依自身需求最佳化」。分離後讀取面的具體產物是 &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>。它處理的根本問題是讀寫不對稱 — 同一份資料的寫入形狀跟讀取形狀不同、寫入頻率跟讀取頻率不同、寫入 SLA 跟讀取 SLA 不同。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>CQRS 是一種架構分離策略，位於資料存取模式的設計層。它跟 &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> 的關係是：CQRS 是分離的決策框架，read model 是分離之後「讀取面」的具體產物。&lt;/p>
&lt;p>CQRS 經常跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-sourcing/" data-link-title="Event Sourcing" data-link-desc="說明用 append-only 事件流取代 mutable state 作為正式紀錄的設計模式、需求判準與代價">event sourcing&lt;/a> 一起出現，但兩者是獨立概念。CQRS 只要求讀寫模型分離；&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/event-sourcing/" data-link-title="Event Sourcing" data-link-desc="說明用 append-only 事件流取代 mutable state 作為正式紀錄的設計模式、需求判準與代價">event sourcing&lt;/a> 是把寫入模型改成 append-only 的事件流。可以有 CQRS 但沒有 event sourcing（寫入仍用傳統 CRUD，讀取用獨立的 &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>），也可以有 event sourcing 但沒有 CQRS（讀寫都直接操作 event store）。&lt;/p>
&lt;h2 id="讀寫不對稱的三個維度">讀寫不對稱的三個維度&lt;/h2>
&lt;p>分離的動機來自三種不對稱，當任一種超過單一模型能承受的範圍時，CQRS 開始有設計價值。&lt;/p>
&lt;p>&lt;strong>形狀不對稱&lt;/strong>：寫入時資料以正規化、事務安全的結構進入系統；讀取時不同消費者需要不同的反正規化形狀。一個訂單寫入時是 order + line items + payment 三張表的事務；列表頁需要扁平的 order summary，報表需要跨訂單的聚合，搜尋需要全文索引。強迫同一個模型同時服務這些形狀，會讓寫入模型變得過度複雜或讀取效能退化。&lt;/p>
&lt;p>&lt;strong>頻率不對稱&lt;/strong>：讀取頻率遠高於寫入頻率是常見的服務模型（商品頁的瀏覽量遠大於商品更新頻率）。讀寫共用模型時，高頻讀取的效能需求會推動寫入模型往讀取最佳化靠攏，犧牲寫入的簡潔性跟一致性保證。&lt;/p>
&lt;p>&lt;strong>SLA 不對稱&lt;/strong>：不同讀取消費者的延遲容忍跟一致性需求不同。即時顯示需要毫秒級回應但容忍短暫不一致；報表需要完整一致但容忍分鐘級延遲；稽核需要長期可查但容忍更高延遲。單一模型難以同時滿足多種 SLA。&lt;/p>
&lt;h2 id="分離的設計判準">分離的設計判準&lt;/h2>
&lt;p>讀寫不對稱存在不代表一定需要 CQRS。分離的判準是不對稱的程度是否已經超過「在同一個模型上做最佳化」能解決的範圍。&lt;/p>
&lt;p>&lt;strong>可以不分離的情境&lt;/strong>：讀寫形狀接近（CRUD 應用、管理後台）、讀取消費者單一（只有一種 UI）、流量規模讓讀寫共用模型的效能足夠、團隊規模小到維護兩套模型的成本大於效能收益。&lt;/p>
&lt;p>&lt;strong>需要考慮分離的訊號&lt;/strong>：讀取效能持續退化但寫入側無法再為讀取最佳化（加 index 已到極限、反正規化導致寫入複雜度上升）；多種讀取消費者對同一份資料有互斥的形狀需求；讀寫的擴展需求方向不同（讀取要水平擴展、寫入要強一致性）。&lt;/p>
&lt;h2 id="分離的代價">分離的代價&lt;/h2>
&lt;p>CQRS 的代價集中在同步、一致性與維護三個面向。&lt;/p>
&lt;p>&lt;strong>最終一致性&lt;/strong>：read model 透過事件或同步機制從 write model 更新，中間有延遲。使用者寫入後立即讀取可能看不到自己的變更。這個延遲窗口需要被明確設計（多長、可接受嗎、UI 怎麼處理）而非假裝不存在。&lt;/p>
&lt;p>&lt;strong>同步機制的可靠性&lt;/strong>：write model 到 read model 的同步本身是一個需要監控跟治理的資料路徑。同步失敗、同步延遲、同步漂移都需要被偵測跟處理。&lt;/p>
&lt;p>&lt;strong>多模型維護&lt;/strong>：schema 變更需要同時更新 write model 跟所有 read model。read model 的數量增長後，每次 schema migration 的變更面會擴大。&lt;/p>
&lt;h2 id="跨領域的應用">跨領域的應用&lt;/h2>
&lt;p>讀寫分離的設計張力不限於 application data。觀測資料的讀取路徑設計（&lt;a href="https://tarrragon.github.io/blog/backend/04-observability/observability-query-design/" data-link-title="4.23 觀測查詢設計" data-link-desc="把觀測資料的讀取路徑當系統設計問題處理：三種查詢模式、storage tiering、pre-aggregation 與資源治理">4.23 觀測查詢設計&lt;/a>）面臨同樣的不對稱：寫入是高吞吐的 append-only，讀取被至少三種不同 SLA 的消費者（即席診斷、聚合趨勢、鑑識回溯）拉扯。觀測領域用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/storage-tiering/" data-link-title="Storage Tiering" data-link-desc="說明按資料熱度分層儲存以平衡查詢速度、儲存成本與保留完整性的機制">storage tiering&lt;/a> 來實作讀寫分離，概念上對應 CQRS 的 read model，但術語跟實作層級不同。&lt;/p>
&lt;p>Message queue 的消費端也有類似結構：同一份事件被多個 consumer 以不同速度、不同形狀讀取，fan-out 跟 consumer group 是另一種讀寫分離的實作。&lt;/p></description><content:encoded><![CDATA[<p>CQRS（Command Query Responsibility Segregation）的核心概念是「把寫入路徑跟讀取路徑拆成各自獨立的模型，各自依自身需求最佳化」。分離後讀取面的具體產物是 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a>。它處理的根本問題是讀寫不對稱 — 同一份資料的寫入形狀跟讀取形狀不同、寫入頻率跟讀取頻率不同、寫入 SLA 跟讀取 SLA 不同。</p>
<h2 id="概念位置">概念位置</h2>
<p>CQRS 是一種架構分離策略，位於資料存取模式的設計層。它跟 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a> 的關係是：CQRS 是分離的決策框架，read model 是分離之後「讀取面」的具體產物。</p>
<p>CQRS 經常跟 <a href="/blog/backend/knowledge-cards/event-sourcing/" data-link-title="Event Sourcing" data-link-desc="說明用 append-only 事件流取代 mutable state 作為正式紀錄的設計模式、需求判準與代價">event sourcing</a> 一起出現，但兩者是獨立概念。CQRS 只要求讀寫模型分離；<a href="/blog/backend/knowledge-cards/event-sourcing/" data-link-title="Event Sourcing" data-link-desc="說明用 append-only 事件流取代 mutable state 作為正式紀錄的設計模式、需求判準與代價">event sourcing</a> 是把寫入模型改成 append-only 的事件流。可以有 CQRS 但沒有 event sourcing（寫入仍用傳統 CRUD，讀取用獨立的 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a>），也可以有 event sourcing 但沒有 CQRS（讀寫都直接操作 event store）。</p>
<h2 id="讀寫不對稱的三個維度">讀寫不對稱的三個維度</h2>
<p>分離的動機來自三種不對稱，當任一種超過單一模型能承受的範圍時，CQRS 開始有設計價值。</p>
<p><strong>形狀不對稱</strong>：寫入時資料以正規化、事務安全的結構進入系統；讀取時不同消費者需要不同的反正規化形狀。一個訂單寫入時是 order + line items + payment 三張表的事務；列表頁需要扁平的 order summary，報表需要跨訂單的聚合，搜尋需要全文索引。強迫同一個模型同時服務這些形狀，會讓寫入模型變得過度複雜或讀取效能退化。</p>
<p><strong>頻率不對稱</strong>：讀取頻率遠高於寫入頻率是常見的服務模型（商品頁的瀏覽量遠大於商品更新頻率）。讀寫共用模型時，高頻讀取的效能需求會推動寫入模型往讀取最佳化靠攏，犧牲寫入的簡潔性跟一致性保證。</p>
<p><strong>SLA 不對稱</strong>：不同讀取消費者的延遲容忍跟一致性需求不同。即時顯示需要毫秒級回應但容忍短暫不一致；報表需要完整一致但容忍分鐘級延遲；稽核需要長期可查但容忍更高延遲。單一模型難以同時滿足多種 SLA。</p>
<h2 id="分離的設計判準">分離的設計判準</h2>
<p>讀寫不對稱存在不代表一定需要 CQRS。分離的判準是不對稱的程度是否已經超過「在同一個模型上做最佳化」能解決的範圍。</p>
<p><strong>可以不分離的情境</strong>：讀寫形狀接近（CRUD 應用、管理後台）、讀取消費者單一（只有一種 UI）、流量規模讓讀寫共用模型的效能足夠、團隊規模小到維護兩套模型的成本大於效能收益。</p>
<p><strong>需要考慮分離的訊號</strong>：讀取效能持續退化但寫入側無法再為讀取最佳化（加 index 已到極限、反正規化導致寫入複雜度上升）；多種讀取消費者對同一份資料有互斥的形狀需求；讀寫的擴展需求方向不同（讀取要水平擴展、寫入要強一致性）。</p>
<h2 id="分離的代價">分離的代價</h2>
<p>CQRS 的代價集中在同步、一致性與維護三個面向。</p>
<p><strong>最終一致性</strong>：read model 透過事件或同步機制從 write model 更新，中間有延遲。使用者寫入後立即讀取可能看不到自己的變更。這個延遲窗口需要被明確設計（多長、可接受嗎、UI 怎麼處理）而非假裝不存在。</p>
<p><strong>同步機制的可靠性</strong>：write model 到 read model 的同步本身是一個需要監控跟治理的資料路徑。同步失敗、同步延遲、同步漂移都需要被偵測跟處理。</p>
<p><strong>多模型維護</strong>：schema 變更需要同時更新 write model 跟所有 read model。read model 的數量增長後，每次 schema migration 的變更面會擴大。</p>
<h2 id="跨領域的應用">跨領域的應用</h2>
<p>讀寫分離的設計張力不限於 application data。觀測資料的讀取路徑設計（<a href="/blog/backend/04-observability/observability-query-design/" data-link-title="4.23 觀測查詢設計" data-link-desc="把觀測資料的讀取路徑當系統設計問題處理：三種查詢模式、storage tiering、pre-aggregation 與資源治理">4.23 觀測查詢設計</a>）面臨同樣的不對稱：寫入是高吞吐的 append-only，讀取被至少三種不同 SLA 的消費者（即席診斷、聚合趨勢、鑑識回溯）拉扯。觀測領域用 <a href="/blog/backend/knowledge-cards/recording-rule/" data-link-title="Recording Rule" data-link-desc="說明把 query-time 聚合計算推到寫入時的 pre-aggregation 機制">recording rule</a>、<a href="/blog/backend/knowledge-cards/rollup/" data-link-title="Rollup / Downsampling" data-link-desc="說明時間序列資料隨時間降低精度以控制儲存成本與查詢效能的機制">rollup</a>、<a href="/blog/backend/knowledge-cards/storage-tiering/" data-link-title="Storage Tiering" data-link-desc="說明按資料熱度分層儲存以平衡查詢速度、儲存成本與保留完整性的機制">storage tiering</a> 來實作讀寫分離，概念上對應 CQRS 的 read model，但術語跟實作層級不同。</p>
<p>Message queue 的消費端也有類似結構：同一份事件被多個 consumer 以不同速度、不同形狀讀取，fan-out 跟 consumer group 是另一種讀寫分離的實作。</p>
]]></content:encoded></item><item><title>Single Writer Model</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/single-writer-model/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/single-writer-model/</guid><description>&lt;p>Single Writer Model 的核心概念是同一個邏輯資料庫在任一時間只允許一條 writer path，所有寫入被序列化。它讓寫入路徑簡單、省去分散式寫入協調，代價是寫入吞吐有明確上限。它是 SQLite WAL mode 與許多 leader-based 系統的並發模型，和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/write-ahead-log/" data-link-title="Write-Ahead Log" data-link-desc="說明資料庫如何先寫入 log 再合併回主資料，以提供持久性與崩潰復原">Write-Ahead Log&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/embedded-database/" data-link-title="Embedded Database" data-link-desc="說明嵌入式資料庫如何隨 application process 運作，並把檔案生命週期責任交回應用">Embedded Database&lt;/a> 一起決定寫入行為。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Single Writer Model 位在並發模型的一端 — 寫入併發度上限為一。它和「多 reader 並行」可以共存：SQLite WAL mode 允許多個 reader 與一個 writer 同時運作。要擴展寫入時，靠的是改變架構（例如分區、分庫或換成 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">Distributed SQL&lt;/a>），增加 writer 在此模型下行不通。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>single writer 仍夠用的訊號是寫入可以用一個 writer 排隊完成、busy 或 lock timeout 偶發且短。需要重新設計的訊號是寫入長期排隊、busy timeout 從偶發變成常態。常見誤判是把 busy timeout 調大當成擴容 — 那只是讓請求等更久；也常見多個 instance 同時寫同一個檔案，破壞 single writer 假設。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要明確指認「誰是 writer」並確保系統真的只有一個。LiteFS 類方案用 primary lease 把 writer 角色集中；應用層要把寫入路徑收斂到單一節點或單一序列化點。容量規劃要把單 writer 吞吐當作硬上限，超過時改走分區或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">Distributed SQL&lt;/a>，而不是疊加 writer。&lt;/p></description><content:encoded><![CDATA[<p>Single Writer Model 的核心概念是同一個邏輯資料庫在任一時間只允許一條 writer path，所有寫入被序列化。它讓寫入路徑簡單、省去分散式寫入協調，代價是寫入吞吐有明確上限。它是 SQLite WAL mode 與許多 leader-based 系統的並發模型，和 <a href="/blog/backend/knowledge-cards/write-ahead-log/" data-link-title="Write-Ahead Log" data-link-desc="說明資料庫如何先寫入 log 再合併回主資料，以提供持久性與崩潰復原">Write-Ahead Log</a>、<a href="/blog/backend/knowledge-cards/embedded-database/" data-link-title="Embedded Database" data-link-desc="說明嵌入式資料庫如何隨 application process 運作，並把檔案生命週期責任交回應用">Embedded Database</a> 一起決定寫入行為。</p>
<h2 id="概念位置">概念位置</h2>
<p>Single Writer Model 位在並發模型的一端 — 寫入併發度上限為一。它和「多 reader 並行」可以共存：SQLite WAL mode 允許多個 reader 與一個 writer 同時運作。要擴展寫入時，靠的是改變架構（例如分區、分庫或換成 <a href="/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">Distributed SQL</a>），增加 writer 在此模型下行不通。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>single writer 仍夠用的訊號是寫入可以用一個 writer 排隊完成、busy 或 lock timeout 偶發且短。需要重新設計的訊號是寫入長期排隊、busy timeout 從偶發變成常態。常見誤判是把 busy timeout 調大當成擴容 — 那只是讓請求等更久；也常見多個 instance 同時寫同一個檔案，破壞 single writer 假設。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要明確指認「誰是 writer」並確保系統真的只有一個。LiteFS 類方案用 primary lease 把 writer 角色集中；應用層要把寫入路徑收斂到單一節點或單一序列化點。容量規劃要把單 writer 吞吐當作硬上限，超過時改走分區或 <a href="/blog/backend/knowledge-cards/distributed-sql/" data-link-title="Distributed SQL" data-link-desc="把 SQL 與交易語意延伸到多節點與多區域的資料庫形態">Distributed SQL</a>，而不是疊加 writer。</p>
]]></content:encoded></item><item><title>Event Sourcing</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/event-sourcing/</link><pubDate>Mon, 22 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/event-sourcing/</guid><description>&lt;p>Event sourcing 的核心概念是「不存 current state、存產生 current state 的所有事件」。儲存層是 &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/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">projection&lt;/a> 推算 current state。每一次狀態變更被記錄為一筆不可變的事件（event），current state 透過重播（replay）事件序列推算出來。正式紀錄是事件流本身，current state 是派生物。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Event sourcing 是一種資料持久化策略，改變的是「狀態怎麼被記錄」而非「狀態怎麼被讀取」。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cqrs/" data-link-title="CQRS" data-link-desc="說明讀寫不對稱時為何需要分離查詢與寫入責任、分離的判準與代價">CQRS&lt;/a> 經常搭配但概念獨立 — event sourcing 處理寫入模型（append-only event log 取代 mutable row），CQRS 處理讀寫分離。可以有 event sourcing 但沒有 CQRS（讀寫都直接操作 event store），也可以有 CQRS 但沒有 event sourcing（寫入仍用 CRUD）。&lt;/p>
&lt;p>Event sourcing 的儲存層是 &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/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">projection&lt;/a> 把事件流轉換成查詢用的 &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;/p>
&lt;h2 id="設計判準">設計判準&lt;/h2>
&lt;p>Event sourcing 的設計價值來自「需要完整變更歷史」的業務需求。判準是：業務是否需要回答「某個時間點的狀態是什麼」或「狀態怎麼從 A 變成 B」。&lt;/p>
&lt;p>&lt;strong>適合的場景&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>金融帳務 — 餘額的每一筆增減都是 audit 事件，法規要求能追溯任意時點的 balance&lt;/li>
&lt;li>訂單流程 — 每個狀態轉換（建立→付款→出貨→完成）是 business event，需要重建任意階段&lt;/li>
&lt;li>法規合規 — 完整變更歷史是合規證據，刪除或覆寫正式紀錄違反要求&lt;/li>
&lt;li>需要 replay 能力 — downstream consumer 落後或資料損壞時，能從 event log 重建&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>不適合的場景&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>簡單 CRUD — 狀態覆寫即可、不需要歷史、event sourcing 的 overhead 遠大於收益&lt;/li>
&lt;li>需要直接查 current state 的高頻場景 — 每次讀取都 replay 整條事件流延遲太高，必須搭配 projection 維護 snapshot，增加系統複雜度&lt;/li>
&lt;li>事件 schema 變更頻繁 — 舊事件需要被新版 schema 正確 replay，schema evolution 成本高&lt;/li>
&lt;/ul>
&lt;h2 id="代價">代價&lt;/h2>
&lt;p>&lt;strong>讀取複雜度&lt;/strong>：current state 不再是一筆 row，而是需要 replay 或 projection 推算。讀取路徑的設計從「查一筆 record」變成「維護多個 &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> + 保證 projection 正確性 + 處理 projection lag」。&lt;/p>
&lt;p>&lt;strong>事件 schema evolution&lt;/strong>：事件一旦寫入就不可變，但業務需求會改變事件結構。版本化 event schema（upcasting）是長期維護的核心挑戰 — 新版 projection 要能正確消費舊版事件。&lt;/p>
&lt;p>&lt;strong>儲存成長&lt;/strong>：事件永不刪除（或只做 retention），儲存量隨時間持續成長。高頻寫入的系統可能需要 snapshot 機制（定期存一份 current state 快照，replay 從 snapshot 開始而非從頭）來控制 replay 時間。&lt;/p>
&lt;p>&lt;strong>除錯難度&lt;/strong>：bug 可能是某個 event handler 在 replay 時產生錯誤結果。除錯需要重現特定事件序列的 replay，比查一筆 mutable record 的 diff 更複雜。&lt;/p>
&lt;h2 id="跟其他概念的關係">跟其他概念的關係&lt;/h2>
&lt;ul>
&lt;li>&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> — event sourcing 的儲存層，append-only 的事件序列&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">Projection&lt;/a> — 把 event log 轉換成可查詢的 read model 的機制&lt;/li>
&lt;li>&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> — projection 的輸出，為特定查詢需求最佳化的資料形狀&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cqrs/" data-link-title="CQRS" data-link-desc="說明讀寫不對稱時為何需要分離查詢與寫入責任、分離的判準與代價">CQRS&lt;/a> — 讀寫分離的設計框架，event sourcing 是其中一種 write model 實作&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/saga/" data-link-title="Saga" data-link-desc="處理跨服務分散事務的補償型 transaction 序列、用最終一致換 ACID atomic">Saga&lt;/a> — 跨服務的分散事務，event sourcing 提供每個 step 的事件紀錄&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Event sourcing 的核心概念是「不存 current state、存產生 current state 的所有事件」。儲存層是 <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/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">projection</a> 推算 current state。每一次狀態變更被記錄為一筆不可變的事件（event），current state 透過重播（replay）事件序列推算出來。正式紀錄是事件流本身，current state 是派生物。</p>
<h2 id="概念位置">概念位置</h2>
<p>Event sourcing 是一種資料持久化策略，改變的是「狀態怎麼被記錄」而非「狀態怎麼被讀取」。它跟 <a href="/blog/backend/knowledge-cards/cqrs/" data-link-title="CQRS" data-link-desc="說明讀寫不對稱時為何需要分離查詢與寫入責任、分離的判準與代價">CQRS</a> 經常搭配但概念獨立 — event sourcing 處理寫入模型（append-only event log 取代 mutable row），CQRS 處理讀寫分離。可以有 event sourcing 但沒有 CQRS（讀寫都直接操作 event store），也可以有 CQRS 但沒有 event sourcing（寫入仍用 CRUD）。</p>
<p>Event sourcing 的儲存層是 <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/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">projection</a> 把事件流轉換成查詢用的 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a>。</p>
<h2 id="設計判準">設計判準</h2>
<p>Event sourcing 的設計價值來自「需要完整變更歷史」的業務需求。判準是：業務是否需要回答「某個時間點的狀態是什麼」或「狀態怎麼從 A 變成 B」。</p>
<p><strong>適合的場景</strong>：</p>
<ul>
<li>金融帳務 — 餘額的每一筆增減都是 audit 事件，法規要求能追溯任意時點的 balance</li>
<li>訂單流程 — 每個狀態轉換（建立→付款→出貨→完成）是 business event，需要重建任意階段</li>
<li>法規合規 — 完整變更歷史是合規證據，刪除或覆寫正式紀錄違反要求</li>
<li>需要 replay 能力 — downstream consumer 落後或資料損壞時，能從 event log 重建</li>
</ul>
<p><strong>不適合的場景</strong>：</p>
<ul>
<li>簡單 CRUD — 狀態覆寫即可、不需要歷史、event sourcing 的 overhead 遠大於收益</li>
<li>需要直接查 current state 的高頻場景 — 每次讀取都 replay 整條事件流延遲太高，必須搭配 projection 維護 snapshot，增加系統複雜度</li>
<li>事件 schema 變更頻繁 — 舊事件需要被新版 schema 正確 replay，schema evolution 成本高</li>
</ul>
<h2 id="代價">代價</h2>
<p><strong>讀取複雜度</strong>：current state 不再是一筆 row，而是需要 replay 或 projection 推算。讀取路徑的設計從「查一筆 record」變成「維護多個 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">read model</a> + 保證 projection 正確性 + 處理 projection lag」。</p>
<p><strong>事件 schema evolution</strong>：事件一旦寫入就不可變，但業務需求會改變事件結構。版本化 event schema（upcasting）是長期維護的核心挑戰 — 新版 projection 要能正確消費舊版事件。</p>
<p><strong>儲存成長</strong>：事件永不刪除（或只做 retention），儲存量隨時間持續成長。高頻寫入的系統可能需要 snapshot 機制（定期存一份 current state 快照，replay 從 snapshot 開始而非從頭）來控制 replay 時間。</p>
<p><strong>除錯難度</strong>：bug 可能是某個 event handler 在 replay 時產生錯誤結果。除錯需要重現特定事件序列的 replay，比查一筆 mutable record 的 diff 更複雜。</p>
<h2 id="跟其他概念的關係">跟其他概念的關係</h2>
<ul>
<li><a href="/blog/backend/knowledge-cards/event-log/" data-link-title="Event Log" data-link-desc="說明事件歷史如何保存、重播與支援跨服務資料重建">Event log</a> — event sourcing 的儲存層，append-only 的事件序列</li>
<li><a href="/blog/backend/knowledge-cards/projection/" data-link-title="Projection" data-link-desc="說明從事件流或資料變更推算出查詢用讀取視圖的轉換機制">Projection</a> — 把 event log 轉換成可查詢的 read model 的機制</li>
<li><a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">Read model</a> — projection 的輸出，為特定查詢需求最佳化的資料形狀</li>
<li><a href="/blog/backend/knowledge-cards/cqrs/" data-link-title="CQRS" data-link-desc="說明讀寫不對稱時為何需要分離查詢與寫入責任、分離的判準與代價">CQRS</a> — 讀寫分離的設計框架，event sourcing 是其中一種 write model 實作</li>
<li><a href="/blog/backend/knowledge-cards/saga/" data-link-title="Saga" data-link-desc="處理跨服務分散事務的補償型 transaction 序列、用最終一致換 ACID atomic">Saga</a> — 跨服務的分散事務，event sourcing 提供每個 step 的事件紀錄</li>
</ul>
]]></content:encoded></item><item><title>Embedded Database</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/embedded-database/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/embedded-database/</guid><description>&lt;p>Embedded Database 的核心概念是資料庫以 library 形式嵌入 application process，與應用共用同一個 process。它讓部署簡單、讀寫沒有網路往返，代價是 backup、locking、durability 與 corruption recovery 的責任從 DBA 回到 application process 與檔案系統。SQLite 是典型例子，它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/single-writer-model/" data-link-title="Single Writer Model" data-link-desc="說明單寫者模型如何序列化寫入，並成為系統的容量邊界">Single Writer Model&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/local-first/" data-link-title="Local-First" data-link-desc="說明本機優先的資料架構如何讓離線可用，並把同步當成獨立問題">Local-First&lt;/a> 一起定義這類系統的邊界。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Embedded Database 位在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database&lt;/a> 這個傘狀概念下、與 server-side database 相對的一端。server-side database 有獨立 process、連線協定與營運團隊；embedded database 的 production boundary 在裝置與檔案生命週期 — 資料庫的可用性等同那個檔案與那個 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/single-writer-model/" data-link-title="Single Writer Model" data-link-desc="說明單寫者模型如何序列化寫入，並成為系統的容量邊界">Single Writer Model&lt;/a> process 的可用性。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合 embedded database 的訊號是單一 process 內的本地狀態、測試 fixture、桌面或行動 app 的本地儲存，或邊緣節點上讀多寫少的資料。需要重新評估的訊號是多個 process 或多台機器要同時寫同一份資料 — 那已超出 embedded database 加 single writer 的設計範圍。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要明確指認檔案的 owner、backup 方式、崩潰後的復原流程與並發寫入的邊界。backup 要在一致的時點取，避免複製到寫入中途的檔案；corruption 要先保全原檔再修復。要跨裝置或跨節點共享資料時，要把同步當成獨立問題，接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/local-first/" data-link-title="Local-First" data-link-desc="說明本機優先的資料架構如何讓離線可用，並把同步當成獨立問題">Local-First&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/conflict-resolution/" data-link-title="Conflict Resolution" data-link-desc="說明並發或離線寫入產生衝突時，如何偵測、呈現與合併成可接受狀態">Conflict Resolution&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Embedded Database 的核心概念是資料庫以 library 形式嵌入 application process，與應用共用同一個 process。它讓部署簡單、讀寫沒有網路往返，代價是 backup、locking、durability 與 corruption recovery 的責任從 DBA 回到 application process 與檔案系統。SQLite 是典型例子，它和 <a href="/blog/backend/knowledge-cards/single-writer-model/" data-link-title="Single Writer Model" data-link-desc="說明單寫者模型如何序列化寫入，並成為系統的容量邊界">Single Writer Model</a>、<a href="/blog/backend/knowledge-cards/local-first/" data-link-title="Local-First" data-link-desc="說明本機優先的資料架構如何讓離線可用，並把同步當成獨立問題">Local-First</a> 一起定義這類系統的邊界。</p>
<h2 id="概念位置">概念位置</h2>
<p>Embedded Database 位在 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database</a> 這個傘狀概念下、與 server-side database 相對的一端。server-side database 有獨立 process、連線協定與營運團隊；embedded database 的 production boundary 在裝置與檔案生命週期 — 資料庫的可用性等同那個檔案與那個 <a href="/blog/backend/knowledge-cards/single-writer-model/" data-link-title="Single Writer Model" data-link-desc="說明單寫者模型如何序列化寫入，並成為系統的容量邊界">Single Writer Model</a> process 的可用性。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合 embedded database 的訊號是單一 process 內的本地狀態、測試 fixture、桌面或行動 app 的本地儲存，或邊緣節點上讀多寫少的資料。需要重新評估的訊號是多個 process 或多台機器要同時寫同一份資料 — 那已超出 embedded database 加 single writer 的設計範圍。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要明確指認檔案的 owner、backup 方式、崩潰後的復原流程與並發寫入的邊界。backup 要在一致的時點取，避免複製到寫入中途的檔案；corruption 要先保全原檔再修復。要跨裝置或跨節點共享資料時，要把同步當成獨立問題，接回 <a href="/blog/backend/knowledge-cards/local-first/" data-link-title="Local-First" data-link-desc="說明本機優先的資料架構如何讓離線可用，並把同步當成獨立問題">Local-First</a> 與 <a href="/blog/backend/knowledge-cards/conflict-resolution/" data-link-title="Conflict Resolution" data-link-desc="說明並發或離線寫入產生衝突時，如何偵測、呈現與合併成可接受狀態">Conflict Resolution</a>。</p>
]]></content:encoded></item><item><title>Conflict Resolution</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/conflict-resolution/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/conflict-resolution/</guid><description>&lt;p>Conflict Resolution 的核心概念是當兩筆都合法的寫入落在同一份資料上時，用一個明確策略把它們合併成可接受的最終狀態。它讓多裝置同步、離線編輯與多區寫入有確定的結果，代價是要先選定策略並承擔它的取捨。它和事後比對修復的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation&lt;/a> 是不同時機 — conflict resolution 是寫入或合併當下的策略，是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/local-first/" data-link-title="Local-First" data-link-desc="說明本機優先的資料架構如何讓離線可用，並把同步當成獨立問題">Local-First&lt;/a> 系統的核心決策。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Conflict Resolution 位在多寫入來源收斂成一致狀態的關鍵環節。常見策略有 last-write-wins、欄位層合併、CRDT，以及交給人工或伺服器裁決；每種策略對「哪一筆寫入會被保留」給出不同答案。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">Eventual Consistency&lt;/a> 相鄰：最終一致描述系統會收斂，conflict resolution 描述它收斂到什麼結果。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要明確 conflict resolution 的訊號是同一份資料會被多個裝置或多個區域並發修改。last-write-wins 實作簡單，但會在兩個使用者同時編輯時靜默覆蓋其中一份 — 對筆記、購物車、協作文件這類場景等於資料遺失。欄位層合併能保留兩邊改的不同欄位，CRDT 能讓特定資料型別自動收斂。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要先依資料型別與業務後果選策略，再決定衝突要不要讓使用者看見。刪除要當成可傳播的事件處理（tombstone），讓離線裝置上的刪除能正確同步出去。observability 要能看到衝突發生率與被覆蓋的寫入量，讓 last-write-wins 的代價是可量測的，而不是隱形的。&lt;/p></description><content:encoded><![CDATA[<p>Conflict Resolution 的核心概念是當兩筆都合法的寫入落在同一份資料上時，用一個明確策略把它們合併成可接受的最終狀態。它讓多裝置同步、離線編輯與多區寫入有確定的結果，代價是要先選定策略並承擔它的取捨。它和事後比對修復的 <a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">Data Reconciliation</a> 是不同時機 — conflict resolution 是寫入或合併當下的策略，是 <a href="/blog/backend/knowledge-cards/local-first/" data-link-title="Local-First" data-link-desc="說明本機優先的資料架構如何讓離線可用，並把同步當成獨立問題">Local-First</a> 系統的核心決策。</p>
<h2 id="概念位置">概念位置</h2>
<p>Conflict Resolution 位在多寫入來源收斂成一致狀態的關鍵環節。常見策略有 last-write-wins、欄位層合併、CRDT，以及交給人工或伺服器裁決；每種策略對「哪一筆寫入會被保留」給出不同答案。它和 <a href="/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">Eventual Consistency</a> 相鄰：最終一致描述系統會收斂，conflict resolution 描述它收斂到什麼結果。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要明確 conflict resolution 的訊號是同一份資料會被多個裝置或多個區域並發修改。last-write-wins 實作簡單，但會在兩個使用者同時編輯時靜默覆蓋其中一份 — 對筆記、購物車、協作文件這類場景等於資料遺失。欄位層合併能保留兩邊改的不同欄位，CRDT 能讓特定資料型別自動收斂。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要先依資料型別與業務後果選策略，再決定衝突要不要讓使用者看見。刪除要當成可傳播的事件處理（tombstone），讓離線裝置上的刪除能正確同步出去。observability 要能看到衝突發生率與被覆蓋的寫入量，讓 last-write-wins 的代價是可量測的，而不是隱形的。</p>
]]></content:encoded></item><item><title>Row-Level Security</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/row-level-security/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/row-level-security/</guid><description>&lt;p>Row-Level Security（RLS）的核心概念是在資料庫層、用 policy 規則限制同一張表裡哪些 row 對某個角色可讀或可寫。它讓資料隔離多一道資料庫強制的防線，而不只依賴 application 的查詢條件。它是 &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;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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Row-Level Security 位在 application 授權的下游。application 層的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization&lt;/a> 決定「誰能呼叫這個功能」，RLS 決定「即使查詢送到資料庫，引擎也只回傳這個角色該看到的 row」。它和 &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> 的差別在執行者：tenant boundary 是跨層的隔離概念，RLS 指明由資料庫引擎在 query 執行時強制過濾。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合 RLS 的訊號是多租戶 SaaS、需要資料庫層兜底防止跨租戶外洩，或合規要求資料存取有獨立 enforcement。RLS 通常依賴 application 在交易內設一個 session 變數（例如 tenant_id）來判斷；這個變數的生命週期要和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/transaction-pooling/" data-link-title="Transaction Pooling" data-link-desc="說明 connection pooler 的 transaction 綁定模式如何壓縮連線並改變 session 語意">Transaction Pooling&lt;/a> 的綁定模式對齊，否則會漂到別的請求。table owner 與 superuser 預設會繞過 RLS，這點要納入設計。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要讓 policy 覆蓋 SELECT、INSERT、UPDATE、DELETE 四種操作，並為緊急例外存取留 &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>。RLS 要有獨立測試，證明跨租戶查詢確實被擋下。它是兜底防線，application 層授權仍要做 — 兩道防線各自承擔不同的失敗模式。&lt;/p></description><content:encoded><![CDATA[<p>Row-Level Security（RLS）的核心概念是在資料庫層、用 policy 規則限制同一張表裡哪些 row 對某個角色可讀或可寫。它讓資料隔離多一道資料庫強制的防線，而不只依賴 application 的查詢條件。它是 <a href="/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">Tenant Boundary</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> 一起構成防禦縱深。</p>
<h2 id="概念位置">概念位置</h2>
<p>Row-Level Security 位在 application 授權的下游。application 層的 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a> 決定「誰能呼叫這個功能」，RLS 決定「即使查詢送到資料庫，引擎也只回傳這個角色該看到的 row」。它和 <a href="/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">Tenant Boundary</a> 的差別在執行者：tenant boundary 是跨層的隔離概念，RLS 指明由資料庫引擎在 query 執行時強制過濾。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合 RLS 的訊號是多租戶 SaaS、需要資料庫層兜底防止跨租戶外洩，或合規要求資料存取有獨立 enforcement。RLS 通常依賴 application 在交易內設一個 session 變數（例如 tenant_id）來判斷；這個變數的生命週期要和 <a href="/blog/backend/knowledge-cards/transaction-pooling/" data-link-title="Transaction Pooling" data-link-desc="說明 connection pooler 的 transaction 綁定模式如何壓縮連線並改變 session 語意">Transaction Pooling</a> 的綁定模式對齊，否則會漂到別的請求。table owner 與 superuser 預設會繞過 RLS，這點要納入設計。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要讓 policy 覆蓋 SELECT、INSERT、UPDATE、DELETE 四種操作，並為緊急例外存取留 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a>。RLS 要有獨立測試，證明跨租戶查詢確實被擋下。它是兜底防線，application 層授權仍要做 — 兩道防線各自承擔不同的失敗模式。</p>
]]></content:encoded></item><item><title>At-Rest Encryption</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/at-rest-encryption/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/at-rest-encryption/</guid><description>&lt;p>At-Rest Encryption 的核心概念是資料寫入磁碟前先加密，保護 tablespace、log、backup 等落地資料。它對應的威脅是儲存媒介遺失或被竊 — 磁碟、快照或 backup 檔落到他人手上時，加密讓資料仍受保護。它和保護傳輸中資料的 &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/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>At-Rest Encryption 位在儲存層，與傳輸層的 &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> 形成對稱的一組保護。in-transit 加密保護資料在網路上移動的階段，at-rest 加密保護資料靜止在儲存媒介的階段；一條完整的保護鏈兩者都要有。它和 &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> 連動 — 資料分級決定哪些資料必須做 at-rest 加密。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 at-rest encryption 的訊號是儲存 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/pii/" data-link-title="PII" data-link-desc="說明可識別個人的資料如何影響權限、遮罩、保留與稽核">PII&lt;/a>、金流或受監管資料，或合規要求磁碟與 backup 加密。常見的保護鏈破洞是主資料庫加了密，但 backup 以明文落到 object storage — 攻擊者取得 backup 就繞過了所有加密。設計時要把 backup、replica 與暫存檔都納入加密範圍。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要決定加密範圍、金鑰管理方式與金鑰輪替策略。加密後資料能否還原取決於金鑰是否健在，因此 restore 演練要連金鑰一起測。金鑰要有 owner 與輪替排程，並和存取用的 credential 分開管理 — 兩者失敗代價不同：金鑰遺失等於資料無法還原，credential 外洩等於存取邊界失效。observability 要能確認加密設定狀態與金鑰可用性。&lt;/p></description><content:encoded><![CDATA[<p>At-Rest Encryption 的核心概念是資料寫入磁碟前先加密，保護 tablespace、log、backup 等落地資料。它對應的威脅是儲存媒介遺失或被竊 — 磁碟、快照或 backup 檔落到他人手上時，加密讓資料仍受保護。它和保護傳輸中資料的 <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/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>At-Rest Encryption 位在儲存層，與傳輸層的 <a href="/blog/backend/knowledge-cards/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS</a> 形成對稱的一組保護。in-transit 加密保護資料在網路上移動的階段，at-rest 加密保護資料靜止在儲存媒介的階段；一條完整的保護鏈兩者都要有。它和 <a href="/blog/backend/knowledge-cards/data-classification/" data-link-title="Data Classification" data-link-desc="說明資料分級如何決定保護、存取、保留與匯出規則">Data Classification</a> 連動 — 資料分級決定哪些資料必須做 at-rest 加密。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 at-rest encryption 的訊號是儲存 <a href="/blog/backend/knowledge-cards/pii/" data-link-title="PII" data-link-desc="說明可識別個人的資料如何影響權限、遮罩、保留與稽核">PII</a>、金流或受監管資料，或合規要求磁碟與 backup 加密。常見的保護鏈破洞是主資料庫加了密，但 backup 以明文落到 object storage — 攻擊者取得 backup 就繞過了所有加密。設計時要把 backup、replica 與暫存檔都納入加密範圍。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要決定加密範圍、金鑰管理方式與金鑰輪替策略。加密後資料能否還原取決於金鑰是否健在，因此 restore 演練要連金鑰一起測。金鑰要有 owner 與輪替排程，並和存取用的 credential 分開管理 — 兩者失敗代價不同：金鑰遺失等於資料無法還原，credential 外洩等於存取邊界失效。observability 要能確認加密設定狀態與金鑰可用性。</p>
]]></content:encoded></item><item><title>Table Partitioning</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/table-partitioning/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/table-partitioning/</guid><description>&lt;p>Table Partitioning 的核心概念是在單一資料庫內，把一張大表按 range、list 或 hash 拆成 parent 表加多個 child 分區，讓查詢規劃器只掃描相關分區。它讓大表的查詢、維護與資料清理可以按分區進行，代價是分區鍵要選得讓多數查詢都帶得到。它和跨節點的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding&lt;/a> 不同層 — table partitioning 仍在同一個資料庫內，&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition&lt;/a> 是它失衡時的訊號。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Table Partitioning 位在單機資料庫的表結構層。它和 messaging 的 &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/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition&lt;/a> 切的是事件流、處理並行與順序；table partitioning 切的是一張資料庫表、處理查詢範圍與資料生命週期。要跨節點水平擴展時，才接到 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合 table partitioning 的訊號是一張表很大、但查詢通常只碰最近一段時間或某個範圍，例如時序事件表、訂單表。time-based 分區讓「清掉 90 天前資料」變成卸載一個分區，而不是大範圍 DELETE。要特別注意的訊號是查詢沒帶分區鍵 — 規劃器無法做 partition pruning，查詢會退化成掃描全部分區。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要讓分區鍵和最常見的查詢條件對齊，並規劃分區的建立與卸載流程。time-based 分區要有自動建立未來分區、自動卸載過期分區的機制，並接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">Retention&lt;/a>。observability 要看查詢是否命中 pruning，以及 default 分區是否意外累積資料。&lt;/p></description><content:encoded><![CDATA[<p>Table Partitioning 的核心概念是在單一資料庫內，把一張大表按 range、list 或 hash 拆成 parent 表加多個 child 分區，讓查詢規劃器只掃描相關分區。它讓大表的查詢、維護與資料清理可以按分區進行，代價是分區鍵要選得讓多數查詢都帶得到。它和跨節點的 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a> 不同層 — table partitioning 仍在同一個資料庫內，<a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition</a> 是它失衡時的訊號。</p>
<h2 id="概念位置">概念位置</h2>
<p>Table Partitioning 位在單機資料庫的表結構層。它和 messaging 的 <a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition</a> 名稱相近但語意不同：<a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition</a> 切的是事件流、處理並行與順序；table partitioning 切的是一張資料庫表、處理查詢範圍與資料生命週期。要跨節點水平擴展時，才接到 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合 table partitioning 的訊號是一張表很大、但查詢通常只碰最近一段時間或某個範圍，例如時序事件表、訂單表。time-based 分區讓「清掉 90 天前資料」變成卸載一個分區，而不是大範圍 DELETE。要特別注意的訊號是查詢沒帶分區鍵 — 規劃器無法做 partition pruning，查詢會退化成掃描全部分區。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要讓分區鍵和最常見的查詢條件對齊，並規劃分區的建立與卸載流程。time-based 分區要有自動建立未來分區、自動卸載過期分區的機制，並接回 <a href="/blog/backend/knowledge-cards/retention/" data-link-title="Retention" data-link-desc="說明資料或事件保留多久，以及保留期限如何影響重放與成本">Retention</a>。observability 要看查詢是否命中 pruning，以及 default 分區是否意外累積資料。</p>
]]></content:encoded></item><item><title>Local-First</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/local-first/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/local-first/</guid><description>&lt;p>Local-First 的核心概念是讓裝置本機持有資料、離線時功能照常運作，把和其他裝置或伺服器的同步當成次要且獨立的問題。它讓產品在弱網或離線下仍可用、互動沒有網路延遲，代價是要處理多端同步的合併語意。它依賴 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/embedded-database/" data-link-title="Embedded Database" data-link-desc="說明嵌入式資料庫如何隨 application process 運作，並把檔案生命週期責任交回應用">Embedded Database&lt;/a> 作為本機儲存，依賴 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/conflict-resolution/" data-link-title="Conflict Resolution" data-link-desc="說明並發或離線寫入產生衝突時，如何偵測、呈現與合併成可接受狀態">Conflict Resolution&lt;/a> 處理同步衝突。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Local-First 位在資料架構的一端，與「伺服器是唯一真相、客戶端只是視圖」相對。它把問題拆成兩層：本機的讀寫與持久性是一層，多端的收斂是另一層。本機層用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/embedded-database/" data-link-title="Embedded Database" data-link-desc="說明嵌入式資料庫如何隨 application process 運作，並把檔案生命週期責任交回應用">Embedded Database&lt;/a> 解決；收斂層要面對順序、權威來源與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/conflict-resolution/" data-link-title="Conflict Resolution" data-link-desc="說明並發或離線寫入產生衝突時，如何偵測、呈現與合併成可接受狀態">Conflict Resolution&lt;/a>，並和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">Eventual Consistency&lt;/a> 相鄰。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合 local-first 的訊號是行動或桌面 app 需要離線可用，或互動要求即時回饋，例如筆記、待辦、現場作業 app。需要謹慎的訊號是強一致需求：付款餘額、庫存、權限這類資料若每次都要看到最新的全域狀態，要先設計 read-after-write 路徑，而不是套用純 local-first。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要先界定哪些資料是 local-first、哪些必須即時和伺服器一致。同步層要決定權威來源、衝突策略，以及刪除如何傳播。observability 要能看到每個裝置的同步落後程度與待同步的本機變更量，讓「離線多久」是可量測的。&lt;/p></description><content:encoded><![CDATA[<p>Local-First 的核心概念是讓裝置本機持有資料、離線時功能照常運作，把和其他裝置或伺服器的同步當成次要且獨立的問題。它讓產品在弱網或離線下仍可用、互動沒有網路延遲，代價是要處理多端同步的合併語意。它依賴 <a href="/blog/backend/knowledge-cards/embedded-database/" data-link-title="Embedded Database" data-link-desc="說明嵌入式資料庫如何隨 application process 運作，並把檔案生命週期責任交回應用">Embedded Database</a> 作為本機儲存，依賴 <a href="/blog/backend/knowledge-cards/conflict-resolution/" data-link-title="Conflict Resolution" data-link-desc="說明並發或離線寫入產生衝突時，如何偵測、呈現與合併成可接受狀態">Conflict Resolution</a> 處理同步衝突。</p>
<h2 id="概念位置">概念位置</h2>
<p>Local-First 位在資料架構的一端，與「伺服器是唯一真相、客戶端只是視圖」相對。它把問題拆成兩層：本機的讀寫與持久性是一層，多端的收斂是另一層。本機層用 <a href="/blog/backend/knowledge-cards/embedded-database/" data-link-title="Embedded Database" data-link-desc="說明嵌入式資料庫如何隨 application process 運作，並把檔案生命週期責任交回應用">Embedded Database</a> 解決；收斂層要面對順序、權威來源與 <a href="/blog/backend/knowledge-cards/conflict-resolution/" data-link-title="Conflict Resolution" data-link-desc="說明並發或離線寫入產生衝突時，如何偵測、呈現與合併成可接受狀態">Conflict Resolution</a>，並和 <a href="/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">Eventual Consistency</a> 相鄰。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合 local-first 的訊號是行動或桌面 app 需要離線可用，或互動要求即時回饋，例如筆記、待辦、現場作業 app。需要謹慎的訊號是強一致需求：付款餘額、庫存、權限這類資料若每次都要看到最新的全域狀態，要先設計 read-after-write 路徑，而不是套用純 local-first。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要先界定哪些資料是 local-first、哪些必須即時和伺服器一致。同步層要決定權威來源、衝突策略，以及刪除如何傳播。observability 要能看到每個裝置的同步落後程度與待同步的本機變更量，讓「離線多久」是可量測的。</p>
]]></content:encoded></item><item><title>Document Store</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/document-store/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/document-store/</guid><description>&lt;p>Document Store 的核心概念是以 JSON 或 BSON 文件為單位儲存與查詢資料，schema 較彈性、巢狀結構可以直接存。它讓形狀多變或快速演進的資料容易落地，代價是 index、schema 演進與一致性仍要治理，彈性的範圍止於資料形狀、不延伸到免治理。它和關聯式的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database&lt;/a> 是不同的資料模型，查詢需求複雜時要對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Document Store 位在資料模型光譜上、和嚴格關聯式 schema 相對的一端。它可以是獨立的 document database，也可以是關聯式引擎內的 JSON 欄位或 document API。它適合放整份一起讀取的聚合資料；當資料間關係變多、需要 join 與跨文件一致性時，要回到關聯式建模或拆出 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合 document store 的訊號是資料以「一份完整文件」被讀寫、形狀因來源而異，例如使用者 profile、第三方整合 payload、feature flag 設定。需要重新評估的訊號是巢狀文件變成主要關聯模型，或 JSON 路徑變成核心查詢條件 — 這時要把熱欄位抽出來建 index，或把這部分 relationalize。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要決定哪些資料適合文件、單份文件多大、哪些 JSON 路徑需要 index，以及 schema 演進怎麼做。文件型資料仍需要 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">Schema Migration&lt;/a> 的紀律 — 欄位語意改變時要有版本與相容策略。observability 要看文件大小分佈，以及熱查詢路徑是否有 index 支撐。&lt;/p></description><content:encoded><![CDATA[<p>Document Store 的核心概念是以 JSON 或 BSON 文件為單位儲存與查詢資料，schema 較彈性、巢狀結構可以直接存。它讓形狀多變或快速演進的資料容易落地，代價是 index、schema 演進與一致性仍要治理，彈性的範圍止於資料形狀、不延伸到免治理。它和關聯式的 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">Database</a> 是不同的資料模型，查詢需求複雜時要對照 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">Read Model</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Document Store 位在資料模型光譜上、和嚴格關聯式 schema 相對的一端。它可以是獨立的 document database，也可以是關聯式引擎內的 JSON 欄位或 document API。它適合放整份一起讀取的聚合資料；當資料間關係變多、需要 join 與跨文件一致性時，要回到關聯式建模或拆出 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">Read Model</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合 document store 的訊號是資料以「一份完整文件」被讀寫、形狀因來源而異，例如使用者 profile、第三方整合 payload、feature flag 設定。需要重新評估的訊號是巢狀文件變成主要關聯模型，或 JSON 路徑變成核心查詢條件 — 這時要把熱欄位抽出來建 index，或把這部分 relationalize。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要決定哪些資料適合文件、單份文件多大、哪些 JSON 路徑需要 index，以及 schema 演進怎麼做。文件型資料仍需要 <a href="/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">Schema Migration</a> 的紀律 — 欄位語意改變時要有版本與相容策略。observability 要看文件大小分佈，以及熱查詢路徑是否有 index 支撐。</p>
]]></content:encoded></item><item><title>OLAP Offload</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/olap-offload/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/olap-offload/</guid><description>&lt;p>OLAP Offload 的核心概念是把分析型查詢從線上交易（OLTP）主庫移開，讓重量級的彙總、掃描與報表查詢不影響線上讀寫。它讓交易效能和分析需求各自有容量，代價是要決定分析資料放哪、以及它和主庫之間的新鮮度差。它常透過 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture&lt;/a> 把資料送到分析側，分析側本身則是一種 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>OLAP Offload 位在 OLTP 與分析系統之間的決策點。OLTP workload 是大量短交易，OLAP workload 是少量長查詢、掃大量資料；兩者放同一個資料庫會互相競爭 buffer、CPU 與 IO。卸載的路徑有 read replica、引擎內建的分析加速器，或用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture&lt;/a> 同步到資料倉儲。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 OLAP offload 的訊號是報表或分析查詢一跑，線上交易的延遲就升高。輕量做法是把分析查詢導到 read replica；查詢更重、要跨多來源或讀長期歷史資料時，要把資料同步到專門的分析系統。需要評估的取捨是資料新鮮度 — replica 與倉儲都有同步延遲，分析結果不是即時的。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要先量化分析 workload 的形狀（頻率、掃描量、並發），再選卸載路徑。要明確分析側可接受的資料延遲，並讓它成為 SLO 的一部分。observability 要能分開看 OLTP 與 OLAP 的資源用量，確認卸載後主庫的交易效能真的被保護。&lt;/p></description><content:encoded><![CDATA[<p>OLAP Offload 的核心概念是把分析型查詢從線上交易（OLTP）主庫移開，讓重量級的彙總、掃描與報表查詢不影響線上讀寫。它讓交易效能和分析需求各自有容量，代價是要決定分析資料放哪、以及它和主庫之間的新鮮度差。它常透過 <a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture</a> 把資料送到分析側，分析側本身則是一種 <a href="/blog/backend/knowledge-cards/read-model/" data-link-title="Read Model" data-link-desc="說明為查詢場景建立的讀取模型，與正式狀態的責任分離">Read Model</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>OLAP Offload 位在 OLTP 與分析系統之間的決策點。OLTP workload 是大量短交易，OLAP workload 是少量長查詢、掃大量資料；兩者放同一個資料庫會互相競爭 buffer、CPU 與 IO。卸載的路徑有 read replica、引擎內建的分析加速器，或用 <a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture</a> 同步到資料倉儲。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 OLAP offload 的訊號是報表或分析查詢一跑，線上交易的延遲就升高。輕量做法是把分析查詢導到 read replica；查詢更重、要跨多來源或讀長期歷史資料時，要把資料同步到專門的分析系統。需要評估的取捨是資料新鮮度 — replica 與倉儲都有同步延遲，分析結果不是即時的。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要先量化分析 workload 的形狀（頻率、掃描量、並發），再選卸載路徑。要明確分析側可接受的資料延遲，並讓它成為 SLO 的一部分。observability 要能分開看 OLTP 與 OLAP 的資源用量，確認卸載後主庫的交易效能真的被保護。</p>
]]></content:encoded></item><item><title>Key Management</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/key-management/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/key-management/</guid><description>&lt;p>Key Management 的核心概念是管理加密金鑰的完整生命週期 — 產生、保存、存取控制與輪替 — 並承擔「加密後的資料能否還原取決於金鑰是否健在」這個責任。它是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/at-rest-encryption/" data-link-title="At-Rest Encryption" data-link-desc="說明資料落到儲存媒介前的加密層，以及它對應的威脅模型">At-Rest Encryption&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>Key Management 位在加密機制的底層。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/at-rest-encryption/" data-link-title="At-Rest Encryption" data-link-desc="說明資料落到儲存媒介前的加密層，以及它對應的威脅模型">At-Rest Encryption&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/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management&lt;/a> 相鄰但責任不同：access secret（password、API key）外洩造成存取邊界失效，data-encryption key 遺失造成資料永久無法讀取。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要正視 key management 的訊號是系統用了 at-rest 加密、TLS 或 application-level 加密，卻沒有明確的金鑰 owner 與輪替排程。常見失敗是 restore 演練時才發現備份的 keyring 沒有一起保存，加密的 backup 變成無法還原的資料。雲端的 envelope encryption 與 customer-managed key 把金鑰階層攤開，讓輪替與撤銷可以分層進行。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義金鑰階層、每把金鑰的 owner、輪替週期與撤銷流程，並把金鑰納入 restore 演練。data-encryption key 要和 access secret 分開保存與分開稽核。observability 要能確認金鑰可用性、最近輪替時間與即將到期的金鑰。&lt;/p></description><content:encoded><![CDATA[<p>Key Management 的核心概念是管理加密金鑰的完整生命週期 — 產生、保存、存取控制與輪替 — 並承擔「加密後的資料能否還原取決於金鑰是否健在」這個責任。它是 <a href="/blog/backend/knowledge-cards/at-rest-encryption/" data-link-title="At-Rest Encryption" data-link-desc="說明資料落到儲存媒介前的加密層，以及它對應的威脅模型">At-Rest Encryption</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>Key Management 位在加密機制的底層。<a href="/blog/backend/knowledge-cards/at-rest-encryption/" data-link-title="At-Rest Encryption" data-link-desc="說明資料落到儲存媒介前的加密層，以及它對應的威脅模型">At-Rest Encryption</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/secret-management/" data-link-title="Secret Management" data-link-desc="說明 token、key、password 與憑證如何保存、輪替與撤銷">Secret Management</a> 相鄰但責任不同：access secret（password、API key）外洩造成存取邊界失效，data-encryption key 遺失造成資料永久無法讀取。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要正視 key management 的訊號是系統用了 at-rest 加密、TLS 或 application-level 加密，卻沒有明確的金鑰 owner 與輪替排程。常見失敗是 restore 演練時才發現備份的 keyring 沒有一起保存，加密的 backup 變成無法還原的資料。雲端的 envelope encryption 與 customer-managed key 把金鑰階層攤開，讓輪替與撤銷可以分層進行。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義金鑰階層、每把金鑰的 owner、輪替週期與撤銷流程，並把金鑰納入 restore 演練。data-encryption key 要和 access secret 分開保存與分開稽核。observability 要能確認金鑰可用性、最近輪替時間與即將到期的金鑰。</p>
]]></content:encoded></item><item><title>Replica Identity</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/replica-identity/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/replica-identity/</guid><description>&lt;p>Replica Identity 的核心概念是一張表對外輸出 row-level 變更時，必須附帶一個穩定的 key，讓下游系統知道每個 update 或 delete 事件要套用到哪一列。它是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/logical-replication/" data-link-title="Logical Replication" data-link-desc="說明以表為粒度解碼 row-level 變更的複製方式，對照 byte-level 的實體複製">Logical Replication&lt;/a> 能否正確重建資料的前置契約，缺少它時 update / delete 事件無法定位目標列。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Replica Identity 位在變更事件的 schema 契約層。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/logical-replication/" data-link-title="Logical Replication" data-link-desc="說明以表為粒度解碼 row-level 變更的複製方式，對照 byte-level 的實體複製">Logical Replication&lt;/a> 負責把變更傳出去，replica identity 決定那些事件本身帶不帶得出「改了哪一列」。多數情況 primary key 就是 replica identity；沒有 primary key 的表（某些 audit table、join table）要明確補一個唯一 key 或設定 full row image。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要檢查 replica identity 的訊號是下游套用 update / delete 時出現資料漂移或事件被丟棄。常見場景是一張沒有 primary key 的表進入 CDC pipeline，insert 事件正常、update / delete 事件卻無法對應目標列。這類問題通常是靜默的 — 資料慢慢不一致，而不是立刻報錯。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 CDC 或邏輯複製前，要先盤點每張要輸出變更的表是否有穩定 key。沒有 primary key 的表要補唯一鍵，或接受 full row image 的成本。observability 要能偵測下游套用失敗或被略過的 update / delete 事件。&lt;/p></description><content:encoded><![CDATA[<p>Replica Identity 的核心概念是一張表對外輸出 row-level 變更時，必須附帶一個穩定的 key，讓下游系統知道每個 update 或 delete 事件要套用到哪一列。它是 <a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture</a> 與 <a href="/blog/backend/knowledge-cards/logical-replication/" data-link-title="Logical Replication" data-link-desc="說明以表為粒度解碼 row-level 變更的複製方式，對照 byte-level 的實體複製">Logical Replication</a> 能否正確重建資料的前置契約，缺少它時 update / delete 事件無法定位目標列。</p>
<h2 id="概念位置">概念位置</h2>
<p>Replica Identity 位在變更事件的 schema 契約層。<a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture</a> 與 <a href="/blog/backend/knowledge-cards/logical-replication/" data-link-title="Logical Replication" data-link-desc="說明以表為粒度解碼 row-level 變更的複製方式，對照 byte-level 的實體複製">Logical Replication</a> 負責把變更傳出去，replica identity 決定那些事件本身帶不帶得出「改了哪一列」。多數情況 primary key 就是 replica identity；沒有 primary key 的表（某些 audit table、join table）要明確補一個唯一 key 或設定 full row image。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要檢查 replica identity 的訊號是下游套用 update / delete 時出現資料漂移或事件被丟棄。常見場景是一張沒有 primary key 的表進入 CDC pipeline，insert 事件正常、update / delete 事件卻無法對應目標列。這類問題通常是靜默的 — 資料慢慢不一致，而不是立刻報錯。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 CDC 或邏輯複製前，要先盤點每張要輸出變更的表是否有穩定 key。沒有 primary key 的表要補唯一鍵，或接受 full row image 的成本。observability 要能偵測下游套用失敗或被略過的 update / delete 事件。</p>
]]></content:encoded></item><item><title>Logical Replication</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/logical-replication/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/logical-replication/</guid><description>&lt;p>Logical Replication 的核心概念是以 table 或 publication 為粒度，把 row-level 變更解碼成邏輯事件再複製到下游，相對於整個 cluster byte-level 複製的實體複製。它讓跨版本、選擇性、跨系統的複製成為可能，代價是要處理 schema 漂移與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-slot/" data-link-title="Replication Slot" data-link-desc="說明邏輯複製如何用 slot 追蹤消費進度，並對來源端造成保留壓力">Replication Slot&lt;/a> 的保留壓力。它是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture&lt;/a> 的常見基礎。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Logical Replication 位在複製粒度光譜的一端。實體複製複製的是 storage 的 byte / page，整個 cluster 一起、版本綁定，適合 HA 與整體還原；logical replication 解碼成 row 事件、可選表、可跨版本，適合 CDC、跨系統同步與漸進遷移。它依賴 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/write-ahead-log/" data-link-title="Write-Ahead Log" data-link-desc="說明資料庫如何先寫入 log 再合併回主資料，以提供持久性與崩潰復原">Write-Ahead Log&lt;/a> 作為變更來源，用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-slot/" data-link-title="Replication Slot" data-link-desc="說明邏輯複製如何用 slot 追蹤消費進度，並對來源端造成保留壓力">Replication Slot&lt;/a> 追蹤進度。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合 logical replication 的訊號是只需要部分表、要跨大版本升級、或要把資料送到非同種系統。需要注意的訊號是 schema 變更：發佈端改 schema 時，訂閱端與下游 consumer 要協調，否則事件欄位對不上。它和實體複製是互補關係 — 許多系統同時用實體複製做 HA、用 logical replication 做資料整合。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要決定哪些表進入 logical replication、schema 變更如何在發佈端與訂閱端協調，以及 slot lag 的監控與告警。要明確它和實體複製各自承擔 HA 與資料整合的哪一塊。observability 要看 replication lag、slot 保留量與套用錯誤。&lt;/p></description><content:encoded><![CDATA[<p>Logical Replication 的核心概念是以 table 或 publication 為粒度，把 row-level 變更解碼成邏輯事件再複製到下游，相對於整個 cluster byte-level 複製的實體複製。它讓跨版本、選擇性、跨系統的複製成為可能，代價是要處理 schema 漂移與 <a href="/blog/backend/knowledge-cards/replication-slot/" data-link-title="Replication Slot" data-link-desc="說明邏輯複製如何用 slot 追蹤消費進度，並對來源端造成保留壓力">Replication Slot</a> 的保留壓力。它是 <a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture</a> 的常見基礎。</p>
<h2 id="概念位置">概念位置</h2>
<p>Logical Replication 位在複製粒度光譜的一端。實體複製複製的是 storage 的 byte / page，整個 cluster 一起、版本綁定，適合 HA 與整體還原；logical replication 解碼成 row 事件、可選表、可跨版本，適合 CDC、跨系統同步與漸進遷移。它依賴 <a href="/blog/backend/knowledge-cards/write-ahead-log/" data-link-title="Write-Ahead Log" data-link-desc="說明資料庫如何先寫入 log 再合併回主資料，以提供持久性與崩潰復原">Write-Ahead Log</a> 作為變更來源，用 <a href="/blog/backend/knowledge-cards/replication-slot/" data-link-title="Replication Slot" data-link-desc="說明邏輯複製如何用 slot 追蹤消費進度，並對來源端造成保留壓力">Replication Slot</a> 追蹤進度。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合 logical replication 的訊號是只需要部分表、要跨大版本升級、或要把資料送到非同種系統。需要注意的訊號是 schema 變更：發佈端改 schema 時，訂閱端與下游 consumer 要協調，否則事件欄位對不上。它和實體複製是互補關係 — 許多系統同時用實體複製做 HA、用 logical replication 做資料整合。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要決定哪些表進入 logical replication、schema 變更如何在發佈端與訂閱端協調，以及 slot lag 的監控與告警。要明確它和實體複製各自承擔 HA 與資料整合的哪一塊。observability 要看 replication lag、slot 保留量與套用錯誤。</p>
]]></content:encoded></item><item><title>Break-Glass Access</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/break-glass-access/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/break-glass-access/</guid><description>&lt;p>Break-Glass Access 的核心概念是在正常權限模型之外，為緊急事故臨時授予的高權限存取，並要求它伴隨工單、時限與事後審查。它讓事故處理在需要時拿得到必要權限，同時讓這個例外可被追溯。它是 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/security-exception/" data-link-title="Security Exception" data-link-desc="說明資安風險例外如何以期限、補償控制與關閉條件管理">Security Exception&lt;/a> 相鄰。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Break-Glass Access 位在日常權限與緊急需求之間。&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> 讓角色平時只拿必要權限；事故有時需要超出平時的存取，break-glass 讓這個提權是有流程、有時限、可回收的。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/security-exception/" data-link-title="Security Exception" data-link-desc="說明資安風險例外如何以期限、補償控制與關閉條件管理">Security Exception&lt;/a> 的差別在形態：security exception 是對已知風險的書面豁免決策，break-glass 是執行中的緊急存取流程。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 break-glass 機制的訊號是事故處理偶爾需要 production 高權限，但平時不該有人持有。沒有 break-glass 流程時，團隊常落入兩種有問題的做法：長期保留 admin 後門，或事故當下臨時亂開權限而沒有紀錄。健康的 break-glass 會在每次啟用時留下工單、申請人、時間窗與事後審查結果。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義誰能啟用、啟用要綁哪種工單、權限的自動回收時限，以及事後審查由誰做。每次 break-glass 啟用都要進 &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>。break-glass 流程本身要定期演練，確認事故當下真的拿得到、事後真的收得回。&lt;/p></description><content:encoded><![CDATA[<p>Break-Glass Access 的核心概念是在正常權限模型之外，為緊急事故臨時授予的高權限存取，並要求它伴隨工單、時限與事後審查。它讓事故處理在需要時拿得到必要權限，同時讓這個例外可被追溯。它是 <a href="/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">Least Privilege</a> 的受控例外，和 <a href="/blog/backend/knowledge-cards/security-exception/" data-link-title="Security Exception" data-link-desc="說明資安風險例外如何以期限、補償控制與關閉條件管理">Security Exception</a> 相鄰。</p>
<h2 id="概念位置">概念位置</h2>
<p>Break-Glass Access 位在日常權限與緊急需求之間。<a href="/blog/backend/knowledge-cards/least-privilege/" data-link-title="Least Privilege" data-link-desc="說明身份、服務與人員只應取得完成工作所需的最小權限">Least Privilege</a> 讓角色平時只拿必要權限；事故有時需要超出平時的存取，break-glass 讓這個提權是有流程、有時限、可回收的。它和 <a href="/blog/backend/knowledge-cards/security-exception/" data-link-title="Security Exception" data-link-desc="說明資安風險例外如何以期限、補償控制與關閉條件管理">Security Exception</a> 的差別在形態：security exception 是對已知風險的書面豁免決策，break-glass 是執行中的緊急存取流程。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 break-glass 機制的訊號是事故處理偶爾需要 production 高權限，但平時不該有人持有。沒有 break-glass 流程時，團隊常落入兩種有問題的做法：長期保留 admin 後門，或事故當下臨時亂開權限而沒有紀錄。健康的 break-glass 會在每次啟用時留下工單、申請人、時間窗與事後審查結果。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義誰能啟用、啟用要綁哪種工單、權限的自動回收時限，以及事後審查由誰做。每次 break-glass 啟用都要進 <a href="/blog/backend/knowledge-cards/audit-log/" data-link-title="Audit Log" data-link-desc="說明高風險操作如何留下可追溯、可稽核的紀錄">Audit Log</a>。break-glass 流程本身要定期演練，確認事故當下真的拿得到、事後真的收得回。</p>
]]></content:encoded></item><item><title>Read-After-Write Consistency</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/read-after-write/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/read-after-write/</guid><description>&lt;p>Read-After-Write Consistency 的核心概念是一個明確的保證：寫入成功後，後續讀取能立即看到這筆寫入。它讓「送出後馬上檢視」這類操作有正確的結果。它和泛指讀到舊資料的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read&lt;/a> 相對，並常和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/session-consistency/" data-link-title="Session Consistency" data-link-desc="同一使用者工作階段內維持讀寫一致、跨工作階段允許短暫不一致">Session Consistency&lt;/a> 一起出現。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Read-After-Write 位在一致性保證光譜上、比 eventual consistency 強的一端。它通常是 session 範圍的保證：同一使用者的寫入，自己後續讀得到。在用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/read-write-split/" data-link-title="Read-Write Split" data-link-desc="說明讀寫流量如何分流到 primary 與 replica，以及它引入的一致性責任">Read-Write Split&lt;/a> 的架構下它要特別設計，因為讀取分流到有 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag&lt;/a> 的 replica 時，剛寫入的資料可能還沒同步。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 read-after-write 的訊號是使用者送出資料後會立刻看結果：下單後看訂單、發文後看貼文、改設定後回設定頁。這些路徑讀到舊狀態會被當成「資料遺失」的 bug。提供保證的常見做法是讓這類讀取走 primary、加 lag guard、或在 session 內 pin 到能看到自己寫入的來源。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要列出哪些讀取路徑需要 read-after-write 保證，並為它們選實作方式。要明確保證的範圍：是同一 session、跨 session、還是全域。observability 要能量到分流到 replica 的讀取中，有多少落在 lag 窗口內而可能讀到舊資料。&lt;/p></description><content:encoded><![CDATA[<p>Read-After-Write Consistency 的核心概念是一個明確的保證：寫入成功後，後續讀取能立即看到這筆寫入。它讓「送出後馬上檢視」這類操作有正確的結果。它和泛指讀到舊資料的 <a href="/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read</a> 相對，並常和 <a href="/blog/backend/knowledge-cards/session-consistency/" data-link-title="Session Consistency" data-link-desc="同一使用者工作階段內維持讀寫一致、跨工作階段允許短暫不一致">Session Consistency</a> 一起出現。</p>
<h2 id="概念位置">概念位置</h2>
<p>Read-After-Write 位在一致性保證光譜上、比 eventual consistency 強的一端。它通常是 session 範圍的保證：同一使用者的寫入，自己後續讀得到。在用 <a href="/blog/backend/knowledge-cards/read-write-split/" data-link-title="Read-Write Split" data-link-desc="說明讀寫流量如何分流到 primary 與 replica，以及它引入的一致性責任">Read-Write Split</a> 的架構下它要特別設計，因為讀取分流到有 <a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag</a> 的 replica 時，剛寫入的資料可能還沒同步。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 read-after-write 的訊號是使用者送出資料後會立刻看結果：下單後看訂單、發文後看貼文、改設定後回設定頁。這些路徑讀到舊狀態會被當成「資料遺失」的 bug。提供保證的常見做法是讓這類讀取走 primary、加 lag guard、或在 session 內 pin 到能看到自己寫入的來源。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要列出哪些讀取路徑需要 read-after-write 保證，並為它們選實作方式。要明確保證的範圍：是同一 session、跨 session、還是全域。observability 要能量到分流到 replica 的讀取中，有多少落在 lag 窗口內而可能讀到舊資料。</p>
]]></content:encoded></item><item><title>Tombstone</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/tombstone/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/tombstone/</guid><description>&lt;p>Tombstone 的核心概念是用一筆「已刪除」標記來記錄刪除，而不是直接讓資料消失，讓刪除這個事件能跨副本、裝置或下游系統傳播。它讓最終一致系統裡的刪除不會被遺漏。它是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/conflict-resolution/" data-link-title="Conflict Resolution" data-link-desc="說明並發或離線寫入產生衝突時，如何偵測、呈現與合併成可接受狀態">Conflict Resolution&lt;/a> 與資料同步處理刪除的基礎機制。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Tombstone 位在「刪除如何被當成事件」的環節。在單一資料庫內，刪除就是移除一列；但在有副本、有離線裝置或有 CDC 下游的系統裡，直接移除會讓其他端不知道「這筆被刪了」。tombstone 把刪除變成一筆可傳播的標記，和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">Eventual Consistency&lt;/a> 一起讓刪除能收斂。它的保留期限要接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-lifecycle/" data-link-title="Data Lifecycle" data-link-desc="說明資料從建立、使用、保留到刪除的責任邊界">資料生命週期&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 tombstone 的訊號是資料會被多端複製或同步，而刪除必須確實傳到每一端。常見失敗是離線裝置重新上線後，把本地還在的「已被刪除資料」同步回伺服器 — 對隱私與合規是實質失效。tombstone 也要設保留期：留太短會讓久未上線的端漏接刪除，留太長會讓墓碑本身累積。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要決定哪些資料的刪除需要 tombstone、墓碑保留多久、以及何時可以真正清除。保留期要長過預期的最長離線或失聯窗口。observability 要能看到 tombstone 數量與最舊未被所有端確認的刪除。&lt;/p></description><content:encoded><![CDATA[<p>Tombstone 的核心概念是用一筆「已刪除」標記來記錄刪除，而不是直接讓資料消失，讓刪除這個事件能跨副本、裝置或下游系統傳播。它讓最終一致系統裡的刪除不會被遺漏。它是 <a href="/blog/backend/knowledge-cards/conflict-resolution/" data-link-title="Conflict Resolution" data-link-desc="說明並發或離線寫入產生衝突時，如何偵測、呈現與合併成可接受狀態">Conflict Resolution</a> 與資料同步處理刪除的基礎機制。</p>
<h2 id="概念位置">概念位置</h2>
<p>Tombstone 位在「刪除如何被當成事件」的環節。在單一資料庫內，刪除就是移除一列；但在有副本、有離線裝置或有 CDC 下游的系統裡，直接移除會讓其他端不知道「這筆被刪了」。tombstone 把刪除變成一筆可傳播的標記，和 <a href="/blog/backend/knowledge-cards/eventual-consistency/" data-link-title="Eventual Consistency" data-link-desc="允許短暫不一致、最終收斂到同一資料狀態的一致性語意">Eventual Consistency</a> 一起讓刪除能收斂。它的保留期限要接回 <a href="/blog/backend/knowledge-cards/data-lifecycle/" data-link-title="Data Lifecycle" data-link-desc="說明資料從建立、使用、保留到刪除的責任邊界">資料生命週期</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 tombstone 的訊號是資料會被多端複製或同步，而刪除必須確實傳到每一端。常見失敗是離線裝置重新上線後，把本地還在的「已被刪除資料」同步回伺服器 — 對隱私與合規是實質失效。tombstone 也要設保留期：留太短會讓久未上線的端漏接刪除，留太長會讓墓碑本身累積。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要決定哪些資料的刪除需要 tombstone、墓碑保留多久、以及何時可以真正清除。保留期要長過預期的最長離線或失聯窗口。observability 要能看到 tombstone 數量與最舊未被所有端確認的刪除。</p>
]]></content:encoded></item><item><title>Per-Connection Memory</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/per-connection-memory/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/per-connection-memory/</guid><description>&lt;p>Per-Connection Memory 的核心概念是某些記憶體是「每條連線」或「每個操作」各自配置的 — sort buffer、join buffer、連線本身的開銷 — 它的總量等於單份用量乘上並發連線數。它讓並發尖峰時的記憶體用量可能遠超直覺。它和全域共用的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/buffer-pool/" data-link-title="Buffer Pool" data-link-desc="說明資料庫如何用記憶體快取磁碟頁，以降低 I/O 並影響查詢效能">Buffer Pool&lt;/a> 是兩種不同的記憶體，並和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool&lt;/a> 直接相關。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Per-Connection Memory 位在資料庫記憶體模型中、與全域記憶體相對的一側。全域記憶體（例如 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/buffer-pool/" data-link-title="Buffer Pool" data-link-desc="說明資料庫如何用記憶體快取磁碟頁，以降低 I/O 並影響查詢效能">Buffer Pool&lt;/a>）由所有連線共用、調一次影響全體；per-connection 記憶體每條連線各配一份，調大單份設定會被並發數放大。連線數的上限由 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool&lt;/a> 與資料庫設定共同決定。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要注意 per-connection memory 的訊號是資料庫在尖峰並發時記憶體吃緊、OOM 或被容器重啟，但平時看起來有餘裕。常見的反直覺陷阱是為了讓某個查詢更快而調大 sort / join buffer，結果在高並發時這個「單份」設定乘上幾百條連線，把記憶體撐爆。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要把記憶體預算拆成全域與 per-connection 兩部分，並用最大並發連線數去乘 per-connection 設定，確認尖峰仍在容量內。調校順序通常是先把全域記憶體調穩，再針對特定查詢調 session 層設定，並同時限制連線數。observability 要看連線數、記憶體用量與 OOM / swap 訊號。&lt;/p></description><content:encoded><![CDATA[<p>Per-Connection Memory 的核心概念是某些記憶體是「每條連線」或「每個操作」各自配置的 — sort buffer、join buffer、連線本身的開銷 — 它的總量等於單份用量乘上並發連線數。它讓並發尖峰時的記憶體用量可能遠超直覺。它和全域共用的 <a href="/blog/backend/knowledge-cards/buffer-pool/" data-link-title="Buffer Pool" data-link-desc="說明資料庫如何用記憶體快取磁碟頁，以降低 I/O 並影響查詢效能">Buffer Pool</a> 是兩種不同的記憶體，並和 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool</a> 直接相關。</p>
<h2 id="概念位置">概念位置</h2>
<p>Per-Connection Memory 位在資料庫記憶體模型中、與全域記憶體相對的一側。全域記憶體（例如 <a href="/blog/backend/knowledge-cards/buffer-pool/" data-link-title="Buffer Pool" data-link-desc="說明資料庫如何用記憶體快取磁碟頁，以降低 I/O 並影響查詢效能">Buffer Pool</a>）由所有連線共用、調一次影響全體；per-connection 記憶體每條連線各配一份，調大單份設定會被並發數放大。連線數的上限由 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">Connection Pool</a> 與資料庫設定共同決定。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要注意 per-connection memory 的訊號是資料庫在尖峰並發時記憶體吃緊、OOM 或被容器重啟，但平時看起來有餘裕。常見的反直覺陷阱是為了讓某個查詢更快而調大 sort / join buffer，結果在高並發時這個「單份」設定乘上幾百條連線，把記憶體撐爆。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要把記憶體預算拆成全域與 per-connection 兩部分，並用最大並發連線數去乘 per-connection 設定，確認尖峰仍在容量內。調校順序通常是先把全域記憶體調穩，再針對特定查詢調 session 層設定，並同時限制連線數。observability 要看連線數、記憶體用量與 OOM / swap 訊號。</p>
]]></content:encoded></item><item><title>Replication Channel</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/replication-channel/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/replication-channel/</guid><description>&lt;p>Replication Channel 的核心概念是當一個資料庫同時從多個來源複製時，每個來源對應一條獨立的複製通道，各自有自己的進度、延遲、錯誤與設定。它讓多來源複製的健康狀況可以被分開判讀與分開處理，每條通道的延遲要分開接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Replication Channel 位在多來源複製的拓撲層。單一來源的複製只有一條流；多來源複製把多條流並存在同一個目標資料庫上，每條就是一個 channel。channel 是隔離單位：一個來源的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag&lt;/a> 或錯誤不必然代表其他來源也有問題，&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/gtid/" data-link-title="GTID" data-link-desc="說明全域交易識別碼如何讓複製進度與故障切換不依賴實體 log 位置">GTID&lt;/a> 之類的識別機制讓各 channel 的位置可以分開追蹤。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 per-channel 視角的訊號是整體 replica 看起來健康、但某個來源的資料就是慢或對不上。只看整體 replica lag 會錯過「哪一個來源卡住」。常見場景是把多個地區或多個服務的資料庫匯總到一個分析庫，其中一條 channel 因為網路或 schema 問題落後，其他 channel 正常。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要為每條 channel 命名、定義各自的 owner、lag SLO 與錯誤處理策略。監控與告警要做到 per-channel，並讓單一 channel 的故障可以只停那一條、不影響其他來源。observability 要能分開看每條 channel 的位置、延遲與錯誤。&lt;/p></description><content:encoded><![CDATA[<p>Replication Channel 的核心概念是當一個資料庫同時從多個來源複製時，每個來源對應一條獨立的複製通道，各自有自己的進度、延遲、錯誤與設定。它讓多來源複製的健康狀況可以被分開判讀與分開處理，每條通道的延遲要分開接回 <a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Replication Channel 位在多來源複製的拓撲層。單一來源的複製只有一條流；多來源複製把多條流並存在同一個目標資料庫上，每條就是一個 channel。channel 是隔離單位：一個來源的 <a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag</a> 或錯誤不必然代表其他來源也有問題，<a href="/blog/backend/knowledge-cards/gtid/" data-link-title="GTID" data-link-desc="說明全域交易識別碼如何讓複製進度與故障切換不依賴實體 log 位置">GTID</a> 之類的識別機制讓各 channel 的位置可以分開追蹤。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 per-channel 視角的訊號是整體 replica 看起來健康、但某個來源的資料就是慢或對不上。只看整體 replica lag 會錯過「哪一個來源卡住」。常見場景是把多個地區或多個服務的資料庫匯總到一個分析庫，其中一條 channel 因為網路或 schema 問題落後，其他 channel 正常。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要為每條 channel 命名、定義各自的 owner、lag SLO 與錯誤處理策略。監控與告警要做到 per-channel，並讓單一 channel 的故障可以只停那一條、不影響其他來源。observability 要能分開看每條 channel 的位置、延遲與錯誤。</p>
]]></content:encoded></item><item><title>Vendor Lock-In</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/vendor-lock-in/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/vendor-lock-in/</guid><description>&lt;p>Vendor Lock-In 的核心概念是採用某個供應商的產品後，它的 API、資料格式或平台行為逐漸滲入核心程式碼，使得日後要換掉它的成本變得很高。它讓「現在好接」與「日後難退」成為要一起評估的取捨。降低它的手段要接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/provider-adapter/" data-link-title="Provider Adapter" data-link-desc="說明第三方服務如何被包裝成內部穩定介面">Provider Adapter&lt;/a> 與 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Vendor Lock-In 位在選型決策的長期成本面。它本身是風險概念，&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/provider-adapter/" data-link-title="Provider Adapter" data-link-desc="說明第三方服務如何被包裝成內部穩定介面">Provider Adapter&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/adapter/" data-link-title="Integration Adapter" data-link-desc="說明外部系統接入層如何轉換介面與隔離差異">Integration Adapter&lt;/a> 則是緩解它的設計手段 — 把供應商特定的介面包在 adapter 後面，讓 domain 程式碼不直接依賴它。退出時的搬遷要接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">Migration&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要正視 vendor lock-in 的訊號是供應商特定的 driver API、查詢語法或資料格式出現在 domain 邏輯裡。低採用成本的產品（特別是 edge 或 serverless 類）常把成本藏在退出端：接的時候很快，要換的時候發現整個 codebase 都綁住了。一個務實的檢查是「能不能說清楚退出路徑」。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要把供應商特定的介面收斂到 adapter 層，並明確記錄退出路徑：要換掉這個供應商，需要動哪些地方。對關鍵依賴，退出路徑應該被實際演練過，而不是只存在文件上。是否接受某個 lock-in 是有效的決策，前提是在採用當下就把成本看清楚。&lt;/p></description><content:encoded><![CDATA[<p>Vendor Lock-In 的核心概念是採用某個供應商的產品後，它的 API、資料格式或平台行為逐漸滲入核心程式碼，使得日後要換掉它的成本變得很高。它讓「現在好接」與「日後難退」成為要一起評估的取捨。降低它的手段要接回 <a href="/blog/backend/knowledge-cards/provider-adapter/" data-link-title="Provider Adapter" data-link-desc="說明第三方服務如何被包裝成內部穩定介面">Provider Adapter</a> 與 <a href="/blog/backend/knowledge-cards/repository-adapter/" data-link-title="Repository Adapter" data-link-desc="說明持久化層如何把資料模型轉成外部儲存介面">Repository Adapter</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Vendor Lock-In 位在選型決策的長期成本面。它本身是風險概念，<a href="/blog/backend/knowledge-cards/provider-adapter/" data-link-title="Provider Adapter" data-link-desc="說明第三方服務如何被包裝成內部穩定介面">Provider Adapter</a> 與 <a href="/blog/backend/knowledge-cards/adapter/" data-link-title="Integration Adapter" data-link-desc="說明外部系統接入層如何轉換介面與隔離差異">Integration Adapter</a> 則是緩解它的設計手段 — 把供應商特定的介面包在 adapter 後面，讓 domain 程式碼不直接依賴它。退出時的搬遷要接回 <a href="/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">Migration</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要正視 vendor lock-in 的訊號是供應商特定的 driver API、查詢語法或資料格式出現在 domain 邏輯裡。低採用成本的產品（特別是 edge 或 serverless 類）常把成本藏在退出端：接的時候很快，要換的時候發現整個 codebase 都綁住了。一個務實的檢查是「能不能說清楚退出路徑」。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要把供應商特定的介面收斂到 adapter 層，並明確記錄退出路徑：要換掉這個供應商，需要動哪些地方。對關鍵依賴，退出路徑應該被實際演練過，而不是只存在文件上。是否接受某個 lock-in 是有效的決策，前提是在採用當下就把成本看清楚。</p>
]]></content:encoded></item><item><title>Corruption Recovery</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/corruption-recovery/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/corruption-recovery/</guid><description>&lt;p>Corruption Recovery 的核心概念是處理資料損毀事故時，先辨識損毀來自儲存層（檔案、磁碟、檔案系統）還是應用層（寫入了錯誤資料），保全證據，再決定修復或還原。它讓損毀事故有確定的處置順序，而不是直覺地直接修。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/embedded-database/" data-link-title="Embedded Database" data-link-desc="說明嵌入式資料庫如何隨 application process 運作，並把檔案生命週期責任交回應用">Embedded Database&lt;/a> 特別相關，因為這類系統的檔案責任落在 application。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Corruption Recovery 位在事故處理流程中、針對「資料本身壞了」這一類事故。它和一般 incident response 共用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">Evidence Package&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rca/" data-link-title="RCA" data-link-desc="說明根因分析如何區分觸發事件、系統弱點與防線缺口">RCA&lt;/a> 的紀律，但多一個前置判斷：儲存層損毀與應用層寫錯的修法不同，前者要還原、後者要修資料也要修程式。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 corruption recovery 流程的訊號是讀取時出現 checksum 錯誤、結構異常或資料明顯不合理。一個常見的處置錯誤是在疑似損毀的檔案上直接跑修復或 vacuum — 那可能把還能搶救的狀態也蓋掉。正確的第一步是先複製一份原始損毀檔案，保留它當證據與還原素材。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義損毀的偵測訊號、第一步的證據保全動作，以及修復與還原的決策分支。要事先確認 backup 與還原機制本身可用，否則損毀事故發生時沒有退路。observability 要能盡早偵測 corruption 訊號，把它和一般錯誤分開。&lt;/p></description><content:encoded><![CDATA[<p>Corruption Recovery 的核心概念是處理資料損毀事故時，先辨識損毀來自儲存層（檔案、磁碟、檔案系統）還是應用層（寫入了錯誤資料），保全證據，再決定修復或還原。它讓損毀事故有確定的處置順序，而不是直覺地直接修。它和 <a href="/blog/backend/knowledge-cards/embedded-database/" data-link-title="Embedded Database" data-link-desc="說明嵌入式資料庫如何隨 application process 運作，並把檔案生命週期責任交回應用">Embedded Database</a> 特別相關，因為這類系統的檔案責任落在 application。</p>
<h2 id="概念位置">概念位置</h2>
<p>Corruption Recovery 位在事故處理流程中、針對「資料本身壞了」這一類事故。它和一般 incident response 共用 <a href="/blog/backend/knowledge-cards/evidence-package/" data-link-title="Evidence Package" data-link-desc="說明觀測、驗證與事故流程如何把證據包成可交接、可回放的 artifact">Evidence Package</a>、<a href="/blog/backend/knowledge-cards/rca/" data-link-title="RCA" data-link-desc="說明根因分析如何區分觸發事件、系統弱點與防線缺口">RCA</a> 的紀律，但多一個前置判斷：儲存層損毀與應用層寫錯的修法不同，前者要還原、後者要修資料也要修程式。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 corruption recovery 流程的訊號是讀取時出現 checksum 錯誤、結構異常或資料明顯不合理。一個常見的處置錯誤是在疑似損毀的檔案上直接跑修復或 vacuum — 那可能把還能搶救的狀態也蓋掉。正確的第一步是先複製一份原始損毀檔案，保留它當證據與還原素材。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義損毀的偵測訊號、第一步的證據保全動作，以及修復與還原的決策分支。要事先確認 backup 與還原機制本身可用，否則損毀事故發生時沒有退路。observability 要能盡早偵測 corruption 訊號，把它和一般錯誤分開。</p>
]]></content:encoded></item><item><title>Buffer Pool</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/buffer-pool/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/buffer-pool/</guid><description>&lt;p>Buffer Pool 的核心概念是資料庫在記憶體中快取磁碟上的資料頁，讓重複存取的資料不必每次讀磁碟。它是資料庫最主要的記憶體消耗者，命中率直接決定查詢要走記憶體還是 I/O。它是全域共用的快取，和每條連線各自配置的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/per-connection-memory/" data-link-title="Per-Connection Memory" data-link-desc="說明每條連線或每個操作的記憶體用量如何隨並發數放大">Per-Connection Memory&lt;/a> 是兩種不同的記憶體。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Buffer Pool 位在資料庫的儲存與運算之間。MySQL 的 InnoDB buffer pool、PostgreSQL 的 shared buffers 都是同一個概念 — 磁碟頁的記憶體快取。它的更新搭配 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/write-ahead-log/" data-link-title="Write-Ahead Log" data-link-desc="說明資料庫如何先寫入 log 再合併回主資料，以提供持久性與崩潰復原">Write-Ahead Log&lt;/a>：變更先發生在 buffer pool 的頁面上、寫入 WAL，再由 checkpoint 落回磁碟。容量不足時要決定哪些頁被換出，接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/eviction/" data-link-title="Eviction" data-link-desc="說明快取容量不足時哪些資料會被淘汰，以及淘汰如何影響服務">Eviction&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>觀察 buffer pool 的關鍵指標是命中率：命中率高代表多數讀取走記憶體，命中率掉代表查詢開始打磁碟、延遲上升。常見場景是資料量成長超過 buffer pool 大小，熱資料放不下、頁面頻繁換進換出，查詢延遲整體升高。這時要評估加大 buffer pool 或縮小工作集。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要讓 buffer pool 大小和熱資料工作集、機器記憶體與 per-connection 記憶體預算一起規劃。buffer pool 調大會擠壓其他記憶體用途，要留餘裕給連線與作業系統。observability 要看命中率、換頁速率與 dirty page 比例。&lt;/p></description><content:encoded><![CDATA[<p>Buffer Pool 的核心概念是資料庫在記憶體中快取磁碟上的資料頁，讓重複存取的資料不必每次讀磁碟。它是資料庫最主要的記憶體消耗者，命中率直接決定查詢要走記憶體還是 I/O。它是全域共用的快取，和每條連線各自配置的 <a href="/blog/backend/knowledge-cards/per-connection-memory/" data-link-title="Per-Connection Memory" data-link-desc="說明每條連線或每個操作的記憶體用量如何隨並發數放大">Per-Connection Memory</a> 是兩種不同的記憶體。</p>
<h2 id="概念位置">概念位置</h2>
<p>Buffer Pool 位在資料庫的儲存與運算之間。MySQL 的 InnoDB buffer pool、PostgreSQL 的 shared buffers 都是同一個概念 — 磁碟頁的記憶體快取。它的更新搭配 <a href="/blog/backend/knowledge-cards/write-ahead-log/" data-link-title="Write-Ahead Log" data-link-desc="說明資料庫如何先寫入 log 再合併回主資料，以提供持久性與崩潰復原">Write-Ahead Log</a>：變更先發生在 buffer pool 的頁面上、寫入 WAL，再由 checkpoint 落回磁碟。容量不足時要決定哪些頁被換出，接回 <a href="/blog/backend/knowledge-cards/eviction/" data-link-title="Eviction" data-link-desc="說明快取容量不足時哪些資料會被淘汰，以及淘汰如何影響服務">Eviction</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>觀察 buffer pool 的關鍵指標是命中率：命中率高代表多數讀取走記憶體，命中率掉代表查詢開始打磁碟、延遲上升。常見場景是資料量成長超過 buffer pool 大小，熱資料放不下、頁面頻繁換進換出，查詢延遲整體升高。這時要評估加大 buffer pool 或縮小工作集。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要讓 buffer pool 大小和熱資料工作集、機器記憶體與 per-connection 記憶體預算一起規劃。buffer pool 調大會擠壓其他記憶體用途，要留餘裕給連線與作業系統。observability 要看命中率、換頁速率與 dirty page 比例。</p>
]]></content:encoded></item><item><title>GTID</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/gtid/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/gtid/</guid><description>&lt;p>GTID（Global Transaction Identifier）的核心概念是給每一筆交易一個全域唯一的識別碼，讓複製進度用「套用到哪個交易」來表示，而不是用某台機器上的實體 log 檔名與位移。它讓 replica 重接、故障切換與拓撲調整不必手算 log 位置。它是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-channel/" data-link-title="Replication Channel" data-link-desc="說明多來源複製中，每個來源對應的獨立複製通道如何成為隔離單位">Replication Channel&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture&lt;/a> 追蹤位置的基礎。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>GTID 位在複製拓撲的進度標記層。沒有 GTID 時，replica 的進度是「primary 的 binlog 檔加位移」，這個座標換一台 primary 就失效；GTID 用交易本身的識別碼當座標，跨機器仍成立。它讓 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">Failover&lt;/a> 後 replica 能自動找到接續點，也讓 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag&lt;/a> 可以用「落後幾個交易」表達。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 GTID 的訊號是拓撲會變動：會做故障切換、會加減 replica、會調整複製鏈。用實體 log 位置時，每次換 primary 都要手動換算每個 replica 的接續點，容易出錯；GTID 讓 replica 指向新 primary 後自動續傳。CDC 工具也常用 GTID 當位置標記，讓 consumer 斷線重連後既不漏事件也不重複。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要在拓撲全體一致地啟用 GTID，並讓故障切換、CDC consumer 與備援流程都以 GTID 為位置基準。要監控每個 replica 與 consumer 已套用的 GTID 集合，據此判斷延遲與缺口。observability 要能看到 GTID 落後量與是否有 gap。&lt;/p></description><content:encoded><![CDATA[<p>GTID（Global Transaction Identifier）的核心概念是給每一筆交易一個全域唯一的識別碼，讓複製進度用「套用到哪個交易」來表示，而不是用某台機器上的實體 log 檔名與位移。它讓 replica 重接、故障切換與拓撲調整不必手算 log 位置。它是 <a href="/blog/backend/knowledge-cards/replication-channel/" data-link-title="Replication Channel" data-link-desc="說明多來源複製中，每個來源對應的獨立複製通道如何成為隔離單位">Replication Channel</a> 與 <a href="/blog/backend/knowledge-cards/change-data-capture/" data-link-title="Change Data Capture" data-link-desc="說明資料變更如何被捕捉並傳送到其他系統">Change Data Capture</a> 追蹤位置的基礎。</p>
<h2 id="概念位置">概念位置</h2>
<p>GTID 位在複製拓撲的進度標記層。沒有 GTID 時，replica 的進度是「primary 的 binlog 檔加位移」，這個座標換一台 primary 就失效；GTID 用交易本身的識別碼當座標，跨機器仍成立。它讓 <a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">Failover</a> 後 replica 能自動找到接續點，也讓 <a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag</a> 可以用「落後幾個交易」表達。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 GTID 的訊號是拓撲會變動：會做故障切換、會加減 replica、會調整複製鏈。用實體 log 位置時，每次換 primary 都要手動換算每個 replica 的接續點，容易出錯；GTID 讓 replica 指向新 primary 後自動續傳。CDC 工具也常用 GTID 當位置標記，讓 consumer 斷線重連後既不漏事件也不重複。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要在拓撲全體一致地啟用 GTID，並讓故障切換、CDC consumer 與備援流程都以 GTID 為位置基準。要監控每個 replica 與 consumer 已套用的 GTID 集合，據此判斷延遲與缺口。observability 要能看到 GTID 落後量與是否有 gap。</p>
]]></content:encoded></item><item><title>Point-in-Time Recovery</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/point-in-time-recovery/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/point-in-time-recovery/</guid><description>&lt;p>Point-in-Time Recovery（PITR）的核心概念是用一份完整備份，加上備份之後累積的變更日誌，把資料庫還原到過去任意一個時間點。它讓「還原到誤操作發生的前一刻」成為可能，而不只是還原到最近一次備份。它依賴 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/write-ahead-log/" data-link-title="Write-Ahead Log" data-link-desc="說明資料庫如何先寫入 log 再合併回主資料，以提供持久性與崩潰復原">Write-Ahead Log&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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Point-in-Time Recovery 位在備份還原機制中、比「還原到最近備份」更精細的一端。&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO&lt;/a> 是還原的目標（可接受的資料損失與停機時間），PITR 是達成這些目標的機制：base backup 決定起點、持續歸檔的變更日誌決定能還原到多近的時間點。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">Rollback Strategy&lt;/a> 一起構成事故的資料復原能力。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 PITR 的訊號是事故型態包含「某個時間點之後的資料被汙染」 — 誤刪、錯誤的批次更新、應用 bug 寫壞資料。只有定期備份時，還原會把備份之後的正常資料一起丟掉；PITR 讓還原點可以精準停在汙染發生前。常見的隱性風險是變更日誌歸檔斷掉，PITR 的可還原窗口其實有缺口卻沒被發現。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要確認 base backup 頻率、變更日誌的持續歸檔、以及可還原窗口的長度。PITR 要定期演練 — 真正跑一次還原到指定時間點，才能確認備份與日誌都完整、RTO 在預期內。observability 要監控日誌歸檔是否連續、最舊可還原時間點是否符合 RPO。&lt;/p></description><content:encoded><![CDATA[<p>Point-in-Time Recovery（PITR）的核心概念是用一份完整備份，加上備份之後累積的變更日誌，把資料庫還原到過去任意一個時間點。它讓「還原到誤操作發生的前一刻」成為可能，而不只是還原到最近一次備份。它依賴 <a href="/blog/backend/knowledge-cards/write-ahead-log/" data-link-title="Write-Ahead Log" data-link-desc="說明資料庫如何先寫入 log 再合併回主資料，以提供持久性與崩潰復原">Write-Ahead Log</a> 之類的變更日誌，是達成 <a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a> 的具體機制。</p>
<h2 id="概念位置">概念位置</h2>
<p>Point-in-Time Recovery 位在備份還原機制中、比「還原到最近備份」更精細的一端。<a href="/blog/backend/knowledge-cards/rpo/" data-link-title="RPO" data-link-desc="說明恢復點目標如何定義可接受資料損失範圍">RPO</a> 與 <a href="/blog/backend/knowledge-cards/rto/" data-link-title="RTO" data-link-desc="說明恢復時間目標如何約束事故回復策略">RTO</a> 是還原的目標（可接受的資料損失與停機時間），PITR 是達成這些目標的機制：base backup 決定起點、持續歸檔的變更日誌決定能還原到多近的時間點。它和 <a href="/blog/backend/knowledge-cards/rollback-strategy/" data-link-title="Rollback Strategy" data-link-desc="說明事故期間如何判斷回滾、回切與暫停變更">Rollback Strategy</a> 一起構成事故的資料復原能力。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 PITR 的訊號是事故型態包含「某個時間點之後的資料被汙染」 — 誤刪、錯誤的批次更新、應用 bug 寫壞資料。只有定期備份時，還原會把備份之後的正常資料一起丟掉；PITR 讓還原點可以精準停在汙染發生前。常見的隱性風險是變更日誌歸檔斷掉，PITR 的可還原窗口其實有缺口卻沒被發現。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要確認 base backup 頻率、變更日誌的持續歸檔、以及可還原窗口的長度。PITR 要定期演練 — 真正跑一次還原到指定時間點，才能確認備份與日誌都完整、RTO 在預期內。observability 要監控日誌歸檔是否連續、最舊可還原時間點是否符合 RPO。</p>
]]></content:encoded></item><item><title>Outbound Tunnel</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/outbound-tunnel/</link><pubDate>Thu, 18 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/outbound-tunnel/</guid><description>&lt;p>Outbound tunnel 是一種入口形態：本機進程主動對外連到邊緣節點，把流量沿反向隧道帶回來，路由器零開 port、對公網零入站面。跟傳統 port-forward（從外往內開 port）的責任方向相反 — 連線由內部發起、外部只能沿已建立的隧道回來。與 &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> 的責任方向不同：LB 假設 instance 有公開可達位址，tunnel 由內部主動外連。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Outbound tunnel 位在本機進程與公網之間，取代傳統的 port-forward 或 &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/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS&lt;/a> 搭配保護隧道內的傳輸安全，認證則疊在 tunnel 之後由 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authentication-middleware/" data-link-title="Authentication Middleware" data-link-desc="說明請求進入 handler 前如何完成身份驗證">authentication middleware&lt;/a> 處理。&lt;/p>
&lt;p>常見實作包括 cloudflared（綁 Cloudflare 邊緣）和 Tailscale（WireGuard mesh VPN）。隧道網址是位址、不是密碼 — 認證必須疊在 tunnel 之後。&lt;/p>
&lt;p>深入：&lt;a href="https://tarrragon.github.io/blog/backend/05-deployment-platform/outbound-tunnel-entry/" data-link-title="5.10 Outbound Tunnel 入口與生命週期" data-link-desc="整理 cloudflared / Tailscale 等反向隧道的入口形態、生命週期合約與故障模式">5.10 Outbound Tunnel 入口與生命週期&lt;/a>。選型案例：&lt;a href="https://tarrragon.github.io/blog/backend/07-security-data-protection/cases/remote-shell-access-tailscale-vs-cloudflare-tunnel/" data-link-title="7.C11 選型：單人遠端 Shell — Tailscale vs Cloudflare Tunnel" data-link-desc="以「手機遠端操作本機 shell」為情境，比較 Tailscale mesh VPN 與 Cloudflare Tunnel &amp;#43; Access 兩種存取模型的選型判讀。">7.C11 Tailscale vs Cloudflare Tunnel&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Outbound tunnel 是一種入口形態：本機進程主動對外連到邊緣節點，把流量沿反向隧道帶回來，路由器零開 port、對公網零入站面。跟傳統 port-forward（從外往內開 port）的責任方向相反 — 連線由內部發起、外部只能沿已建立的隧道回來。與 <a href="/blog/backend/knowledge-cards/load-balancer/" data-link-title="Load Balancer" data-link-desc="說明流量如何分散、排空與導向健康節點">load balancer</a> 的責任方向不同：LB 假設 instance 有公開可達位址，tunnel 由內部主動外連。</p>
<h2 id="概念位置">概念位置</h2>
<p>Outbound tunnel 位在本機進程與公網之間，取代傳統的 port-forward 或 <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/tls-mtls/" data-link-title="TLS / mTLS" data-link-desc="說明傳輸加密與雙向憑證驗證如何保護跨邊界資料流">TLS / mTLS</a> 搭配保護隧道內的傳輸安全，認證則疊在 tunnel 之後由 <a href="/blog/backend/knowledge-cards/authentication-middleware/" data-link-title="Authentication Middleware" data-link-desc="說明請求進入 handler 前如何完成身份驗證">authentication middleware</a> 處理。</p>
<p>常見實作包括 cloudflared（綁 Cloudflare 邊緣）和 Tailscale（WireGuard mesh VPN）。隧道網址是位址、不是密碼 — 認證必須疊在 tunnel 之後。</p>
<p>深入：<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>。選型案例：<a href="/blog/backend/07-security-data-protection/cases/remote-shell-access-tailscale-vs-cloudflare-tunnel/" data-link-title="7.C11 選型：單人遠端 Shell — Tailscale vs Cloudflare Tunnel" data-link-desc="以「手機遠端操作本機 shell」為情境，比較 Tailscale mesh VPN 與 Cloudflare Tunnel &#43; Access 兩種存取模型的選型判讀。">7.C11 Tailscale vs Cloudflare Tunnel</a>。</p>
]]></content:encoded></item><item><title>Type Affinity</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/type-affinity/</link><pubDate>Fri, 22 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/type-affinity/</guid><description>&lt;p>Type Affinity 的核心概念是 SQLite 的型別模型 — 欄位宣告的型別是一個「傾向」，SQLite 依這個傾向決定存入的值如何被轉換與儲存，硬約束的心智模型在此不適用。它讓 SQLite 的 schema 比嚴格型別資料庫更寬鬆，代價是要理解值實際被存成什麼。理解它對寫對 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">Schema Migration&lt;/a> 與查詢很關鍵。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Type Affinity 位在 SQLite 的資料模型核心，和嚴格靜態型別的資料庫相對。多數關聯式資料庫的欄位型別是硬約束，存錯型別會被拒絕；SQLite 的欄位有 type affinity，值會被儘量依 affinity 轉換、也允許存入不同 storage class。它和 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/document-store/" data-link-title="Document Store" data-link-desc="說明以 JSON 文件與彈性 schema 提供資料存取的模式，以及它仍需的治理邊界">Document Store&lt;/a> 的彈性 schema 是不同來源的彈性 — 一個是型別寬鬆、一個是結構寬鬆。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要理解 type affinity 的訊號是查詢結果的型別或排序不如預期，或同一欄位混進了數字與字串。常見場景是把數字以字串存入，比較與排序就按字串規則跑；或預期欄位是整數、實際存進了文字。SQLite 的 STRICT table 可以把欄位改回硬約束，讓行為更接近傳統資料庫。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 schema 時要清楚每個欄位的 type affinity、以及值會如何被轉換。需要嚴格型別保證時，要明確選用 STRICT table 或在應用層驗證。測試 fixture 要涵蓋型別邊界，避免「本機測試剛好都存對型別」掩蓋問題。&lt;/p></description><content:encoded><![CDATA[<p>Type Affinity 的核心概念是 SQLite 的型別模型 — 欄位宣告的型別是一個「傾向」，SQLite 依這個傾向決定存入的值如何被轉換與儲存，硬約束的心智模型在此不適用。它讓 SQLite 的 schema 比嚴格型別資料庫更寬鬆，代價是要理解值實際被存成什麼。理解它對寫對 <a href="/blog/backend/knowledge-cards/schema-migration/" data-link-title="Schema Migration" data-link-desc="說明資料庫結構如何隨應用程式版本安全演進">Schema Migration</a> 與查詢很關鍵。</p>
<h2 id="概念位置">概念位置</h2>
<p>Type Affinity 位在 SQLite 的資料模型核心，和嚴格靜態型別的資料庫相對。多數關聯式資料庫的欄位型別是硬約束，存錯型別會被拒絕；SQLite 的欄位有 type affinity，值會被儘量依 affinity 轉換、也允許存入不同 storage class。它和 <a href="/blog/backend/knowledge-cards/document-store/" data-link-title="Document Store" data-link-desc="說明以 JSON 文件與彈性 schema 提供資料存取的模式，以及它仍需的治理邊界">Document Store</a> 的彈性 schema 是不同來源的彈性 — 一個是型別寬鬆、一個是結構寬鬆。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要理解 type affinity 的訊號是查詢結果的型別或排序不如預期，或同一欄位混進了數字與字串。常見場景是把數字以字串存入，比較與排序就按字串規則跑；或預期欄位是整數、實際存進了文字。SQLite 的 STRICT table 可以把欄位改回硬約束，讓行為更接近傳統資料庫。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 schema 時要清楚每個欄位的 type affinity、以及值會如何被轉換。需要嚴格型別保證時，要明確選用 STRICT table 或在應用層驗證。測試 fixture 要涵蓋型別邊界，避免「本機測試剛好都存對型別」掩蓋問題。</p>
]]></content:encoded></item><item><title>Distributed Lock</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-lock/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-lock/</guid><description>&lt;p>Distributed lock 的核心責任是讓分散式系統中多個 process 對共享資源做互斥存取。比單機 mutex 多一層責任：要處理 holder 失效（process crash、network partition）後鎖的自動釋放 — 解法是 lease（租約）：持鎖 process 必須定期 renew、未 renew 時鎖自動過期。底層通常依賴 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consensus-protocol/" data-link-title="Consensus Protocol" data-link-desc="讓多個獨立節點在訊息可能延遲、丟失、亂序的網路下對單一決策達成一致的演算法">consensus protocol&lt;/a> 保證跨節點對「誰持鎖」達成一致、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/leader-election/" data-link-title="Leader Election" data-link-desc="從一群對等節點中選出單一主節點負責獨佔工作、leader 失效時自動選新 leader">leader election&lt;/a> 區分在「資源互斥 vs 角色互斥」兩種使用情境。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Distributed lock 處於分散式協調控制層、底層通常依賴 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consensus-protocol/" data-link-title="Consensus Protocol" data-link-desc="讓多個獨立節點在訊息可能延遲、丟失、亂序的網路下對單一決策達成一致的演算法">consensus protocol&lt;/a>。常見實作載體：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Redis SET NX + EX&lt;/strong>：簡單 lease lock、Redlock 算法嘗試強化但仍有爭議&lt;/li>
&lt;li>&lt;strong>ZooKeeper / Etcd / Consul&lt;/strong>：consensus 底層、提供強一致性保證、適合長期鎖&lt;/li>
&lt;li>&lt;strong>資料庫層&lt;/strong>：PostgreSQL advisory lock、MySQL &lt;code>GET_LOCK()&lt;/code> — 跟業務 transaction 同源、但跟 DB primary 綁定&lt;/li>
&lt;/ul>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>典型使用情境包含分散式 cache build（cache miss 時讓單一 process 打 origin、配合 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">cache stampede&lt;/a> 防護）、migration / cleanup job 確保單一 instance 執行、確保兩個 worker 處理不同訂單。實測 Redis lock acquire latency 毫秒級、Etcd / ZK 跨 region 可達 10-50ms — 高頻短鎖通常改用 partition / sharding、是更省 lock 的設計。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Fencing token 是必備設計 — 用單調遞增 token 在舊 holder 跟新 holder 並存時、讓資源側拒絕舊 holder 的寫入、防範 clock drift 或 long GC pause 導致的隱性鎖失效。Renew loop 要在 background 確認 renew 成功、若 network 卡住未及時拋錯、process 會自信操作其租約已失效的資源。Lease 期間應縮短 critical section、保持操作時間遠小於 lease timeout。&lt;/p></description><content:encoded><![CDATA[<p>Distributed lock 的核心責任是讓分散式系統中多個 process 對共享資源做互斥存取。比單機 mutex 多一層責任：要處理 holder 失效（process crash、network partition）後鎖的自動釋放 — 解法是 lease（租約）：持鎖 process 必須定期 renew、未 renew 時鎖自動過期。底層通常依賴 <a href="/blog/backend/knowledge-cards/consensus-protocol/" data-link-title="Consensus Protocol" data-link-desc="讓多個獨立節點在訊息可能延遲、丟失、亂序的網路下對單一決策達成一致的演算法">consensus protocol</a> 保證跨節點對「誰持鎖」達成一致、跟 <a href="/blog/backend/knowledge-cards/leader-election/" data-link-title="Leader Election" data-link-desc="從一群對等節點中選出單一主節點負責獨佔工作、leader 失效時自動選新 leader">leader election</a> 區分在「資源互斥 vs 角色互斥」兩種使用情境。</p>
<h2 id="概念位置">概念位置</h2>
<p>Distributed lock 處於分散式協調控制層、底層通常依賴 <a href="/blog/backend/knowledge-cards/consensus-protocol/" data-link-title="Consensus Protocol" data-link-desc="讓多個獨立節點在訊息可能延遲、丟失、亂序的網路下對單一決策達成一致的演算法">consensus protocol</a>。常見實作載體：</p>
<ul>
<li><strong>Redis SET NX + EX</strong>：簡單 lease lock、Redlock 算法嘗試強化但仍有爭議</li>
<li><strong>ZooKeeper / Etcd / Consul</strong>：consensus 底層、提供強一致性保證、適合長期鎖</li>
<li><strong>資料庫層</strong>：PostgreSQL advisory lock、MySQL <code>GET_LOCK()</code> — 跟業務 transaction 同源、但跟 DB primary 綁定</li>
</ul>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>典型使用情境包含分散式 cache build（cache miss 時讓單一 process 打 origin、配合 <a href="/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">cache stampede</a> 防護）、migration / cleanup job 確保單一 instance 執行、確保兩個 worker 處理不同訂單。實測 Redis lock acquire latency 毫秒級、Etcd / ZK 跨 region 可達 10-50ms — 高頻短鎖通常改用 partition / sharding、是更省 lock 的設計。</p>
<h2 id="設計責任">設計責任</h2>
<p>Fencing token 是必備設計 — 用單調遞增 token 在舊 holder 跟新 holder 並存時、讓資源側拒絕舊 holder 的寫入、防範 clock drift 或 long GC pause 導致的隱性鎖失效。Renew loop 要在 background 確認 renew 成功、若 network 卡住未及時拋錯、process 會自信操作其租約已失效的資源。Lease 期間應縮短 critical section、保持操作時間遠小於 lease timeout。</p>
]]></content:encoded></item><item><title>Connection Pooler</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pooler/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pooler/</guid><description>&lt;p>Connection pooler 的核心責任是讓部署在應用層跟資料庫之間的中介層、把多個應用層連線複用到少數 DB backend 連線上。解水平擴展應用層時「100 臺機器 × 每臺 10 連線 = 1000 個 DB 連線、超過 &lt;code>max_connections&lt;/code> 十倍」這個常見問題。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&lt;/a> 是不同層 — 後者在 application instance 內、本卡是跨 instance 共享層。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Connection pooler 在 DB topology 中是「應用層跟 DB 之間的 multiplexer 層」、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool&lt;/a> 是不同層。常見實作：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>PgBouncer&lt;/strong>（PostgreSQL）：輕量 single-process、三種 pool_mode（session / transaction / statement）&lt;/li>
&lt;li>&lt;strong>AWS RDS Proxy&lt;/strong>（PostgreSQL / MySQL）：managed 版本、整合 IAM auth、failover 加速&lt;/li>
&lt;li>&lt;strong>ProxySQL&lt;/strong>（MySQL）：規則型 routing + connection pooling + query rewriting&lt;/li>
&lt;li>&lt;strong>PgCat&lt;/strong>（PostgreSQL）：Rust 寫的 PgBouncer 替代、支援 sharding&lt;/li>
&lt;/ul>
&lt;p>PgBouncer 的 &lt;code>pool_mode&lt;/code> 是核心配置：session mode 嚴格說屬 connection caching（單 client 跟 backend 1:1 綁定整個 session）；transaction mode 是多數場景的 default、但限於不依賴 transaction-scoped state 的應用（&lt;code>SET LOCAL&lt;/code>、prepared statement、temp table 在 transaction mode 下會丟失）；statement mode 限於純無狀態 query workload、極少用。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>該裝 pooler 的訊號：應用層機器數 ≥ 20、每臺機器連線數 ≥ 10、DB &lt;code>max_connections&lt;/code> 使用率 ≥ 70%、P99 connection wait time 升高。&lt;code>pg_stat_activity&lt;/code> 顯示大量 idle 連線是裝 pooler 的明確指標。中型 PostgreSQL 服務裝 PgBouncer 後、DB 連線數常從 1000+ 壓到 50-100。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選 PgBouncer 自管要付 HA / failover / 監控的運維成本；選 RDS Proxy 換掉運維、付 per vCPU 計價。Transaction mode 配置前要 audit ORM / driver 行為 — JDBC / asyncpg 的 default prepared statement 跟 transaction mode 衝突、要明示配置 protocol-level prepared statement 或改寫成 inline parameter。Pooler 解的是連線數放大、N+1 query 屬另一層議題 — 兩個問題正交、各自要解。&lt;/p></description><content:encoded><![CDATA[<p>Connection pooler 的核心責任是讓部署在應用層跟資料庫之間的中介層、把多個應用層連線複用到少數 DB backend 連線上。解水平擴展應用層時「100 臺機器 × 每臺 10 連線 = 1000 個 DB 連線、超過 <code>max_connections</code> 十倍」這個常見問題。跟 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a> 是不同層 — 後者在 application instance 內、本卡是跨 instance 共享層。</p>
<h2 id="概念位置">概念位置</h2>
<p>Connection pooler 在 DB topology 中是「應用層跟 DB 之間的 multiplexer 層」、跟 <a href="/blog/backend/knowledge-cards/connection-pool/" data-link-title="Connection Pool" data-link-desc="說明連線池如何限制下游資源並影響服務容量">connection pool</a> 是不同層。常見實作：</p>
<ul>
<li><strong>PgBouncer</strong>（PostgreSQL）：輕量 single-process、三種 pool_mode（session / transaction / statement）</li>
<li><strong>AWS RDS Proxy</strong>（PostgreSQL / MySQL）：managed 版本、整合 IAM auth、failover 加速</li>
<li><strong>ProxySQL</strong>（MySQL）：規則型 routing + connection pooling + query rewriting</li>
<li><strong>PgCat</strong>（PostgreSQL）：Rust 寫的 PgBouncer 替代、支援 sharding</li>
</ul>
<p>PgBouncer 的 <code>pool_mode</code> 是核心配置：session mode 嚴格說屬 connection caching（單 client 跟 backend 1:1 綁定整個 session）；transaction mode 是多數場景的 default、但限於不依賴 transaction-scoped state 的應用（<code>SET LOCAL</code>、prepared statement、temp table 在 transaction mode 下會丟失）；statement mode 限於純無狀態 query workload、極少用。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>該裝 pooler 的訊號：應用層機器數 ≥ 20、每臺機器連線數 ≥ 10、DB <code>max_connections</code> 使用率 ≥ 70%、P99 connection wait time 升高。<code>pg_stat_activity</code> 顯示大量 idle 連線是裝 pooler 的明確指標。中型 PostgreSQL 服務裝 PgBouncer 後、DB 連線數常從 1000+ 壓到 50-100。</p>
<h2 id="設計責任">設計責任</h2>
<p>選 PgBouncer 自管要付 HA / failover / 監控的運維成本；選 RDS Proxy 換掉運維、付 per vCPU 計價。Transaction mode 配置前要 audit ORM / driver 行為 — JDBC / asyncpg 的 default prepared statement 跟 transaction mode 衝突、要明示配置 protocol-level prepared statement 或改寫成 inline parameter。Pooler 解的是連線數放大、N+1 query 屬另一層議題 — 兩個問題正交、各自要解。</p>
]]></content:encoded></item><item><title>Strangler Fig Pattern</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/strangler-fig/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/strangler-fig/</guid><description>&lt;p>Strangler Fig pattern 的核心責任是讓 legacy 系統替換成新系統的過程可控、用「新服務從舊 monolith 旁長出、流量逐步遷移、舊系統最終下架」取代 big bang 重寫。跟 big bang 的本質差異是失敗代價可控 — 大爆炸失敗就整個服務掛、Strangler 拆分失敗只影響該功能、可即時切回。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">dual write&lt;/a> 是組合關係（dual write 是 strangler 階段 2 的核心執行）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Strangler Fig 處於系統演進的策略層、是組合多種技術的執行框架。完整執行需要四階段：邊界冷凍 + Adapter 抽出（在 monolith 內封 interface）、新服務 + &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">dual write&lt;/a> 雙寫期（並驗證對賬）、切流（讀路徑逐步遷移、按 user ID hash / endpoint / dark launch 分流）、寫路徑遷移 + Monolith 退役（寫路徑切到新服務、舊系統 read-only、最後下架）。&lt;/p>
&lt;p>階段 4 是 point of no return — 過了寫路徑切換、新服務累積寫入、回 monolith 要 backfill 成本指數成長。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>大型 monolith 重寫、microservice 拆分、資料庫遷移、第三方 SaaS 換家都用 strangler。完整四階段通常 3-12 個月、雙寫期 1-4 週收斂、切流期 4-12 週逐步推進。Routing layer（API gateway / proxy / feature flag）是核心基礎設施、決定每個 request 走新或舊、出問題能瞬間切回。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>每階段都要有明示的回退條件跟成本評估 — 階段 1-3 回退代價低、階段 4 之後成本指數成長、要把 monolith 下架時點延後到「確信回退已罕見」、寧可多保留 monolith 1-2 個月。Monolith 下架前用 access log audit 確認真實流量為 0、確保 batch job / report / 內部 tool 都已切換。觀察期是硬要求 — 讀切完後至少 2 週觀察、確認穩定再進階段 4。&lt;/p></description><content:encoded><![CDATA[<p>Strangler Fig pattern 的核心責任是讓 legacy 系統替換成新系統的過程可控、用「新服務從舊 monolith 旁長出、流量逐步遷移、舊系統最終下架」取代 big bang 重寫。跟 big bang 的本質差異是失敗代價可控 — 大爆炸失敗就整個服務掛、Strangler 拆分失敗只影響該功能、可即時切回。跟 <a href="/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">dual write</a> 是組合關係（dual write 是 strangler 階段 2 的核心執行）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Strangler Fig 處於系統演進的策略層、是組合多種技術的執行框架。完整執行需要四階段：邊界冷凍 + Adapter 抽出（在 monolith 內封 interface）、新服務 + <a href="/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">dual write</a> 雙寫期（並驗證對賬）、切流（讀路徑逐步遷移、按 user ID hash / endpoint / dark launch 分流）、寫路徑遷移 + Monolith 退役（寫路徑切到新服務、舊系統 read-only、最後下架）。</p>
<p>階段 4 是 point of no return — 過了寫路徑切換、新服務累積寫入、回 monolith 要 backfill 成本指數成長。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>大型 monolith 重寫、microservice 拆分、資料庫遷移、第三方 SaaS 換家都用 strangler。完整四階段通常 3-12 個月、雙寫期 1-4 週收斂、切流期 4-12 週逐步推進。Routing layer（API gateway / proxy / feature flag）是核心基礎設施、決定每個 request 走新或舊、出問題能瞬間切回。</p>
<h2 id="設計責任">設計責任</h2>
<p>每階段都要有明示的回退條件跟成本評估 — 階段 1-3 回退代價低、階段 4 之後成本指數成長、要把 monolith 下架時點延後到「確信回退已罕見」、寧可多保留 monolith 1-2 個月。Monolith 下架前用 access log audit 確認真實流量為 0、確保 batch job / report / 內部 tool 都已切換。觀察期是硬要求 — 讀切完後至少 2 週觀察、確認穩定再進階段 4。</p>
]]></content:encoded></item><item><title>Modular Monolith</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/modular-monolith/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/modular-monolith/</guid><description>&lt;p>Modular monolith 的核心責任是讓單一部署單位內維持明確的模組邊界、約束 dependency 走 interface。換取的是「monolith 的部署簡單」+「microservice 的邊界紀律」、收回兩個極端各自的代價。Shopify、Basecamp、Stack Overflow 是大規模長期維持的代表。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cell-based-architecture/" data-link-title="Cell-Based Architecture" data-link-desc="把系統拆成多個 isolated cell、控制 blast radius、跨 cell 共用標準介面">cell-based architecture&lt;/a> 沿不同維度拆分（cell-based 沿使用者群 / region 拆、modular monolith 沿業務功能拆內部）、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/strangler-fig/" data-link-title="Strangler Fig Pattern" data-link-desc="服務拆分 / 系統替換的漸進演進模式、用『新舊共存 &amp;#43; 逐步遷移 &amp;#43; 最終下架』取代 big bang 重寫">strangler fig&lt;/a> 是策略階段關係（modular monolith 是拆分前該先嘗試的中間態）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Modular monolith 處於系統架構演進的「中段」位置、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cell-based-architecture/" data-link-title="Cell-Based Architecture" data-link-desc="把系統拆成多個 isolated cell、控制 blast radius、跨 cell 共用標準介面">cell-based architecture&lt;/a> 沿不同維度拆分。模組化的具體做法包含：每個模組對外公開的 API 用 interface / port 定義、其他模組只能透過 interface 互動；每個模組擁有自己的 table / schema、跨模組查詢走 interface（取代直接 join）；用 lint rule / build tool 強制 dependency graph 是 DAG；模組可獨立 build / test、最終 deploy 仍是 monolithic。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合採用的訊號：業務複雜但團隊規模 5-30 人、部署複雜度敏感（不想維護多服務 ops）、流量 / 團隊 / 變更頻率邊界尚未強到需要拆服務、想為未來拆分做準備。Shopify 在 Rails monolith 內維持 component-based 邊界、Stack Overflow 用單一 ASP.NET monolith 服務全球流量、Basecamp 拒絕 microservice 並 ship Modular Monolith 為長期 endgame。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>維持模組邊界需要團隊紀律 — 聲稱模組化但實際 import 散落各處、就退化成普通 monolith。要在 CI 強制 dependency 方向、用工具補位 review 自律。早期團隊（3 人以下）強迫每個 feature 都用嚴格 interface、會增加實作摩擦但無收益。當多團隊發布節奏完全不同、或流量 / 資源需求差距大、就到強制拆服務時機、應該主動往 microservice 推進。&lt;/p></description><content:encoded><![CDATA[<p>Modular monolith 的核心責任是讓單一部署單位內維持明確的模組邊界、約束 dependency 走 interface。換取的是「monolith 的部署簡單」+「microservice 的邊界紀律」、收回兩個極端各自的代價。Shopify、Basecamp、Stack Overflow 是大規模長期維持的代表。跟 <a href="/blog/backend/knowledge-cards/cell-based-architecture/" data-link-title="Cell-Based Architecture" data-link-desc="把系統拆成多個 isolated cell、控制 blast radius、跨 cell 共用標準介面">cell-based architecture</a> 沿不同維度拆分（cell-based 沿使用者群 / region 拆、modular monolith 沿業務功能拆內部）、跟 <a href="/blog/backend/knowledge-cards/strangler-fig/" data-link-title="Strangler Fig Pattern" data-link-desc="服務拆分 / 系統替換的漸進演進模式、用『新舊共存 &#43; 逐步遷移 &#43; 最終下架』取代 big bang 重寫">strangler fig</a> 是策略階段關係（modular monolith 是拆分前該先嘗試的中間態）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Modular monolith 處於系統架構演進的「中段」位置、跟 <a href="/blog/backend/knowledge-cards/cell-based-architecture/" data-link-title="Cell-Based Architecture" data-link-desc="把系統拆成多個 isolated cell、控制 blast radius、跨 cell 共用標準介面">cell-based architecture</a> 沿不同維度拆分。模組化的具體做法包含：每個模組對外公開的 API 用 interface / port 定義、其他模組只能透過 interface 互動；每個模組擁有自己的 table / schema、跨模組查詢走 interface（取代直接 join）；用 lint rule / build tool 強制 dependency graph 是 DAG；模組可獨立 build / test、最終 deploy 仍是 monolithic。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合採用的訊號：業務複雜但團隊規模 5-30 人、部署複雜度敏感（不想維護多服務 ops）、流量 / 團隊 / 變更頻率邊界尚未強到需要拆服務、想為未來拆分做準備。Shopify 在 Rails monolith 內維持 component-based 邊界、Stack Overflow 用單一 ASP.NET monolith 服務全球流量、Basecamp 拒絕 microservice 並 ship Modular Monolith 為長期 endgame。</p>
<h2 id="設計責任">設計責任</h2>
<p>維持模組邊界需要團隊紀律 — 聲稱模組化但實際 import 散落各處、就退化成普通 monolith。要在 CI 強制 dependency 方向、用工具補位 review 自律。早期團隊（3 人以下）強迫每個 feature 都用嚴格 interface、會增加實作摩擦但無收益。當多團隊發布節奏完全不同、或流量 / 資源需求差距大、就到強制拆服務時機、應該主動往 microservice 推進。</p>
]]></content:encoded></item><item><title>Query Cardinality Explosion</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cardinality-explosion/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cardinality-explosion/</guid><description>&lt;p>Query cardinality explosion 的核心責任是命名「query 結果行數遠超業務直覺」這類反模式 — 通常源於多對多 join 缺 filter、或誤用 cross join。一個應該回 100 行的 query 變成回 10000 行（10000 × M）、應用層拉回 deserialize 後記憶體爆掉、DB 也付出大量的 scan + serialization 成本。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/keyset-pagination/" data-link-title="Keyset Pagination" data-link-desc="用上一頁最後一筆的 key 當下一頁起點、避開 OFFSET 大表時的線性退化">keyset pagination&lt;/a> 是 query 結果集大小判讀的雙刃 — cardinality 處理「join 行數失控的爆量」、keyset 處理「offset 跳行的線性退化」、修法方向不同但同屬 result-set sizing 維度。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cardinality explosion 處於 SQL query 設計的「結果集大小判讀」維度、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/keyset-pagination/" data-link-title="Keyset Pagination" data-link-desc="用上一頁最後一筆的 key 當下一頁起點、避開 OFFSET 大表時的線性退化">keyset pagination&lt;/a> 都是大表查詢反模式修法。常見成因：多對多 join 缺 filter（100 訂單 × 10 item × 5 tag × 5 評論 = 25000 行）、誤用 CROSS JOIN（漏 JOIN 條件、結果是 N × M 笛卡兒積）、遞迴 CTE 缺終止條件（可能跑出百萬行）。&lt;/p>
&lt;p>本卡專指 query result-set 行數爆、跟 metric cardinality（time-series 維度爆）是兩個獨立議題、各自獨立成卡。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>業務上預期回 100 行、實際拿到 10000+ 行；&lt;code>EXPLAIN&lt;/code> 估計 rows 跟實際表大小有數量級落差；應用層記憶體用量隨流量線性升高、但 QPS 增速明顯低於記憶體增速；同樣的 query 在小資料量正常、大資料量 query 變慢且記憶體爆。電商訂單列表頁、報表查詢、後台搜尋是高發場景。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>修法方向：拆 query（先拿主資源、再用 IN 條件批次取相關資源、從 join 改成 N+1 但 N 可控）；用 EXISTS / 半連接取代 JOIN（只判斷存在性的場景、&lt;code>WHERE EXISTS (...)&lt;/code> 比 join 便宜）；明確 LIMIT（大資料量 query 強制加 limit）；重新評估資料模型（頻繁出現代表表關係設計過度正規化）。CI 加 query result size middleware、超過閾值觸發 review 比事後從 slow log 找問題早。&lt;/p></description><content:encoded><![CDATA[<p>Query cardinality explosion 的核心責任是命名「query 結果行數遠超業務直覺」這類反模式 — 通常源於多對多 join 缺 filter、或誤用 cross join。一個應該回 100 行的 query 變成回 10000 行（10000 × M）、應用層拉回 deserialize 後記憶體爆掉、DB 也付出大量的 scan + serialization 成本。跟 <a href="/blog/backend/knowledge-cards/keyset-pagination/" data-link-title="Keyset Pagination" data-link-desc="用上一頁最後一筆的 key 當下一頁起點、避開 OFFSET 大表時的線性退化">keyset pagination</a> 是 query 結果集大小判讀的雙刃 — cardinality 處理「join 行數失控的爆量」、keyset 處理「offset 跳行的線性退化」、修法方向不同但同屬 result-set sizing 維度。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cardinality explosion 處於 SQL query 設計的「結果集大小判讀」維度、跟 <a href="/blog/backend/knowledge-cards/keyset-pagination/" data-link-title="Keyset Pagination" data-link-desc="用上一頁最後一筆的 key 當下一頁起點、避開 OFFSET 大表時的線性退化">keyset pagination</a> 都是大表查詢反模式修法。常見成因：多對多 join 缺 filter（100 訂單 × 10 item × 5 tag × 5 評論 = 25000 行）、誤用 CROSS JOIN（漏 JOIN 條件、結果是 N × M 笛卡兒積）、遞迴 CTE 缺終止條件（可能跑出百萬行）。</p>
<p>本卡專指 query result-set 行數爆、跟 metric cardinality（time-series 維度爆）是兩個獨立議題、各自獨立成卡。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>業務上預期回 100 行、實際拿到 10000+ 行；<code>EXPLAIN</code> 估計 rows 跟實際表大小有數量級落差；應用層記憶體用量隨流量線性升高、但 QPS 增速明顯低於記憶體增速；同樣的 query 在小資料量正常、大資料量 query 變慢且記憶體爆。電商訂單列表頁、報表查詢、後台搜尋是高發場景。</p>
<h2 id="設計責任">設計責任</h2>
<p>修法方向：拆 query（先拿主資源、再用 IN 條件批次取相關資源、從 join 改成 N+1 但 N 可控）；用 EXISTS / 半連接取代 JOIN（只判斷存在性的場景、<code>WHERE EXISTS (...)</code> 比 join 便宜）；明確 LIMIT（大資料量 query 強制加 limit）；重新評估資料模型（頻繁出現代表表關係設計過度正規化）。CI 加 query result size middleware、超過閾值觸發 review 比事後從 slow log 找問題早。</p>
]]></content:encoded></item><item><title>Keyset Pagination</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/keyset-pagination/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/keyset-pagination/</guid><description>&lt;p>Keyset pagination（也稱 cursor pagination）的核心責任是讓大表分頁性能穩定在 O(LIMIT)、跟 offset 大小解耦。傳統 &lt;code>LIMIT 20 OFFSET 10000&lt;/code> 在大表退化成「掃描 10020 行 + skip 10000 行」、是 O(OFFSET + LIMIT)；keyset 寫成 &lt;code>WHERE id &amp;gt; last_seen_id LIMIT 20&lt;/code>、永遠是 O(LIMIT)、跟 offset 大小無關。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cardinality-explosion/" data-link-title="Query Cardinality Explosion" data-link-desc="Query 結果行數因 join / cross product / 條件缺失爆炸性放大的反模式">query cardinality explosion&lt;/a> 同屬大表查詢反模式修法、機制各自獨立。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Keyset pagination 處於 SQL query 設計的「pagination 策略」維度、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cardinality-explosion/" data-link-title="Query Cardinality Explosion" data-link-desc="Query 結果行數因 join / cross product / 條件缺失爆炸性放大的反模式">query cardinality explosion&lt;/a> 是 sibling 反模式修法。對比：&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>OFFSET-based&lt;/td>
 &lt;td>&lt;code>LIMIT 20 OFFSET 10000&lt;/code>&lt;/td>
 &lt;td>O(offset+limit)&lt;/td>
 &lt;td>大表線性退化、deep pagination 退化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Keyset&lt;/td>
 &lt;td>&lt;code>WHERE id &amp;gt; last_seen_id LIMIT 20&lt;/code>&lt;/td>
 &lt;td>O(limit)&lt;/td>
 &lt;td>限於順序逐頁、跳頁需另設計&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>該採用的訊號：排序欄位是 indexed + unique（或加 tiebreaker 確保唯一）、使用者操作是「逐頁前進」（next / load more）、大表（百萬 row 以上）需要分頁。Twitter timeline、Slack 訊息歷史、GitHub commit 列表都用 keyset。實測大表 deep pagination 場景 keyset 比 OFFSET 快數百倍 — OFFSET 100000 的 query 從秒級降到毫秒級。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>排序欄位若是非 unique（如 &lt;code>created_at&lt;/code>）、用 &lt;code>(created_at, id)&lt;/code> 複合條件確保穩定 — 缺 tiebreaker 時、重複值翻頁會跳過或重複資料。Cursor 編碼成 opaque token 給 client、避免暴露內部 ID 結構（也方便未來改 cursor 內容）。對「插入 / 刪除中翻頁」的行為比 OFFSET 穩定（OFFSET 在這類場景容易跳過或重複）。表小於 10000 行時 OFFSET 也快、保持簡單即可。Google 搜尋結果頁那種「跳到第 N 頁」需求要回到 OFFSET 或考慮重新設計使用者操作。&lt;/p></description><content:encoded><![CDATA[<p>Keyset pagination（也稱 cursor pagination）的核心責任是讓大表分頁性能穩定在 O(LIMIT)、跟 offset 大小解耦。傳統 <code>LIMIT 20 OFFSET 10000</code> 在大表退化成「掃描 10020 行 + skip 10000 行」、是 O(OFFSET + LIMIT)；keyset 寫成 <code>WHERE id &gt; last_seen_id LIMIT 20</code>、永遠是 O(LIMIT)、跟 offset 大小無關。跟 <a href="/blog/backend/knowledge-cards/cardinality-explosion/" data-link-title="Query Cardinality Explosion" data-link-desc="Query 結果行數因 join / cross product / 條件缺失爆炸性放大的反模式">query cardinality explosion</a> 同屬大表查詢反模式修法、機制各自獨立。</p>
<h2 id="概念位置">概念位置</h2>
<p>Keyset pagination 處於 SQL query 設計的「pagination 策略」維度、跟 <a href="/blog/backend/knowledge-cards/cardinality-explosion/" data-link-title="Query Cardinality Explosion" data-link-desc="Query 結果行數因 join / cross product / 條件缺失爆炸性放大的反模式">query cardinality explosion</a> 是 sibling 反模式修法。對比：</p>
<table>
  <thead>
      <tr>
          <th>策略</th>
          <th>寫法</th>
          <th>複雜度</th>
          <th>限制</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>OFFSET-based</td>
          <td><code>LIMIT 20 OFFSET 10000</code></td>
          <td>O(offset+limit)</td>
          <td>大表線性退化、deep pagination 退化</td>
      </tr>
      <tr>
          <td>Keyset</td>
          <td><code>WHERE id &gt; last_seen_id LIMIT 20</code></td>
          <td>O(limit)</td>
          <td>限於順序逐頁、跳頁需另設計</td>
      </tr>
  </tbody>
</table>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>該採用的訊號：排序欄位是 indexed + unique（或加 tiebreaker 確保唯一）、使用者操作是「逐頁前進」（next / load more）、大表（百萬 row 以上）需要分頁。Twitter timeline、Slack 訊息歷史、GitHub commit 列表都用 keyset。實測大表 deep pagination 場景 keyset 比 OFFSET 快數百倍 — OFFSET 100000 的 query 從秒級降到毫秒級。</p>
<h2 id="設計責任">設計責任</h2>
<p>排序欄位若是非 unique（如 <code>created_at</code>）、用 <code>(created_at, id)</code> 複合條件確保穩定 — 缺 tiebreaker 時、重複值翻頁會跳過或重複資料。Cursor 編碼成 opaque token 給 client、避免暴露內部 ID 結構（也方便未來改 cursor 內容）。對「插入 / 刪除中翻頁」的行為比 OFFSET 穩定（OFFSET 在這類場景容易跳過或重複）。表小於 10000 行時 OFFSET 也快、保持簡單即可。Google 搜尋結果頁那種「跳到第 N 頁」需求要回到 OFFSET 或考慮重新設計使用者操作。</p>
]]></content:encoded></item><item><title>Cache Tag Purge</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-tag-purge/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-tag-purge/</guid><description>&lt;p>Cache tag purge（也稱 surrogate key purge）的核心責任是讓 CDN / cache 批量失效操作可控 — 寫入快取時除了 cache key 還附加多個 tag；purge 時用 tag 觸發、一次失效所有帶該 tag 的資源、用單一 tag 取代逐個 cache key 列舉。是大型內容系統的事實標準 — 比版本化路徑通用、比逐個 purge 可控。跟 &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> 是執行手段關係（cache invalidation 規定「何時清」、本卡提供「怎麼批量清」）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cache tag purge 處於 CDN / cache 失效策略的「批量失效機制」層、是 &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> 的執行手段。常見 vendor 實作：Fastly Cache Tag（&lt;code>Surrogate-Key&lt;/code> header、purge 用 &lt;code>POST /service/.../purge/&amp;lt;tag&amp;gt;&lt;/code>）、Cloudflare Cache Tag（Enterprise plan、用 &lt;code>Cache-Tag&lt;/code> header）、Akamai Surrogate Key、Varnish（用 &lt;code>X-Cache-Tag&lt;/code> header + ban-list）。&lt;/p>
&lt;p>CDN 用 cache key（通常是 URL + Vary header）做快取存取。批量失效的三條路是：逐個 URL purge（拿到所有受影響 URL 清單）、wildcard purge（粗、容易誤傷）、tag purge（寫入時就標 tag、失效時用 tag 觸發、精準批量）。tag purge 的優勢是失效範圍在寫入時就規劃好、屬「寫入時規劃」型 invalidation、跟 wildcard 的「事後猜」型對比。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>電商商品頁、相關搜尋、推薦 widget 都帶 &lt;code>product:123&lt;/code> tag、商品下架時 purge &lt;code>product:123&lt;/code> 一次清乾淨；新聞文章 + tag page + author page + RSS 都帶 &lt;code>article:456&lt;/code> tag、文章更新時批量失效相關頁；CMS 模組更新時、所有 reference 該模組的頁面用 &lt;code>template:hero-v2&lt;/code> tag 一次清。實測大型內容系統一次 tag purge 可影響數萬 cache entry、比逐個 purge 快數量級。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Tag 粒度設計要在兩端之間取捨：tag 太粗（所有頁面都帶 &lt;code>site:main&lt;/code> tag、每次小更新都全站 purge）、tag 太細（每個資源獨立 tag、batch purge 需要 enumerate 所有 tag、退化成逐個 purge）。Vendor 對 tag 數量、tag 長度、purge API rate 都有上限、要事前 audit。跨服務 tag 設計要同步 — 若 CDN 有 tag、應用層快取缺對應機制、CDN purge 後應用層仍 stale、會回填到 CDN。兩層失效要設計成同步協議、視為單一 invalidation pipeline。&lt;/p></description><content:encoded><![CDATA[<p>Cache tag purge（也稱 surrogate key purge）的核心責任是讓 CDN / cache 批量失效操作可控 — 寫入快取時除了 cache key 還附加多個 tag；purge 時用 tag 觸發、一次失效所有帶該 tag 的資源、用單一 tag 取代逐個 cache key 列舉。是大型內容系統的事實標準 — 比版本化路徑通用、比逐個 purge 可控。跟 <a href="/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">cache invalidation</a> 是執行手段關係（cache invalidation 規定「何時清」、本卡提供「怎麼批量清」）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cache tag purge 處於 CDN / cache 失效策略的「批量失效機制」層、是 <a href="/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">cache invalidation</a> 的執行手段。常見 vendor 實作：Fastly Cache Tag（<code>Surrogate-Key</code> header、purge 用 <code>POST /service/.../purge/&lt;tag&gt;</code>）、Cloudflare Cache Tag（Enterprise plan、用 <code>Cache-Tag</code> header）、Akamai Surrogate Key、Varnish（用 <code>X-Cache-Tag</code> header + ban-list）。</p>
<p>CDN 用 cache key（通常是 URL + Vary header）做快取存取。批量失效的三條路是：逐個 URL purge（拿到所有受影響 URL 清單）、wildcard purge（粗、容易誤傷）、tag purge（寫入時就標 tag、失效時用 tag 觸發、精準批量）。tag purge 的優勢是失效範圍在寫入時就規劃好、屬「寫入時規劃」型 invalidation、跟 wildcard 的「事後猜」型對比。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>電商商品頁、相關搜尋、推薦 widget 都帶 <code>product:123</code> tag、商品下架時 purge <code>product:123</code> 一次清乾淨；新聞文章 + tag page + author page + RSS 都帶 <code>article:456</code> tag、文章更新時批量失效相關頁；CMS 模組更新時、所有 reference 該模組的頁面用 <code>template:hero-v2</code> tag 一次清。實測大型內容系統一次 tag purge 可影響數萬 cache entry、比逐個 purge 快數量級。</p>
<h2 id="設計責任">設計責任</h2>
<p>Tag 粒度設計要在兩端之間取捨：tag 太粗（所有頁面都帶 <code>site:main</code> tag、每次小更新都全站 purge）、tag 太細（每個資源獨立 tag、batch purge 需要 enumerate 所有 tag、退化成逐個 purge）。Vendor 對 tag 數量、tag 長度、purge API rate 都有上限、要事前 audit。跨服務 tag 設計要同步 — 若 CDN 有 tag、應用層快取缺對應機制、CDN purge 後應用層仍 stale、會回填到 CDN。兩層失效要設計成同步協議、視為單一 invalidation pipeline。</p>
]]></content:encoded></item><item><title>Cell-Based Architecture</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cell-based-architecture/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cell-based-architecture/</guid><description>&lt;p>Cell-based architecture 的核心責任是 blast radius 控制 — 把整個系統拆成多個 isolated cell、每個 cell 內含完整 stack（front + back + data）、跨 cell 共用標準介面。任何一個 cell 的故障、最壞影響範圍是該 cell 的使用者群、不會跨 cell 擴散。AWS、Slack、DoorDash 採用這條模式。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/modular-monolith/" data-link-title="Modular Monolith" data-link-desc="單一部署單位 &amp;#43; 模組化內部邊界的架構、是 monolith 跟 microservice 之間的折衷形態">modular monolith&lt;/a> 跟 microservice 是不同維度的拆分（後兩者沿功能拆、cell-based 沿使用者群 / 區域 / tenant 拆）、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding&lt;/a> 同概念但不同層級（sharding 切資料、cell 切完整 stack）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cell-based architecture 處於系統架構的「失敗隔離」維度、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding&lt;/a> 同概念但不同層級（sharding 切資料、cell 切完整 stack）。常見 cell 切分軸：按地理 region（AWS 把每個 region 視為獨立 cell）、按 tenant（multi-tenant SaaS 把大客戶各放獨立 cell）、按 user shard（user ID hash 分到 N 個 cell）、按業務 vertical（DoorDash dispatch / payment / merchant 各 cell）。Cell-based 跟 microservice 可以組合：每個 cell 內部用 microservice、跨 cell 也用 microservice 通訊、但 cell 邊界是故障隔離的硬邊界。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合採用的訊號：規模到「全站事故代價」遠超「N 個 cell 維運成本」（通常每 cell 服務 10 萬+ 使用者才划算）、業務本質支援使用者分群、合規要求資料 / 流量地理隔離。AWS 用 cell 控制 region 級別的事故影響（每個 region 是獨立 cell）、Slack 用 cell 隔離大客戶事故、DoorDash 用 cell 切 dispatch / payment 業務 vertical。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Cell 路由層（API gateway / DNS / 負載均衡）決定 request 進哪個 cell、路由邏輯限於單 cell 內 — 防範 cell 間隱式依賴。資料邊界硬切：cell A 的資料庫跟 cell B 完全分離、跨 cell 查詢走標準 API。每 cell 獨立 deploy、rollout 一次只動一個 cell、出問題影響範圍可控。常見失敗：某個 shared service（如 user auth）所有 cell 都打、變成跨 cell 故障的單點 — 真正的 cell-based 連 auth 也要每 cell 獨立或設計成 read-only cache。&lt;/p></description><content:encoded><![CDATA[<p>Cell-based architecture 的核心責任是 blast radius 控制 — 把整個系統拆成多個 isolated cell、每個 cell 內含完整 stack（front + back + data）、跨 cell 共用標準介面。任何一個 cell 的故障、最壞影響範圍是該 cell 的使用者群、不會跨 cell 擴散。AWS、Slack、DoorDash 採用這條模式。跟 <a href="/blog/backend/knowledge-cards/modular-monolith/" data-link-title="Modular Monolith" data-link-desc="單一部署單位 &#43; 模組化內部邊界的架構、是 monolith 跟 microservice 之間的折衷形態">modular monolith</a> 跟 microservice 是不同維度的拆分（後兩者沿功能拆、cell-based 沿使用者群 / 區域 / tenant 拆）、跟 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding</a> 同概念但不同層級（sharding 切資料、cell 切完整 stack）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cell-based architecture 處於系統架構的「失敗隔離」維度、跟 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">database sharding</a> 同概念但不同層級（sharding 切資料、cell 切完整 stack）。常見 cell 切分軸：按地理 region（AWS 把每個 region 視為獨立 cell）、按 tenant（multi-tenant SaaS 把大客戶各放獨立 cell）、按 user shard（user ID hash 分到 N 個 cell）、按業務 vertical（DoorDash dispatch / payment / merchant 各 cell）。Cell-based 跟 microservice 可以組合：每個 cell 內部用 microservice、跨 cell 也用 microservice 通訊、但 cell 邊界是故障隔離的硬邊界。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合採用的訊號：規模到「全站事故代價」遠超「N 個 cell 維運成本」（通常每 cell 服務 10 萬+ 使用者才划算）、業務本質支援使用者分群、合規要求資料 / 流量地理隔離。AWS 用 cell 控制 region 級別的事故影響（每個 region 是獨立 cell）、Slack 用 cell 隔離大客戶事故、DoorDash 用 cell 切 dispatch / payment 業務 vertical。</p>
<h2 id="設計責任">設計責任</h2>
<p>Cell 路由層（API gateway / DNS / 負載均衡）決定 request 進哪個 cell、路由邏輯限於單 cell 內 — 防範 cell 間隱式依賴。資料邊界硬切：cell A 的資料庫跟 cell B 完全分離、跨 cell 查詢走標準 API。每 cell 獨立 deploy、rollout 一次只動一個 cell、出問題影響範圍可控。常見失敗：某個 shared service（如 user auth）所有 cell 都打、變成跨 cell 故障的單點 — 真正的 cell-based 連 auth 也要每 cell 獨立或設計成 read-only cache。</p>
]]></content:encoded></item><item><title>Freshness Token</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/freshness-token/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/freshness-token/</guid><description>&lt;p>Freshness token 的核心概念是「write 完成後 DB 返回一個版本 token、後續 read 帶這個 token、中間任何一層（cache / replica / proxy）必須回傳 ≥ token 版本的資料、否則 bypass 回 source of truth」。它的責任是把 read-after-write 一致性從單一 DB 內部、延伸到 application 跟 cache 之間的跨層協議。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/session-consistency/" data-link-title="Session Consistency" data-link-desc="同一使用者工作階段內維持讀寫一致、跨工作階段允許短暫不一致">Session Consistency&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Freshness token 出現在「application 在 DB 前面加 cache、但 cache 跟 DB 不同步」的場景。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/session-consistency/" data-link-title="Session Consistency" data-link-desc="同一使用者工作階段內維持讀寫一致、跨工作階段允許短暫不一致">Session Consistency&lt;/a> 區分：後者是 DB 內部的 causal session、保證同一 session 看得到自己剛寫的；freshness token 是跨層協議、把「保證讀到自己剛寫的」從 DB 內延伸到包含 cache 的整條 read path。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read&lt;/a> 是症狀與防護機制的對應 — stale read 是現象、freshness token 是用版本門檻防止它。跟 &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> 互補 — 後者由 write 端 push 失效、freshness token 由 read 端 pull 版本檢查、兩者可同時部署。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 freshness token 的訊號是「DB 寫成功、user 立刻 read、cache 還回舊資料」。&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/coinbase-mongodb-document-platform/" data-link-title="9.C36 Coinbase：MongoDB 撐 Ruby 單體 &amp;#43; 1.5M reads/sec identity 服務" data-link-desc="Coinbase 以 MongoDB 為主資料層、自建 mongobetween connection proxy、users 服務在加密貨幣 surge 時撐 1.5M reads/sec">9.C36 Coinbase MongoDB&lt;/a> 揭露具體機制：在 MongoDB + Memcached 三層架構下、users 服務直接撐 1.5M reads/sec（含 cache、users 服務應用層觀察口徑）。write 成功時 DB 返回 token（含 OCC version / clusterTime）、client 後續 read 帶 token、server 保證返回 ≥ token 版本、必要時 bypass cache 直接打 DB。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要先區分 token 的 &lt;em>語意層級&lt;/em> — 是 application 自行管理（如 Coinbase 自建協議、把 version 寫進 token）、還是 SDK 內建（如 Cosmos DB session token 自動跨 service 傳遞）。若同時部署多種 cache 層（CDN / application cache / DB read replica）、token 要能穿透所有層、否則最弱的一層會破壞保證。Token 過期或不可用時的 fallback 行為（bypass cache 直接讀 primary）要明示寫進設計、不能讓 user 在 token 失效時悄悄讀到舊資料。&lt;/p></description><content:encoded><![CDATA[<p>Freshness token 的核心概念是「write 完成後 DB 返回一個版本 token、後續 read 帶這個 token、中間任何一層（cache / replica / proxy）必須回傳 ≥ token 版本的資料、否則 bypass 回 source of truth」。它的責任是把 read-after-write 一致性從單一 DB 內部、延伸到 application 跟 cache 之間的跨層協議。可先對照 <a href="/blog/backend/knowledge-cards/session-consistency/" data-link-title="Session Consistency" data-link-desc="同一使用者工作階段內維持讀寫一致、跨工作階段允許短暫不一致">Session Consistency</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Freshness token 出現在「application 在 DB 前面加 cache、但 cache 跟 DB 不同步」的場景。跟 <a href="/blog/backend/knowledge-cards/session-consistency/" data-link-title="Session Consistency" data-link-desc="同一使用者工作階段內維持讀寫一致、跨工作階段允許短暫不一致">Session Consistency</a> 區分：後者是 DB 內部的 causal session、保證同一 session 看得到自己剛寫的；freshness token 是跨層協議、把「保證讀到自己剛寫的」從 DB 內延伸到包含 cache 的整條 read path。跟 <a href="/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read</a> 是症狀與防護機制的對應 — stale read 是現象、freshness token 是用版本門檻防止它。跟 <a href="/blog/backend/knowledge-cards/cache-invalidation/" data-link-title="Cache Invalidation" data-link-desc="說明快取資料何時更新、刪除或重建，以及失效策略如何影響一致性">Cache Invalidation</a> 互補 — 後者由 write 端 push 失效、freshness token 由 read 端 pull 版本檢查、兩者可同時部署。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 freshness token 的訊號是「DB 寫成功、user 立刻 read、cache 還回舊資料」。<a href="/blog/backend/09-performance-capacity/cases/coinbase-mongodb-document-platform/" data-link-title="9.C36 Coinbase：MongoDB 撐 Ruby 單體 &#43; 1.5M reads/sec identity 服務" data-link-desc="Coinbase 以 MongoDB 為主資料層、自建 mongobetween connection proxy、users 服務在加密貨幣 surge 時撐 1.5M reads/sec">9.C36 Coinbase MongoDB</a> 揭露具體機制：在 MongoDB + Memcached 三層架構下、users 服務直接撐 1.5M reads/sec（含 cache、users 服務應用層觀察口徑）。write 成功時 DB 返回 token（含 OCC version / clusterTime）、client 後續 read 帶 token、server 保證返回 ≥ token 版本、必要時 bypass cache 直接打 DB。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要先區分 token 的 <em>語意層級</em> — 是 application 自行管理（如 Coinbase 自建協議、把 version 寫進 token）、還是 SDK 內建（如 Cosmos DB session token 自動跨 service 傳遞）。若同時部署多種 cache 層（CDN / application cache / DB read replica）、token 要能穿透所有層、否則最弱的一層會破壞保證。Token 過期或不可用時的 fallback 行為（bypass cache 直接讀 primary）要明示寫進設計、不能讓 user 在 token 失效時悄悄讀到舊資料。</p>
]]></content:encoded></item><item><title>Leaseholder</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/leaseholder/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/leaseholder/</guid><description>&lt;p>Leaseholder 的核心概念是「distributed SQL 把 key space 切成多個 range、每個 range 在任一時間點有唯一一個 leaseholder 節點、承擔該 range 所有 read / write 的 coordination」。它的責任是把「誰來決定這個 range 的順序」這件事從 cluster-level 推到 per-range level、讓寫入吞吐可以線性分散。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consensus-protocol/" data-link-title="Consensus Protocol" data-link-desc="讓多個獨立節點在訊息可能延遲、丟失、亂序的網路下對單一決策達成一致的演算法">Consensus Protocol&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Leaseholder 出現在 CockroachDB / Spanner 等 distributed SQL 架構、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/consensus-protocol/" data-link-title="Consensus Protocol" data-link-desc="讓多個獨立節點在訊息可能延遲、丟失、亂序的網路下對單一決策達成一致的演算法">Consensus Protocol&lt;/a> 是抽象與落地的對應 — Raft / Paxos 是通用 consensus 機制、leaseholder 是 distributed SQL 把它落地成 per-range 的 entry point。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition&lt;/a> 對照：KV 系統的 hot partition 是物理 partition 流量集中、distributed SQL 是 leaseholder 集中在某節點、機制不同但容量影響類似。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/single-writer-model/" data-link-title="Single Writer Model" data-link-desc="說明單寫者模型如何序列化寫入，並成為系統的容量邊界">Single Writer Model&lt;/a> 區分：後者是 cluster-level 只有單一 primary 寫入、leaseholder 是 range-level 的 single writer、cluster 內每個 range 可以分散到不同節點。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 leaseholder 判讀的訊號是「整體 cluster CPU 不高、但某節點 p99 latency 飆 + 寫入 throughput 卡住」。&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/doordash-cockroachdb-orders-platform/" data-link-title="9.C39 DoorDash：Aurora Postgres 寫入瓶頸 → CockroachDB 多主寫入" data-link-desc="DoorDash 從 Aurora Postgres 遷到 CockroachDB、解 1.6 M QPS 單主寫入瓶頸、外送平台爆量壓力下重做 OLTP 拓樸">9.C39 DoorDash CockroachDB&lt;/a> 揭露 Aurora Postgres 撞牆後遷到 CockroachDB、寫入分散到 leaseholder 跟 Raft replica；&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/netflix-cockroachdb-multi-region-fleet/" data-link-title="9.C40 Netflix：380&amp;#43; CockroachDB cluster 的 multi-active 拓樸艦隊" data-link-desc="Netflix 把 Cassandra 不夠用的 transactional workload 移到 CockroachDB、380&amp;#43; cluster / 60&amp;#43; 跨 region、含 Open Connect、studio cloud drive、gaming control plane">9.C40 Netflix CockroachDB&lt;/a> 揭露 380+ cluster / 最大單區 60 nodes 規模、leaseholder placement 跟 locality config 直接決定 cross-region latency。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要主動把 leaseholder 分布納入 capacity planning — 不是只看 cluster 總 CPU、要看每個節點承擔多少 leaseholder。lease transfer（rebalance、節點 drain、failover）會引發短期 p99 spike、要寫進變更窗口跟 rollback 觀測點。region survival 配置下、voting replica 跨 region 強制提高 write latency、leaseholder placement 跟 locality tag 一致時才能拿到本地 read 紅利、否則跨 region 多跑一趟 RTT。&lt;/p></description><content:encoded><![CDATA[<p>Leaseholder 的核心概念是「distributed SQL 把 key space 切成多個 range、每個 range 在任一時間點有唯一一個 leaseholder 節點、承擔該 range 所有 read / write 的 coordination」。它的責任是把「誰來決定這個 range 的順序」這件事從 cluster-level 推到 per-range level、讓寫入吞吐可以線性分散。可先對照 <a href="/blog/backend/knowledge-cards/consensus-protocol/" data-link-title="Consensus Protocol" data-link-desc="讓多個獨立節點在訊息可能延遲、丟失、亂序的網路下對單一決策達成一致的演算法">Consensus Protocol</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Leaseholder 出現在 CockroachDB / Spanner 等 distributed SQL 架構、跟 <a href="/blog/backend/knowledge-cards/consensus-protocol/" data-link-title="Consensus Protocol" data-link-desc="讓多個獨立節點在訊息可能延遲、丟失、亂序的網路下對單一決策達成一致的演算法">Consensus Protocol</a> 是抽象與落地的對應 — Raft / Paxos 是通用 consensus 機制、leaseholder 是 distributed SQL 把它落地成 per-range 的 entry point。跟 <a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition</a> 對照：KV 系統的 hot partition 是物理 partition 流量集中、distributed SQL 是 leaseholder 集中在某節點、機制不同但容量影響類似。跟 <a href="/blog/backend/knowledge-cards/single-writer-model/" data-link-title="Single Writer Model" data-link-desc="說明單寫者模型如何序列化寫入，並成為系統的容量邊界">Single Writer Model</a> 區分：後者是 cluster-level 只有單一 primary 寫入、leaseholder 是 range-level 的 single writer、cluster 內每個 range 可以分散到不同節點。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 leaseholder 判讀的訊號是「整體 cluster CPU 不高、但某節點 p99 latency 飆 + 寫入 throughput 卡住」。<a href="/blog/backend/09-performance-capacity/cases/doordash-cockroachdb-orders-platform/" data-link-title="9.C39 DoorDash：Aurora Postgres 寫入瓶頸 → CockroachDB 多主寫入" data-link-desc="DoorDash 從 Aurora Postgres 遷到 CockroachDB、解 1.6 M QPS 單主寫入瓶頸、外送平台爆量壓力下重做 OLTP 拓樸">9.C39 DoorDash CockroachDB</a> 揭露 Aurora Postgres 撞牆後遷到 CockroachDB、寫入分散到 leaseholder 跟 Raft replica；<a href="/blog/backend/09-performance-capacity/cases/netflix-cockroachdb-multi-region-fleet/" data-link-title="9.C40 Netflix：380&#43; CockroachDB cluster 的 multi-active 拓樸艦隊" data-link-desc="Netflix 把 Cassandra 不夠用的 transactional workload 移到 CockroachDB、380&#43; cluster / 60&#43; 跨 region、含 Open Connect、studio cloud drive、gaming control plane">9.C40 Netflix CockroachDB</a> 揭露 380+ cluster / 最大單區 60 nodes 規模、leaseholder placement 跟 locality config 直接決定 cross-region latency。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要主動把 leaseholder 分布納入 capacity planning — 不是只看 cluster 總 CPU、要看每個節點承擔多少 leaseholder。lease transfer（rebalance、節點 drain、failover）會引發短期 p99 spike、要寫進變更窗口跟 rollback 觀測點。region survival 配置下、voting replica 跨 region 強制提高 write latency、leaseholder placement 跟 locality tag 一致時才能拿到本地 read 紅利、否則跨 region 多跑一趟 RTT。</p>
]]></content:encoded></item><item><title>Range Sharding</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/range-sharding/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/range-sharding/</guid><description>&lt;p>Range sharding 的核心概念是「distributed SQL 把整個 key space 依 key 順序切成多個 range、每個 range 有自己的 consensus group 跟 replica 分布、容量逼近 split 上限就自動分裂、application 看到的只是 SQL table」。它的責任是讓資料分散變成系統內建透明機制、不需要 application 端設計 shard key。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Range sharding 出現在 CockroachDB / Spanner 等 distributed SQL、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition&lt;/a> 必須區分 — partition 卡承擔事件流 / KV 風格的 hash partition 語意、range sharding 是 distributed SQL 系統內透明的 range-based 切分、兩者語意不同。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding&lt;/a> 區分：後者是 application-level 由開發者選 shard key 跟設計 routing、range sharding 是系統自動 split / merge 不需要 shard key。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/table-partitioning/" data-link-title="Table Partitioning" data-link-desc="說明單一資料庫內如何把大表拆成多個分區，並由查詢規劃器只掃相關片段">Table Partitioning&lt;/a> 區分：PostgreSQL declarative partition 是 single-node table 內的 partition、range sharding 是跨節點分散 + consensus 一起的機制。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 range sharding 概念的訊號是「設計 distributed SQL schema 時、誤把 KV 的 shard key 思維搬過來」。&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/netflix-cockroachdb-multi-region-fleet/" data-link-title="9.C40 Netflix：380&amp;#43; CockroachDB cluster 的 multi-active 拓樸艦隊" data-link-desc="Netflix 把 Cassandra 不夠用的 transactional workload 移到 CockroachDB、380&amp;#43; cluster / 60&amp;#43; 跨 region、含 Open Connect、studio cloud drive、gaming control plane">9.C40 Netflix CockroachDB&lt;/a> 揭露 range 預設 ~512MB 自動 split 的機制：380+ cluster / 最大單區 60 nodes / 26.5 TB、不需要 application 端做 shard 設計。&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Spanner&lt;/a> 也用類似機制、跟 interleaved table 配合做 parent-child 物理 co-location。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時不要把 KV partition key 設計的直覺套到 range sharding — 在 range sharding 下、hot range 仍會發生（連續寫入 monotonic key 例如 timestamp 會集中到同一 range）、但解法不是設 shard key、是讓 primary key 有 entropy（例如改用 UUID 或加 hash prefix）。range split 雖然自動、但 split 過程是 ops event、會引發短期 p99 spike、變更窗口要避開。多 region 部署下、range 的 replica placement 由 locality config 決定、預設不會自動把 replica 放到合規 region、要主動配置。&lt;/p></description><content:encoded><![CDATA[<p>Range sharding 的核心概念是「distributed SQL 把整個 key space 依 key 順序切成多個 range、每個 range 有自己的 consensus group 跟 replica 分布、容量逼近 split 上限就自動分裂、application 看到的只是 SQL table」。它的責任是讓資料分散變成系統內建透明機制、不需要 application 端設計 shard key。可先對照 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Range sharding 出現在 CockroachDB / Spanner 等 distributed SQL、跟 <a href="/blog/backend/knowledge-cards/partition/" data-link-title="Partition" data-link-desc="說明事件流如何切分成多個可並行處理的有序片段">Partition</a> 必須區分 — partition 卡承擔事件流 / KV 風格的 hash partition 語意、range sharding 是 distributed SQL 系統內透明的 range-based 切分、兩者語意不同。跟 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a> 區分：後者是 application-level 由開發者選 shard key 跟設計 routing、range sharding 是系統自動 split / merge 不需要 shard key。跟 <a href="/blog/backend/knowledge-cards/table-partitioning/" data-link-title="Table Partitioning" data-link-desc="說明單一資料庫內如何把大表拆成多個分區，並由查詢規劃器只掃相關片段">Table Partitioning</a> 區分：PostgreSQL declarative partition 是 single-node table 內的 partition、range sharding 是跨節點分散 + consensus 一起的機制。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 range sharding 概念的訊號是「設計 distributed SQL schema 時、誤把 KV 的 shard key 思維搬過來」。<a href="/blog/backend/09-performance-capacity/cases/netflix-cockroachdb-multi-region-fleet/" data-link-title="9.C40 Netflix：380&#43; CockroachDB cluster 的 multi-active 拓樸艦隊" data-link-desc="Netflix 把 Cassandra 不夠用的 transactional workload 移到 CockroachDB、380&#43; cluster / 60&#43; 跨 region、含 Open Connect、studio cloud drive、gaming control plane">9.C40 Netflix CockroachDB</a> 揭露 range 預設 ~512MB 自動 split 的機制：380+ cluster / 最大單區 60 nodes / 26.5 TB、不需要 application 端做 shard 設計。<a href="/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Spanner</a> 也用類似機制、跟 interleaved table 配合做 parent-child 物理 co-location。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時不要把 KV partition key 設計的直覺套到 range sharding — 在 range sharding 下、hot range 仍會發生（連續寫入 monotonic key 例如 timestamp 會集中到同一 range）、但解法不是設 shard key、是讓 primary key 有 entropy（例如改用 UUID 或加 hash prefix）。range split 雖然自動、但 split 過程是 ops event、會引發短期 p99 spike、變更窗口要避開。多 region 部署下、range 的 replica placement 由 locality config 決定、預設不會自動把 replica 放到合規 region、要主動配置。</p>
]]></content:encoded></item><item><title>Hybrid Logical Clock</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/hybrid-logical-clock/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/hybrid-logical-clock/</guid><description>&lt;p>Hybrid Logical Clock（HLC）的核心概念是「給每個事件一個 &lt;code>(physical, logical)&lt;/code> timestamp、physical 來自 NTP 同步的 wall clock、logical 是單調遞增的 counter 處理同一 physical tick 內的事件順序」。它的責任是讓跨節點 event ordering 可以用軟體保證、不需要 GPS + 原子鐘等專用硬體、代價是要承擔 max-offset 邊界內的不確定性。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/truetime/" data-link-title="TrueTime" data-link-desc="分散式資料庫用來界定時間不確定性的時間語意機制">TrueTime&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>HLC 出現在 CockroachDB 等不依賴專用硬體的 distributed SQL、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/truetime/" data-link-title="TrueTime" data-link-desc="分散式資料庫用來界定時間不確定性的時間語意機制">TrueTime&lt;/a> 是對照關係 — 兩者解同一個 event ordering 問題、HLC 用軟體 + NTP、TrueTime 用 GPS + 原子鐘。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">External Consistency&lt;/a> 互補但不等同：HLC 保證 linearizability、不保證 external consistency；TrueTime 加 commit-wait 才能達 external consistency。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/linearizability/" data-link-title="Linearizability" data-link-desc="每次操作看起來都在單一全域順序中即時生效的一致性語意">Linearizability&lt;/a> 緊密相關 — HLC 在 max-offset 契約成立的前提下、cluster 內所有 transaction 仍是 linearizable。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 HLC 判讀的訊號是「distributed SQL cluster 節點 NTP 異常、寫入路徑開始 panic」。&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/doordash-cockroachdb-orders-platform/" data-link-title="9.C39 DoorDash：Aurora Postgres 寫入瓶頸 → CockroachDB 多主寫入" data-link-desc="DoorDash 從 Aurora Postgres 遷到 CockroachDB、解 1.6 M QPS 單主寫入瓶頸、外送平台爆量壓力下重做 OLTP 拓樸">9.C39 DoorDash CockroachDB&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/netflix-cockroachdb-multi-region-fleet/" data-link-title="9.C40 Netflix：380&amp;#43; CockroachDB cluster 的 multi-active 拓樸艦隊" data-link-desc="Netflix 把 Cassandra 不夠用的 transactional workload 移到 CockroachDB、380&amp;#43; cluster / 60&amp;#43; 跨 region、含 Open Connect、studio cloud drive、gaming control plane">9.C40 Netflix CockroachDB&lt;/a> 都用 HLC 撐線性化、NTP 是 ops first-class concern。CockroachDB 預設 &lt;code>max-offset&lt;/code> 是 500ms、節點時鐘飄超過就自動 panic、不會發出錯誤 commit；HLC 在跨 node RPC 時把 logical counter 同步推進、確保事件因果順序在跨節點仍可推導。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選擇 HLC 路徑就要把 NTP / chronyd 維運當成 production-critical — 不是「裝了就好」、要監控時鐘漂移、設 alert 在 max-offset 的一半左右觸發。max-offset 配置過寬（例如改 5s 想避免 panic）會在跨節點交易順序判讀上引入錯誤、不是 ops 「彈性」、是把線性化保證打破。對比 TrueTime 路徑、HLC 不需要付 commit-wait latency tax、但 cross-cloud / on-prem 部署彈性是它的主要 trade-off 動機、不要為了「不付 commit-wait」就選 HLC、要為了部署環境選 HLC、commit-wait 不付只是順帶結果。&lt;/p></description><content:encoded><![CDATA[<p>Hybrid Logical Clock（HLC）的核心概念是「給每個事件一個 <code>(physical, logical)</code> timestamp、physical 來自 NTP 同步的 wall clock、logical 是單調遞增的 counter 處理同一 physical tick 內的事件順序」。它的責任是讓跨節點 event ordering 可以用軟體保證、不需要 GPS + 原子鐘等專用硬體、代價是要承擔 max-offset 邊界內的不確定性。可先對照 <a href="/blog/backend/knowledge-cards/truetime/" data-link-title="TrueTime" data-link-desc="分散式資料庫用來界定時間不確定性的時間語意機制">TrueTime</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>HLC 出現在 CockroachDB 等不依賴專用硬體的 distributed SQL、跟 <a href="/blog/backend/knowledge-cards/truetime/" data-link-title="TrueTime" data-link-desc="分散式資料庫用來界定時間不確定性的時間語意機制">TrueTime</a> 是對照關係 — 兩者解同一個 event ordering 問題、HLC 用軟體 + NTP、TrueTime 用 GPS + 原子鐘。跟 <a href="/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">External Consistency</a> 互補但不等同：HLC 保證 linearizability、不保證 external consistency；TrueTime 加 commit-wait 才能達 external consistency。跟 <a href="/blog/backend/knowledge-cards/linearizability/" data-link-title="Linearizability" data-link-desc="每次操作看起來都在單一全域順序中即時生效的一致性語意">Linearizability</a> 緊密相關 — HLC 在 max-offset 契約成立的前提下、cluster 內所有 transaction 仍是 linearizable。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 HLC 判讀的訊號是「distributed SQL cluster 節點 NTP 異常、寫入路徑開始 panic」。<a href="/blog/backend/09-performance-capacity/cases/doordash-cockroachdb-orders-platform/" data-link-title="9.C39 DoorDash：Aurora Postgres 寫入瓶頸 → CockroachDB 多主寫入" data-link-desc="DoorDash 從 Aurora Postgres 遷到 CockroachDB、解 1.6 M QPS 單主寫入瓶頸、外送平台爆量壓力下重做 OLTP 拓樸">9.C39 DoorDash CockroachDB</a> 跟 <a href="/blog/backend/09-performance-capacity/cases/netflix-cockroachdb-multi-region-fleet/" data-link-title="9.C40 Netflix：380&#43; CockroachDB cluster 的 multi-active 拓樸艦隊" data-link-desc="Netflix 把 Cassandra 不夠用的 transactional workload 移到 CockroachDB、380&#43; cluster / 60&#43; 跨 region、含 Open Connect、studio cloud drive、gaming control plane">9.C40 Netflix CockroachDB</a> 都用 HLC 撐線性化、NTP 是 ops first-class concern。CockroachDB 預設 <code>max-offset</code> 是 500ms、節點時鐘飄超過就自動 panic、不會發出錯誤 commit；HLC 在跨 node RPC 時把 logical counter 同步推進、確保事件因果順序在跨節點仍可推導。</p>
<h2 id="設計責任">設計責任</h2>
<p>選擇 HLC 路徑就要把 NTP / chronyd 維運當成 production-critical — 不是「裝了就好」、要監控時鐘漂移、設 alert 在 max-offset 的一半左右觸發。max-offset 配置過寬（例如改 5s 想避免 panic）會在跨節點交易順序判讀上引入錯誤、不是 ops 「彈性」、是把線性化保證打破。對比 TrueTime 路徑、HLC 不需要付 commit-wait latency tax、但 cross-cloud / on-prem 部署彈性是它的主要 trade-off 動機、不要為了「不付 commit-wait」就選 HLC、要為了部署環境選 HLC、commit-wait 不付只是順帶結果。</p>
]]></content:encoded></item><item><title>Commit Wait</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/commit-wait/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/commit-wait/</guid><description>&lt;p>Commit wait 的核心概念是「read-write transaction 拿到 commit timestamp &lt;code>s&lt;/code> 後、Spanner 不立刻回 ACK、而是等到 &lt;code>TT.after(s)&lt;/code> 確定為真（即 wall clock 必然已過 s）才回 ACK、wait 時間約 2ε」。它的責任是用一段固定 latency 支出換取「transaction commit timestamp 全序 = real-time 順序」這個 external consistency 保證。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/truetime/" data-link-title="TrueTime" data-link-desc="分散式資料庫用來界定時間不確定性的時間語意機制">TrueTime&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Commit wait 出現在 Spanner 系列產品、是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/truetime/" data-link-title="TrueTime" data-link-desc="分散式資料庫用來界定時間不確定性的時間語意機制">TrueTime&lt;/a> API 跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">External Consistency&lt;/a> 之間的橋接機制 — TrueTime 給帶 ε 不確定區間的時間 API、commit wait 是 &lt;em>用它撐 external consistency 的具體實作&lt;/em>。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">Latency Budget&lt;/a> 互補：commit wait 是無法 scale away 的固定 latency 支出、要當設計初期就寫進預算、不是運維後才補。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 commit wait 判讀的訊號是「Spanner write latency 拆解時、commit_latencies p99 跟 ε 一起平移」。&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Spanner&lt;/a> 揭露 commit wait 機制：Spanner 設 &lt;code>s = TT.now().latest&lt;/code> 後等 &lt;code>TT.after(s)&lt;/code>、wait ≈ 2ε（從拿 s 那刻起算）；ε 通常 1-7ms（Spanner vendor docs / 2012 OSDI 論文揭露範圍、非 case 直接揭露 production 分布）、所以 commit wait 通常落在 2-14ms。voting region 越分散、ε 上限越高、commit wait 越長。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要把 commit wait 當成「Spanner 寫入路徑的固定 latency 稅」、不是可優化掉的成本。region layout 決策直接影響 commit wait — voting region 散布越廣、ε 上限越高、commit wait 越長。read-only transaction 可用 &lt;code>exact_staleness&lt;/code> / &lt;code>bounded_staleness&lt;/code> 避開 commit wait、適合 reporting / analytics；strong consistency read 要付完整 commit wait + quorum cost、要主動分流。把寫入路徑當「等 commit wait → quorum 已 ack」兩段同步來推 SLO、不是只看 quorum latency 就估完。&lt;/p></description><content:encoded><![CDATA[<p>Commit wait 的核心概念是「read-write transaction 拿到 commit timestamp <code>s</code> 後、Spanner 不立刻回 ACK、而是等到 <code>TT.after(s)</code> 確定為真（即 wall clock 必然已過 s）才回 ACK、wait 時間約 2ε」。它的責任是用一段固定 latency 支出換取「transaction commit timestamp 全序 = real-time 順序」這個 external consistency 保證。可先對照 <a href="/blog/backend/knowledge-cards/truetime/" data-link-title="TrueTime" data-link-desc="分散式資料庫用來界定時間不確定性的時間語意機制">TrueTime</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Commit wait 出現在 Spanner 系列產品、是 <a href="/blog/backend/knowledge-cards/truetime/" data-link-title="TrueTime" data-link-desc="分散式資料庫用來界定時間不確定性的時間語意機制">TrueTime</a> API 跟 <a href="/blog/backend/knowledge-cards/external-consistency/" data-link-title="External Consistency" data-link-desc="交易可見順序與外部真實時間順序一致的強一致性語意">External Consistency</a> 之間的橋接機制 — TrueTime 給帶 ε 不確定區間的時間 API、commit wait 是 <em>用它撐 external consistency 的具體實作</em>。跟 <a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">Latency Budget</a> 互補：commit wait 是無法 scale away 的固定 latency 支出、要當設計初期就寫進預算、不是運維後才補。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 commit wait 判讀的訊號是「Spanner write latency 拆解時、commit_latencies p99 跟 ε 一起平移」。<a href="/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Spanner</a> 揭露 commit wait 機制：Spanner 設 <code>s = TT.now().latest</code> 後等 <code>TT.after(s)</code>、wait ≈ 2ε（從拿 s 那刻起算）；ε 通常 1-7ms（Spanner vendor docs / 2012 OSDI 論文揭露範圍、非 case 直接揭露 production 分布）、所以 commit wait 通常落在 2-14ms。voting region 越分散、ε 上限越高、commit wait 越長。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要把 commit wait 當成「Spanner 寫入路徑的固定 latency 稅」、不是可優化掉的成本。region layout 決策直接影響 commit wait — voting region 散布越廣、ε 上限越高、commit wait 越長。read-only transaction 可用 <code>exact_staleness</code> / <code>bounded_staleness</code> 避開 commit wait、適合 reporting / analytics；strong consistency read 要付完整 commit wait + quorum cost、要主動分流。把寫入路徑當「等 commit wait → quorum 已 ack」兩段同步來推 SLO、不是只看 quorum latency 就估完。</p>
]]></content:encoded></item><item><title>Request Unit</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/request-unit/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/request-unit/</guid><description>&lt;p>Request Unit（RU）的核心概念是「Cosmos DB 把 CPU + memory + IOPS 等資源綜合成單一抽象計量、1 RU 對應 1KB document 的 strong-consistent read 成本」。它的責任是把容量規劃從「估 CPU / IOPS / working set」改成「估每個操作多少 RU × 操作頻率」、讓 throttle / scaling / 計費都用同一個量綱。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cost-per-request/" data-link-title="Cost Per Request" data-link-desc="把雲端成本拆到單一 API 請求的 unit economics 模型">Cost Per Request&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>RU 出現在 Cosmos DB 全產品線、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cost-per-request/" data-link-title="Cost Per Request" data-link-desc="把雲端成本拆到單一 API 請求的 unit economics 模型">Cost Per Request&lt;/a> 是抽象與具體實作的對應 — cost-per-request 是通用概念、RU 是 Cosmos DB 把它落地成單一可計量單位。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/throughput/" data-link-title="Throughput" data-link-desc="整理系統單位時間內可處理的工作量">Throughput&lt;/a> 區分：後者是 raw 計量（每秒幾筆 / 幾 MB）、RU 是 vendor 抽象、不可直接互換。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/workload-model/" data-link-title="Workload Model" data-link-desc="描述 production traffic 形狀的可重播模型 — 容量規劃跟壓測的共同輸入">Workload Model&lt;/a> 互補 — workload model 決定 access pattern、access pattern 決定 RU consumption、兩者一起才能估容量。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 RU 判讀的訊號是「Cosmos DB throttle 在 monthly bill 之前就先出現、team 估容量發現估不出來」。&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/minecraft-earth-cosmos-db-global/" data-link-title="9.C11 Minecraft Earth：Azure Cosmos DB 上的全球分散式 AR 遊戲" data-link-desc="Minecraft Earth 用 Cosmos DB 跨地區分散、測試到 100 萬 RU/s 仍維持承諾延遲">9.C11 Minecraft Earth&lt;/a> 揭露對照：1 RU = 1KB strong-consistent read、寫 ~5 RU、複雜 query 數百 RU；100 萬 RU/s 壓測通過（壓測數字、非 production 持續、case 自己警示）。&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/asos-cosmos-db-black-friday/" data-link-title="9.C21 ASOS：Cosmos DB 在 Black Friday 撐 1.67 億請求" data-link-desc="ASOS 在 2016 Black Friday 用 Azure Cosmos DB 撐 24 小時 1.67 億請求、3500 req/sec、48ms 平均延遲">9.C21 ASOS Cosmos DB&lt;/a> 跟 &lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/microsoft-365-cosmos-db-analytics/" data-link-title="9.C30 Microsoft 365：從 MongoDB 遷移到 Cosmos DB 的分析平台" data-link-desc="Microsoft 365 把使用分析平台從 MongoDB 遷移到 Cosmos DB、planet-scale 全球分散式分析">9.C30 Microsoft 365 Cosmos DB&lt;/a> 揭露 Black Friday 10x 流量下 autoscale 跟不上 throttle、index policy 改動讓 write RU 漲 30%。&lt;/p></description><content:encoded><![CDATA[<p>Request Unit（RU）的核心概念是「Cosmos DB 把 CPU + memory + IOPS 等資源綜合成單一抽象計量、1 RU 對應 1KB document 的 strong-consistent read 成本」。它的責任是把容量規劃從「估 CPU / IOPS / working set」改成「估每個操作多少 RU × 操作頻率」、讓 throttle / scaling / 計費都用同一個量綱。可先對照 <a href="/blog/backend/knowledge-cards/cost-per-request/" data-link-title="Cost Per Request" data-link-desc="把雲端成本拆到單一 API 請求的 unit economics 模型">Cost Per Request</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>RU 出現在 Cosmos DB 全產品線、跟 <a href="/blog/backend/knowledge-cards/cost-per-request/" data-link-title="Cost Per Request" data-link-desc="把雲端成本拆到單一 API 請求的 unit economics 模型">Cost Per Request</a> 是抽象與具體實作的對應 — cost-per-request 是通用概念、RU 是 Cosmos DB 把它落地成單一可計量單位。跟 <a href="/blog/backend/knowledge-cards/throughput/" data-link-title="Throughput" data-link-desc="整理系統單位時間內可處理的工作量">Throughput</a> 區分：後者是 raw 計量（每秒幾筆 / 幾 MB）、RU 是 vendor 抽象、不可直接互換。跟 <a href="/blog/backend/knowledge-cards/workload-model/" data-link-title="Workload Model" data-link-desc="描述 production traffic 形狀的可重播模型 — 容量規劃跟壓測的共同輸入">Workload Model</a> 互補 — workload model 決定 access pattern、access pattern 決定 RU consumption、兩者一起才能估容量。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 RU 判讀的訊號是「Cosmos DB throttle 在 monthly bill 之前就先出現、team 估容量發現估不出來」。<a href="/blog/backend/09-performance-capacity/cases/minecraft-earth-cosmos-db-global/" data-link-title="9.C11 Minecraft Earth：Azure Cosmos DB 上的全球分散式 AR 遊戲" data-link-desc="Minecraft Earth 用 Cosmos DB 跨地區分散、測試到 100 萬 RU/s 仍維持承諾延遲">9.C11 Minecraft Earth</a> 揭露對照：1 RU = 1KB strong-consistent read、寫 ~5 RU、複雜 query 數百 RU；100 萬 RU/s 壓測通過（壓測數字、非 production 持續、case 自己警示）。<a href="/blog/backend/09-performance-capacity/cases/asos-cosmos-db-black-friday/" data-link-title="9.C21 ASOS：Cosmos DB 在 Black Friday 撐 1.67 億請求" data-link-desc="ASOS 在 2016 Black Friday 用 Azure Cosmos DB 撐 24 小時 1.67 億請求、3500 req/sec、48ms 平均延遲">9.C21 ASOS Cosmos DB</a> 跟 <a href="/blog/backend/09-performance-capacity/cases/microsoft-365-cosmos-db-analytics/" data-link-title="9.C30 Microsoft 365：從 MongoDB 遷移到 Cosmos DB 的分析平台" data-link-desc="Microsoft 365 把使用分析平台從 MongoDB 遷移到 Cosmos DB、planet-scale 全球分散式分析">9.C30 Microsoft 365 Cosmos DB</a> 揭露 Black Friday 10x 流量下 autoscale 跟不上 throttle、index policy 改動讓 write RU 漲 30%。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要把 RU 估算當 <em>工程動作</em>、不是 vendor 廣告數字 — 量單一 query 的 <code>x-ms-request-charge</code> header、不是看 slow query log；改 index policy 影響 RU、但不改 query 速度、改的是 cost。team 從 CPU + IOPS 思維轉到 RU 思維通常需要 4-6 週、selection 評估時不能只比 monthly bill 就做 ROI 結論、思維遷移成本可能高過 vendor 廣告價差。autoscale 跟 provisioned 的選擇要看 burst 形狀跟 hot partition 風險、壓測通過數字不能直接當 production sizing 上界。</p>
]]></content:encoded></item><item><title>Follower Read</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/follower-read/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/follower-read/</guid><description>&lt;p>Follower read 的核心概念是「distributed SQL 把 read 從 leaseholder 路徑分流到 non-voting replica、讀的是 closed timestamp 之前已確定不會被改寫的快照」。它的責任是讓跨 region 部署仍能在本地讀到資料、不用付每次 read 都跨 region 找 leaseholder 的 RTT、代價是只能讀稍 stale 的資料。可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Follower read 出現在 CockroachDB / Spanner 等跨 region distributed SQL、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read&lt;/a> 是現象與機制的對應 — stale read 是症狀、follower read 是 &lt;em>有意設計&lt;/em> 換 latency 的機制。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/fallback-read/" data-link-title="Fallback Read" data-link-desc="說明讀取路徑切換失敗時如何暫時回到舊資料語意或舊讀取來源">Fallback Read&lt;/a> 區分：後者是 failure 時的降級路徑、follower read 是常態低 latency 路徑、兩者觸發條件不同。跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/read-write-split/" data-link-title="Read-Write Split" data-link-desc="說明讀寫流量如何分流到 primary 與 replica，以及它引入的一致性責任">Read Write Split&lt;/a> 區分：後者是 application-level 把 read 導到 replica、follower read 是 distributed SQL 系統內機制、application 透明、跟 voting / non-voting replica 配置綁定。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 follower read 的訊號是「跨 region distributed SQL、read p99 卡在跨 region RTT 上、但業務可容忍秒級 stale」。&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/netflix-cockroachdb-multi-region-fleet/" data-link-title="9.C40 Netflix：380&amp;#43; CockroachDB cluster 的 multi-active 拓樸艦隊" data-link-desc="Netflix 把 Cassandra 不夠用的 transactional workload 移到 CockroachDB、380&amp;#43; cluster / 60&amp;#43; 跨 region、含 Open Connect、studio cloud drive、gaming control plane">9.C40 Netflix CockroachDB&lt;/a> 揭露 region survival 配置下的 follower read 機制：voting replica 跨 region 參與 commit、non-voting replica 只 serve follower read；&lt;code>REGIONAL BY ROW&lt;/code> + &lt;code>SURVIVE REGION FAILURE&lt;/code> 配合時、其他 region 有 non-voting replica 提供本地 follower read。&lt;a href="https://tarrragon.github.io/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Spanner&lt;/a> 在 SDK 層提供 &lt;code>bounded_staleness(t)&lt;/code> 選項、容忍 t 秒、可讀最近的本地 replica。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要把 follower read 跟 read 業務分流綁在一起 — strong consistency read（餘額查詢、剛寫完的訂單）走 leaseholder 路徑、容忍 stale 的 read（dashboard / reporting / 風控分析）走 follower read。不要把 follower read 當 failover 機制、它不是 — failover 是 fallback read 的責任。配置 non-voting replica 時要評估 storage cost、每多一個 region 多一份 storage。closed timestamp 推進延遲（通常數秒）就是 follower read 的 staleness 上界、要寫進 SLO、不是「快取秒數可調」。&lt;/p></description><content:encoded><![CDATA[<p>Follower read 的核心概念是「distributed SQL 把 read 從 leaseholder 路徑分流到 non-voting replica、讀的是 closed timestamp 之前已確定不會被改寫的快照」。它的責任是讓跨 region 部署仍能在本地讀到資料、不用付每次 read 都跨 region 找 leaseholder 的 RTT、代價是只能讀稍 stale 的資料。可先對照 <a href="/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Follower read 出現在 CockroachDB / Spanner 等跨 region distributed SQL、跟 <a href="/blog/backend/knowledge-cards/stale-read/" data-link-title="Stale Read" data-link-desc="讀取到落後於最新寫入版本的舊資料">Stale Read</a> 是現象與機制的對應 — stale read 是症狀、follower read 是 <em>有意設計</em> 換 latency 的機制。跟 <a href="/blog/backend/knowledge-cards/fallback-read/" data-link-title="Fallback Read" data-link-desc="說明讀取路徑切換失敗時如何暫時回到舊資料語意或舊讀取來源">Fallback Read</a> 區分：後者是 failure 時的降級路徑、follower read 是常態低 latency 路徑、兩者觸發條件不同。跟 <a href="/blog/backend/knowledge-cards/read-write-split/" data-link-title="Read-Write Split" data-link-desc="說明讀寫流量如何分流到 primary 與 replica，以及它引入的一致性責任">Read Write Split</a> 區分：後者是 application-level 把 read 導到 replica、follower read 是 distributed SQL 系統內機制、application 透明、跟 voting / non-voting replica 配置綁定。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 follower read 的訊號是「跨 region distributed SQL、read p99 卡在跨 region RTT 上、但業務可容忍秒級 stale」。<a href="/blog/backend/09-performance-capacity/cases/netflix-cockroachdb-multi-region-fleet/" data-link-title="9.C40 Netflix：380&#43; CockroachDB cluster 的 multi-active 拓樸艦隊" data-link-desc="Netflix 把 Cassandra 不夠用的 transactional workload 移到 CockroachDB、380&#43; cluster / 60&#43; 跨 region、含 Open Connect、studio cloud drive、gaming control plane">9.C40 Netflix CockroachDB</a> 揭露 region survival 配置下的 follower read 機制：voting replica 跨 region 參與 commit、non-voting replica 只 serve follower read；<code>REGIONAL BY ROW</code> + <code>SURVIVE REGION FAILURE</code> 配合時、其他 region 有 non-voting replica 提供本地 follower read。<a href="/blog/backend/09-performance-capacity/cases/spanner-planetary-scale-database-gcp/" data-link-title="9.C10 Cloud Spanner：每秒 10 億請求的全球一致性資料庫" data-link-desc="Google Cloud Spanner 內部峰值 10 億 req/sec、跨地區強一致 — 全球分散式 OLTP 容量參考">9.C10 Spanner</a> 在 SDK 層提供 <code>bounded_staleness(t)</code> 選項、容忍 t 秒、可讀最近的本地 replica。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要把 follower read 跟 read 業務分流綁在一起 — strong consistency read（餘額查詢、剛寫完的訂單）走 leaseholder 路徑、容忍 stale 的 read（dashboard / reporting / 風控分析）走 follower read。不要把 follower read 當 failover 機制、它不是 — failover 是 fallback read 的責任。配置 non-voting replica 時要評估 storage cost、每多一個 region 多一份 storage。closed timestamp 推進延遲（通常數秒）就是 follower read 的 staleness 上界、要寫進 SLO、不是「快取秒數可調」。</p>
]]></content:encoded></item><item><title>Serialization Failure</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/serialization-failure/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/serialization-failure/</guid><description>&lt;p>Serialization failure 的核心概念是「SERIALIZABLE isolation 偵測到並行 transaction 衝突、把後到的 transaction abort、回傳 SQL state &lt;code>40001&lt;/code>、要求 application 包 retry loop 重跑」。它是 serializable 跟弱 isolation 行為差異的關鍵介面、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">Isolation Level&lt;/a> 共軸、retry 設計沒做好會升級成 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Serialization failure 是跨 vendor 共通協議、不是單一資料庫的機制。CockroachDB（預設 SERIALIZABLE）、Spanner（read-write transaction）、PostgreSQL SSI（opt-in SERIALIZABLE）、Aurora DSQL 都會在偵測衝突時丟 &lt;code>40001&lt;/code>。差別在 &lt;em>衝突偵測時機&lt;/em>：PostgreSQL SSI 用 predicate lock 在 commit 階段偵測、CockroachDB 用 timestamp ordering + write intent 在衝突當下就 abort、Spanner 用 strict 2PL 在讀寫過程中 detect。對 application 來說、不管哪家、看到的都是同一個 error code、處理方式一致：rollback、backoff、重跑。&lt;/p>
&lt;p>跟 &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> 一起設計 — transaction body 必須是 &lt;em>冪等可重跑&lt;/em>、不能含「呼叫外部 API 扣款」這類無法重做的副作用。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要面對 serialization failure 的訊號是「同一段 application code 在 PostgreSQL READ COMMITTED 上從不失敗、遷到 CockroachDB / Spanner 後 retry rate 突然飆升」、或「serializable cluster 的 hot row 路徑 p99 latency 隨並行度線性惡化」。CockroachDB 從 PostgreSQL READ COMMITTED 遷移時、application 接管 retry contract 是必要工程、Cockroach Labs 官方推薦 &lt;code>SAVEPOINT cockroach_restart&lt;/code> 寫法、讓整個 transaction 可以在 &lt;code>ROLLBACK TO SAVEPOINT&lt;/code> 後重新進入。Spanner SDK 內建 retry loop、但開發者仍要保證 transaction body 冪等。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 serializable workload 時必須先寫 retry policy：exponential backoff + jitter 避免 retry storm、max retry 限制避免 user-facing latency 拖垮、retry budget 接 circuit breaker。Application code 要把 transaction body 寫成可重入 — 跨 statement 的 in-memory state、外部 API call、非冪等寫入都要移出 transaction。沒寫 retry loop 等於把 serializable cluster 當 READ COMMITTED 用、衝突就直接拋例外給終端 user。Hot row 場景（同一筆庫存被千人搶）serialization failure 會持續存在、要靠 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding&lt;/a> 或 application-level 排隊解決、不是調大 retry 次數能擋。&lt;/p></description><content:encoded><![CDATA[<p>Serialization failure 的核心概念是「SERIALIZABLE isolation 偵測到並行 transaction 衝突、把後到的 transaction abort、回傳 SQL state <code>40001</code>、要求 application 包 retry loop 重跑」。它是 serializable 跟弱 isolation 行為差異的關鍵介面、跟 <a href="/blog/backend/knowledge-cards/isolation-level/" data-link-title="Isolation Level" data-link-desc="說明資料庫交易隔離級別如何影響並發讀寫結果">Isolation Level</a> 共軸、retry 設計沒做好會升級成 <a href="/blog/backend/knowledge-cards/retry-storm/" data-link-title="Retry Storm" data-link-desc="說明大量重試如何把局部故障放大成系統壓力">Retry Storm</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Serialization failure 是跨 vendor 共通協議、不是單一資料庫的機制。CockroachDB（預設 SERIALIZABLE）、Spanner（read-write transaction）、PostgreSQL SSI（opt-in SERIALIZABLE）、Aurora DSQL 都會在偵測衝突時丟 <code>40001</code>。差別在 <em>衝突偵測時機</em>：PostgreSQL SSI 用 predicate lock 在 commit 階段偵測、CockroachDB 用 timestamp ordering + write intent 在衝突當下就 abort、Spanner 用 strict 2PL 在讀寫過程中 detect。對 application 來說、不管哪家、看到的都是同一個 error code、處理方式一致：rollback、backoff、重跑。</p>
<p>跟 <a href="/blog/backend/knowledge-cards/transaction-boundary/" data-link-title="Transaction Boundary" data-link-desc="說明哪些資料變更應在同一個交易中一起成功或一起回復">Transaction Boundary</a> 一起設計 — transaction body 必須是 <em>冪等可重跑</em>、不能含「呼叫外部 API 扣款」這類無法重做的副作用。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要面對 serialization failure 的訊號是「同一段 application code 在 PostgreSQL READ COMMITTED 上從不失敗、遷到 CockroachDB / Spanner 後 retry rate 突然飆升」、或「serializable cluster 的 hot row 路徑 p99 latency 隨並行度線性惡化」。CockroachDB 從 PostgreSQL READ COMMITTED 遷移時、application 接管 retry contract 是必要工程、Cockroach Labs 官方推薦 <code>SAVEPOINT cockroach_restart</code> 寫法、讓整個 transaction 可以在 <code>ROLLBACK TO SAVEPOINT</code> 後重新進入。Spanner SDK 內建 retry loop、但開發者仍要保證 transaction body 冪等。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 serializable workload 時必須先寫 retry policy：exponential backoff + jitter 避免 retry storm、max retry 限制避免 user-facing latency 拖垮、retry budget 接 circuit breaker。Application code 要把 transaction body 寫成可重入 — 跨 statement 的 in-memory state、外部 API call、非冪等寫入都要移出 transaction。沒寫 retry loop 等於把 serializable cluster 當 READ COMMITTED 用、衝突就直接拋例外給終端 user。Hot row 場景（同一筆庫存被千人搶）serialization failure 會持續存在、要靠 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a> 或 application-level 排隊解決、不是調大 retry 次數能擋。</p>
]]></content:encoded></item><item><title>Composite Partition Key</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/composite-partition-key/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/composite-partition-key/</guid><description>&lt;p>Composite partition key 的核心概念是「用多個欄位拼接成 partition key — 例如 &lt;code>event_id#shard_id&lt;/code>、&lt;code>tenant_id + user_id_hash&lt;/code>、&lt;code>userId_random&lt;/code> — 把單一 logical key 寫入分散到 N 個物理 partition」。它是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition&lt;/a> 的標準治療手段、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding&lt;/a> 不同層（後者是跨 cluster 的 application-level、composite key 是單表內 partition layout）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Composite partition key 在 KV / document DB 的 partition 抽象層運作 — DynamoDB、Cosmos DB、MongoDB sharded cluster 都用同一套思路。隨 composite 方式不同分兩型：&lt;em>random shard&lt;/em>（&lt;code>event_id#random(0,N-1)&lt;/code>、寫完全分散、讀必須 fan-out 全部 N 個 shard）跟 &lt;em>calculated shard&lt;/em>（&lt;code>event_id#hash(user_id) % N&lt;/code>、同 user 寫到固定 shard、單 user 讀不 fan-out、跨 user 讀才 fan-out）。Cosmos DB 的 &lt;em>synthetic partition key&lt;/em>、MongoDB 的 &lt;em>hashed shard key&lt;/em>、DynamoDB 的 &lt;em>write sharding suffix&lt;/em> 都是這個概念的 vendor 命名。&lt;/p>
&lt;p>跟 partition layout 是分散式 SQL 透明 range 的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/range-sharding/" data-link-title="Range Sharding" data-link-desc="分散式 SQL 把 key space 切成可自動 split / merge 的 range、每個 range 自己的 consensus group、application 透明">Range Sharding&lt;/a> 區隔 — 後者不需要 application 操心 key 設計、composite key 是 application-managed 的明確介面。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 composite partition key 的訊號是「整體 utilization 低、少數 partition WCU / RU 飆到上限、p99 latency 隨單一 logical key 流量線性惡化」。對應案例：DynamoDB 售票場景單一 &lt;code>event_id&lt;/code>（一場演唱會）天然集中、composite &lt;code>event_id#shard&lt;/code> + random suffix 把 IOPS 從單 partition 1000 WCU 上限拆到 N × 1000；Cosmos DB synthetic key 把 fanout 設 10-100 之間平衡寫分散跟讀成本。MongoDB hashed shard key 則犧牲 range query 換取均勻分散。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計 composite key 必須先 audit &lt;em>讀寫比例&lt;/em> — 寫密集 + 讀範圍小（單 user 自己的 timeline）適合 calculated shard、讀寫都跨 logical key（全平台 aggregation）random shard 也吃得消；讀密集 + 跨 logical key fan-out 成本爆炸時要回頭重設 shard 數或加 secondary index。fanout 數量是核心參數：太少（&amp;lt; 10）寫入仍可能集中、太多（&amp;gt; 100）讀放大成本壓垮 RU / WCU 預算。Resharding（改 shard 數）成本極高 — 設計階段就要按最壞峰值估 N、留 buffer、寫進 schema 設計文件而不是只寫 application code。&lt;/p></description><content:encoded><![CDATA[<p>Composite partition key 的核心概念是「用多個欄位拼接成 partition key — 例如 <code>event_id#shard_id</code>、<code>tenant_id + user_id_hash</code>、<code>userId_random</code> — 把單一 logical key 寫入分散到 N 個物理 partition」。它是 <a href="/blog/backend/knowledge-cards/hot-partition/" data-link-title="Hot Partition" data-link-desc="說明分散式 KV / OLTP 中、單一 partition 流量遠超其他的容量問題">Hot Partition</a> 的標準治療手段、跟 <a href="/blog/backend/knowledge-cards/database-sharding/" data-link-title="Database Sharding" data-link-desc="說明資料庫如何依 shard key 分散資料、路由請求與承擔跨 shard 查詢成本">Database Sharding</a> 不同層（後者是跨 cluster 的 application-level、composite key 是單表內 partition layout）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Composite partition key 在 KV / document DB 的 partition 抽象層運作 — DynamoDB、Cosmos DB、MongoDB sharded cluster 都用同一套思路。隨 composite 方式不同分兩型：<em>random shard</em>（<code>event_id#random(0,N-1)</code>、寫完全分散、讀必須 fan-out 全部 N 個 shard）跟 <em>calculated shard</em>（<code>event_id#hash(user_id) % N</code>、同 user 寫到固定 shard、單 user 讀不 fan-out、跨 user 讀才 fan-out）。Cosmos DB 的 <em>synthetic partition key</em>、MongoDB 的 <em>hashed shard key</em>、DynamoDB 的 <em>write sharding suffix</em> 都是這個概念的 vendor 命名。</p>
<p>跟 partition layout 是分散式 SQL 透明 range 的 <a href="/blog/backend/knowledge-cards/range-sharding/" data-link-title="Range Sharding" data-link-desc="分散式 SQL 把 key space 切成可自動 split / merge 的 range、每個 range 自己的 consensus group、application 透明">Range Sharding</a> 區隔 — 後者不需要 application 操心 key 設計、composite key 是 application-managed 的明確介面。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 composite partition key 的訊號是「整體 utilization 低、少數 partition WCU / RU 飆到上限、p99 latency 隨單一 logical key 流量線性惡化」。對應案例：DynamoDB 售票場景單一 <code>event_id</code>（一場演唱會）天然集中、composite <code>event_id#shard</code> + random suffix 把 IOPS 從單 partition 1000 WCU 上限拆到 N × 1000；Cosmos DB synthetic key 把 fanout 設 10-100 之間平衡寫分散跟讀成本。MongoDB hashed shard key 則犧牲 range query 換取均勻分散。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 composite key 必須先 audit <em>讀寫比例</em> — 寫密集 + 讀範圍小（單 user 自己的 timeline）適合 calculated shard、讀寫都跨 logical key（全平台 aggregation）random shard 也吃得消；讀密集 + 跨 logical key fan-out 成本爆炸時要回頭重設 shard 數或加 secondary index。fanout 數量是核心參數：太少（&lt; 10）寫入仍可能集中、太多（&gt; 100）讀放大成本壓垮 RU / WCU 預算。Resharding（改 shard 數）成本極高 — 設計階段就要按最壞峰值估 N、留 buffer、寫進 schema 設計文件而不是只寫 application code。</p>
]]></content:encoded></item><item><title>Interleaved Table</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/interleaved-table/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/interleaved-table/</guid><description>&lt;p>Interleaved table 的核心概念是「parent table 跟 child table 的 row 在 storage layer 物理交錯儲存 — child row 跟對應 parent row 落在同一個 split」。它把「foreign key 是 logical constraint」翻成「parent-child access 是 physical co-location」、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/range-sharding/" data-link-title="Range Sharding" data-link-desc="分散式 SQL 把 key space 切成可自動 split / merge 的 range、每個 range 自己的 consensus group、application 透明">Range Sharding&lt;/a> 是相鄰機制（前者是 row-level co-location、後者是 key-space transparent split）、跟 PostgreSQL declarative 的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/table-partitioning/" data-link-title="Table Partitioning" data-link-desc="說明單一資料庫內如何把大表拆成多個分區，並由查詢規劃器只掃相關片段">Table Partitioning&lt;/a> 不同層（後者是單機表結構、interleaved 是分散式 SQL 跨 Paxos group 的 row co-location）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Spanner 是 interleaved table 的代表 vendor — &lt;code>CREATE TABLE Order ... INTERLEAVE IN PARENT Customer ON DELETE CASCADE&lt;/code> 把 child row 物理黏到 parent row 旁邊。Storage layout 從 &lt;code>[c1, c2, c3, ...] [o1, o2, o3, ...]&lt;/code> 變成 &lt;code>[c1, c1.o1, c1.o2, c2, c2.o1, c2.o2, c3, ...]&lt;/code> — parent + child JOIN 在同一個 split 完成、不跨 Paxos group、commit wait + Paxos round-trip 只算一份。CockroachDB 的 &lt;code>REGIONAL BY ROW&lt;/code> + parent-child placement 是相鄰概念（透過 region locality 達成類似 co-location 效果、但機制不同）。&lt;/p>
&lt;p>跟 &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> 共軸 — interleaved 讓 transaction boundary 跟 storage boundary對齊、跨 split transaction 大幅減少。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合 interleaved table 的訊號是「access pattern 固定 parent → child、JOIN 頻率高、跨 split JOIN p99 latency 撐不住」。典型情境：customer → orders、user → posts、tenant → records 這類 1:N 強耦合資料。Spanner 文件揭露的硬限要記住：child PK 必須以 parent PK 為 prefix、最深 7 層、&lt;code>ON DELETE&lt;/code> 只能 CASCADE 或 NO ACTION（不像 PG FK 有 SET NULL / SET DEFAULT）、一旦建立無法 ALTER 改 interleave — 要改就是 export + recreate + import、不是 ALTER。&lt;/p></description><content:encoded><![CDATA[<p>Interleaved table 的核心概念是「parent table 跟 child table 的 row 在 storage layer 物理交錯儲存 — child row 跟對應 parent row 落在同一個 split」。它把「foreign key 是 logical constraint」翻成「parent-child access 是 physical co-location」、跟 <a href="/blog/backend/knowledge-cards/range-sharding/" data-link-title="Range Sharding" data-link-desc="分散式 SQL 把 key space 切成可自動 split / merge 的 range、每個 range 自己的 consensus group、application 透明">Range Sharding</a> 是相鄰機制（前者是 row-level co-location、後者是 key-space transparent split）、跟 PostgreSQL declarative 的 <a href="/blog/backend/knowledge-cards/table-partitioning/" data-link-title="Table Partitioning" data-link-desc="說明單一資料庫內如何把大表拆成多個分區，並由查詢規劃器只掃相關片段">Table Partitioning</a> 不同層（後者是單機表結構、interleaved 是分散式 SQL 跨 Paxos group 的 row co-location）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Spanner 是 interleaved table 的代表 vendor — <code>CREATE TABLE Order ... INTERLEAVE IN PARENT Customer ON DELETE CASCADE</code> 把 child row 物理黏到 parent row 旁邊。Storage layout 從 <code>[c1, c2, c3, ...] [o1, o2, o3, ...]</code> 變成 <code>[c1, c1.o1, c1.o2, c2, c2.o1, c2.o2, c3, ...]</code> — parent + child JOIN 在同一個 split 完成、不跨 Paxos group、commit wait + Paxos round-trip 只算一份。CockroachDB 的 <code>REGIONAL BY ROW</code> + parent-child placement 是相鄰概念（透過 region locality 達成類似 co-location 效果、但機制不同）。</p>
<p>跟 <a href="/blog/backend/knowledge-cards/transaction-boundary/" data-link-title="Transaction Boundary" data-link-desc="說明哪些資料變更應在同一個交易中一起成功或一起回復">Transaction Boundary</a> 共軸 — interleaved 讓 transaction boundary 跟 storage boundary對齊、跨 split transaction 大幅減少。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合 interleaved table 的訊號是「access pattern 固定 parent → child、JOIN 頻率高、跨 split JOIN p99 latency 撐不住」。典型情境：customer → orders、user → posts、tenant → records 這類 1:N 強耦合資料。Spanner 文件揭露的硬限要記住：child PK 必須以 parent PK 為 prefix、最深 7 層、<code>ON DELETE</code> 只能 CASCADE 或 NO ACTION（不像 PG FK 有 SET NULL / SET DEFAULT）、一旦建立無法 ALTER 改 interleave — 要改就是 export + recreate + import、不是 ALTER。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計 interleaved table 必須在 schema 階段就 audit access pattern — 哪些 parent-child 該 interleave 在資料量小時容易決定、資料量到 10 億 row 後再改是大工程。child PK prefix 限制意味設計時要把「跟誰 co-locate」當 schema 主軸、不只是 logical 關聯。不適合 interleave 的情境：child 對多個 parent 有 N:M 關係、access pattern 跨 parent aggregation（report 跨所有 customer 算 orders 總和）、parent 跟 child 寫入頻率差異極大（hot parent 拖累 cold child storage）。錯用 interleave 會把 parent 的 hot range 問題擴散到 child、反而比獨立表更糟。</p>
]]></content:encoded></item><item><title>Data Residency</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/data-residency/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/data-residency/</guid><description>&lt;p>Data residency 的核心概念是「合規法規（GDPR、PIPL、LGPD、美國 Wire Act 等）要求資料留在某個地理邊界內、跨境複製本身違反合規、不是延遲或成本議題」。它是 &lt;em>合規驅動的地理邊界&lt;/em>、跟 &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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/trust-boundary/" data-link-title="Trust Boundary" data-link-desc="說明系統哪些位置開始不能沿用原本的信任假設">Trust Boundary&lt;/a>（安全 / 信任邊界）相鄰但語意分離 — 三者可能在同一系統共存、但決策驅動力不同。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Data residency 直接決定 multi-region database 的拓樸選擇。Aurora Global Database 用 cross-region async replication、在受監管金融場景反指標 — 因為資料一旦複製到另一 region 就違反合規、不是 SLA 換的事。CockroachDB locality + placement、Spanner regional configuration、DynamoDB region-pinned Global Tables 是 &lt;em>合規吸收層&lt;/em> — 用宣告式 region pinning 把資料邏輯綁在合規邊界內、application code 不需要重寫。AWS Outposts / Azure Stack 是另一條路徑、把雲服務硬體直接部署到合規邊界（例如美國 sportsbook 跨州合規要求運算留州內）。&lt;/p>
&lt;p>跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">Blast Radius&lt;/a> 共軸 — 合規邊界常剛好等於 blast radius 邊界、但兩者的決策驅動力不同（合規是法規硬限、blast radius 是失敗影響範圍）。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要面對 data residency 的訊號是「monolith 要進歐盟 / 中國 / 巴西市場」、或「金融 / 醫療 / 博弈業要進跨境部署」。對應 case：Standard Chartered Aurora 7 cluster fleet 路徑（銀行業跨國合規邊界、跨市場業務邏輯弱、每市場獨立 cluster 可行）；Hard Rock Wire Act 跨州博弈（跨州統一帳戶 + 跨州 reporting 是核心業務、必須邏輯一個 CockroachDB cluster + locality placement 吸收合規）。同一個 &lt;em>合規 driver&lt;/em>、不同 &lt;em>業務需求強度&lt;/em> 推出完全相反的拓樸決策。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計受合規驅動的系統時、要先把 residency 規則 &lt;em>寫進 schema 層 / placement policy&lt;/em>、不是寫在 application code retry 邏輯。讀者規劃 Aurora migration 不能假設 Global Database 一定可用 — 合規禁止跨境複製時要改用每市場獨立 cluster。判讀軸線：(1) 合規顆粒（跨國 / 跨州 / 跨 AZ）、(2) 跨 boundary 業務邏輯需求強度（強 → distributed SQL locality / 弱 → fleet of independent clusters）、(3) 團隊運維能力（單邏輯 cluster 跨 region vs 多獨立 cluster fleet）。錯把 latency 當主因（例如把 AWS Outposts 當「降低 cross-state latency 工具」）會買到 wrong tool — Outposts 的存在動機是 residency、latency 改善是副作用。&lt;/p></description><content:encoded><![CDATA[<p>Data residency 的核心概念是「合規法規（GDPR、PIPL、LGPD、美國 Wire Act 等）要求資料留在某個地理邊界內、跨境複製本身違反合規、不是延遲或成本議題」。它是 <em>合規驅動的地理邊界</em>、跟 <a href="/blog/backend/knowledge-cards/tenant-boundary/" data-link-title="Tenant Boundary" data-link-desc="說明多租戶系統如何隔離不同客戶或組織的資料與資源">Tenant Boundary</a>（業務 / 帳戶邊界）跟 <a href="/blog/backend/knowledge-cards/trust-boundary/" data-link-title="Trust Boundary" data-link-desc="說明系統哪些位置開始不能沿用原本的信任假設">Trust Boundary</a>（安全 / 信任邊界）相鄰但語意分離 — 三者可能在同一系統共存、但決策驅動力不同。</p>
<h2 id="概念位置">概念位置</h2>
<p>Data residency 直接決定 multi-region database 的拓樸選擇。Aurora Global Database 用 cross-region async replication、在受監管金融場景反指標 — 因為資料一旦複製到另一 region 就違反合規、不是 SLA 換的事。CockroachDB locality + placement、Spanner regional configuration、DynamoDB region-pinned Global Tables 是 <em>合規吸收層</em> — 用宣告式 region pinning 把資料邏輯綁在合規邊界內、application code 不需要重寫。AWS Outposts / Azure Stack 是另一條路徑、把雲服務硬體直接部署到合規邊界（例如美國 sportsbook 跨州合規要求運算留州內）。</p>
<p>跟 <a href="/blog/backend/knowledge-cards/blast-radius/" data-link-title="Blast Radius" data-link-desc="說明事故影響面如何估算與隔離">Blast Radius</a> 共軸 — 合規邊界常剛好等於 blast radius 邊界、但兩者的決策驅動力不同（合規是法規硬限、blast radius 是失敗影響範圍）。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要面對 data residency 的訊號是「monolith 要進歐盟 / 中國 / 巴西市場」、或「金融 / 醫療 / 博弈業要進跨境部署」。對應 case：Standard Chartered Aurora 7 cluster fleet 路徑（銀行業跨國合規邊界、跨市場業務邏輯弱、每市場獨立 cluster 可行）；Hard Rock Wire Act 跨州博弈（跨州統一帳戶 + 跨州 reporting 是核心業務、必須邏輯一個 CockroachDB cluster + locality placement 吸收合規）。同一個 <em>合規 driver</em>、不同 <em>業務需求強度</em> 推出完全相反的拓樸決策。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計受合規驅動的系統時、要先把 residency 規則 <em>寫進 schema 層 / placement policy</em>、不是寫在 application code retry 邏輯。讀者規劃 Aurora migration 不能假設 Global Database 一定可用 — 合規禁止跨境複製時要改用每市場獨立 cluster。判讀軸線：(1) 合規顆粒（跨國 / 跨州 / 跨 AZ）、(2) 跨 boundary 業務邏輯需求強度（強 → distributed SQL locality / 弱 → fleet of independent clusters）、(3) 團隊運維能力（單邏輯 cluster 跨 region vs 多獨立 cluster fleet）。錯把 latency 當主因（例如把 AWS Outposts 當「降低 cross-state latency 工具」）會買到 wrong tool — Outposts 的存在動機是 residency、latency 改善是副作用。</p>
]]></content:encoded></item><item><title>Cross-Region Quorum</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cross-region-quorum/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cross-region-quorum/</guid><description>&lt;p>Cross-region quorum 的核心概念是「multi-region distributed SQL（Spanner multi-region instance、CockroachDB region survival）強制 voting replica 跨 region 分布、write commit 必須等多 region quorum ack」。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">Quorum&lt;/a> 同源（後者是抽象機制）、但承擔 &lt;em>跨 region 情境下被物理光速限定的 latency tax&lt;/em> 這個獨立語意 — 是 distributed SQL line-rate scaling 上無法 scale away 的固定支出、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">Latency Budget&lt;/a> 共軸、跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/commit-wait/" data-link-title="Commit Wait" data-link-desc="Spanner external consistency 的核心機制 — read-write transaction 拿 commit timestamp s 後等到 TT.after(s) 才 ACK、wait ≈ 2ε、付 latency tax 換 commit 順序 = real-time 順序">Commit Wait&lt;/a> 是相鄰但獨立的物理 cost。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cross-region quorum 跟相鄰卡片有清楚的角色分工 — &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">Quorum&lt;/a> 是抽象機制（多數 ack 即可 commit）、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">Latency Budget&lt;/a> 是把跨 region RTT 寫進 SLO 的決策框架、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/commit-wait/" data-link-title="Commit Wait" data-link-desc="Spanner external consistency 的核心機制 — read-write transaction 拿 commit timestamp s 後等到 TT.after(s) 才 ACK、wait ≈ 2ε、付 latency tax 換 commit 順序 = real-time 順序">Commit Wait&lt;/a> 是 Spanner TrueTime 的另一段獨立延遲、不能混算同一個 latency 數字。&lt;/p>
&lt;p>Cross-region quorum 的 latency 由 voting replica 之間的網路 RTT 主導、跟 instance config 強相關：&lt;/p>
&lt;ul>
&lt;li>Regional（單 region 多 zone）：voting 在同 region 內、quorum RTT &amp;lt; 5ms&lt;/li>
&lt;li>Dual-region（同大陸）：跨大陸內、quorum RTT 10-30ms&lt;/li>
&lt;li>Multi-region（跨洲）：跨大陸或跨洲、quorum RTT 100-200ms&lt;/li>
&lt;/ul>
&lt;p>跨洲 100-200ms 是物理光速下界、不是 vendor SLA 不夠好 — Spanner / CockroachDB 同樣硬限。常見誤讀是把這 100-200ms 寫成「Spanner commit wait」、實際 commit wait 是 TrueTime 不確定區間導致的另一段 2-14ms 等待、跟 cross-region quorum 是兩個獨立的物理 cost、不能混用一個 latency 數字解釋兩者。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要面對 cross-region quorum 的訊號是「multi-region distributed SQL 的 write p99 latency 鎖在 100-200ms、不管怎麼 tune client / cache / node size 都壓不下來」。對應情境：Spanner 跨洲 multi-region instance 揭露的工程數量級（依 voting region 配置變化、不是 SLA 承諾）；CockroachDB &lt;code>SURVIVE REGION FAILURE&lt;/code> 強制 voting replica 散布到多 region、保 region 級故障 RPO=0 但 commit latency 直接吃跨 region RTT。Application 端的訊號是「跨洲 write 的 p99 跟 single-region 比是 10-20 倍、但 read（透過 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/follower-read/" data-link-title="Follower Read" data-link-desc="分散式 SQL 從 non-voting replica 讀 closed timestamp 之前的資料、不參與 Raft commit、低 latency 但 read-after-write 場景仍可能 stale">Follower Read&lt;/a>）p99 接近 single-region」。&lt;/p></description><content:encoded><![CDATA[<p>Cross-region quorum 的核心概念是「multi-region distributed SQL（Spanner multi-region instance、CockroachDB region survival）強制 voting replica 跨 region 分布、write commit 必須等多 region quorum ack」。它跟 <a href="/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">Quorum</a> 同源（後者是抽象機制）、但承擔 <em>跨 region 情境下被物理光速限定的 latency tax</em> 這個獨立語意 — 是 distributed SQL line-rate scaling 上無法 scale away 的固定支出、跟 <a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">Latency Budget</a> 共軸、跟 <a href="/blog/backend/knowledge-cards/commit-wait/" data-link-title="Commit Wait" data-link-desc="Spanner external consistency 的核心機制 — read-write transaction 拿 commit timestamp s 後等到 TT.after(s) 才 ACK、wait ≈ 2ε、付 latency tax 換 commit 順序 = real-time 順序">Commit Wait</a> 是相鄰但獨立的物理 cost。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cross-region quorum 跟相鄰卡片有清楚的角色分工 — <a href="/blog/backend/knowledge-cards/quorum/" data-link-title="Quorum" data-link-desc="分散式系統以多數節點同意作為提交或讀取有效性的門檻">Quorum</a> 是抽象機制（多數 ack 即可 commit）、<a href="/blog/backend/knowledge-cards/latency-budget/" data-link-title="Latency Budget" data-link-desc="把 user-perceived latency 拆到每個 stage 的配額、反推架構選擇">Latency Budget</a> 是把跨 region RTT 寫進 SLO 的決策框架、<a href="/blog/backend/knowledge-cards/commit-wait/" data-link-title="Commit Wait" data-link-desc="Spanner external consistency 的核心機制 — read-write transaction 拿 commit timestamp s 後等到 TT.after(s) 才 ACK、wait ≈ 2ε、付 latency tax 換 commit 順序 = real-time 順序">Commit Wait</a> 是 Spanner TrueTime 的另一段獨立延遲、不能混算同一個 latency 數字。</p>
<p>Cross-region quorum 的 latency 由 voting replica 之間的網路 RTT 主導、跟 instance config 強相關：</p>
<ul>
<li>Regional（單 region 多 zone）：voting 在同 region 內、quorum RTT &lt; 5ms</li>
<li>Dual-region（同大陸）：跨大陸內、quorum RTT 10-30ms</li>
<li>Multi-region（跨洲）：跨大陸或跨洲、quorum RTT 100-200ms</li>
</ul>
<p>跨洲 100-200ms 是物理光速下界、不是 vendor SLA 不夠好 — Spanner / CockroachDB 同樣硬限。常見誤讀是把這 100-200ms 寫成「Spanner commit wait」、實際 commit wait 是 TrueTime 不確定區間導致的另一段 2-14ms 等待、跟 cross-region quorum 是兩個獨立的物理 cost、不能混用一個 latency 數字解釋兩者。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要面對 cross-region quorum 的訊號是「multi-region distributed SQL 的 write p99 latency 鎖在 100-200ms、不管怎麼 tune client / cache / node size 都壓不下來」。對應情境：Spanner 跨洲 multi-region instance 揭露的工程數量級（依 voting region 配置變化、不是 SLA 承諾）；CockroachDB <code>SURVIVE REGION FAILURE</code> 強制 voting replica 散布到多 region、保 region 級故障 RPO=0 但 commit latency 直接吃跨 region RTT。Application 端的訊號是「跨洲 write 的 p99 跟 single-region 比是 10-20 倍、但 read（透過 <a href="/blog/backend/knowledge-cards/follower-read/" data-link-title="Follower Read" data-link-desc="分散式 SQL 從 non-voting replica 讀 closed timestamp 之前的資料、不參與 Raft commit、低 latency 但 read-after-write 場景仍可能 stale">Follower Read</a>）p99 接近 single-region」。</p>
<h2 id="設計責任">設計責任</h2>
<p>Cross-region quorum 的 latency 不能 scale away — 設計時要把它當 <em>結構性 latency</em>、不是可優化的瓶頸。判讀 instance config 是必要動作：寫密集 + 不需 region survival 的 workload 應該選 regional config、別硬上 multi-region；真的需要跨 region 強一致時、要把 write latency budget 從 single-region 的 10ms 改成跨洲 100-200ms、跟業務協商 SLO。引用 100-200ms 這條 anchor 做 capacity planning 必須先 audit 自家 instance 是哪種 config、不能套用單一基線。RTO=0 / RPO=0 跨 region 不是免費 — 它的 cost 落在 write latency、不是 dollar、要把這條 cost 寫進 sizing 文件。</p>
]]></content:encoded></item><item><title>BaaS（Backend as a Service）</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/baas/</link><pubDate>Thu, 11 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/baas/</guid><description>&lt;p>BaaS（Backend as a Service）的核心概念是把後端的常見能力 — 認證、資料庫、檔案儲存、推播、serverless function — 打包成現成模組、應用程式的前端（app / SPA）用平台 SDK 直接連上這些模組、不經過自己寫的後端服務。它讓「沒有後端工程師」的團隊能先把產品做出來、代價是資料模型、查詢能力與授權機制都沿平台的形狀生長。代表服務是 Firebase 與 Supabase。它的長期成本面接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/vendor-lock-in/" data-link-title="Vendor Lock-In" data-link-desc="說明採用供應商產品後，其 API 與格式滲入程式碼造成的退出成本">Vendor Lock-In&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>BaaS 位在交付形態光譜的中段：比全託管平台（Wix、Shopify 類）保留更多應用程式控制權（前端完全自己寫）、比自建少掉整層後端服務。它跟自建世界的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&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> 提供同類能力、差別在存取模型：自建走「client → 自己的 API → 資料庫」、BaaS 走「client → SDK → 平台資料庫」、授權邏輯從 API 層下沉到平台的安全規則裡。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合 BaaS 的訊號是產品形態為行動 app 或 SPA、後端需求集中在認證、資料同步與推播、且團隊想把後端工程延後。一個行動端的記帳 app、用 Firebase Auth 處理登入、Firestore 存帳目並即時同步多裝置、Cloud Messaging 推提醒 — 整個 MVP 沒有一行自己的後端程式。&lt;/p>
&lt;p>撞到邊界的訊號有三類：複雜查詢（跨集合報表在查詢受限的平台資料庫上變成資料複製工程）、成本曲線轉折（讀寫計費隨流量線性成長、高流量下超過自建）、安全規則失控（client 直連模型把全部授權寫進平台的規則語言、規則長到難以測試與 review）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>採用 BaaS 時的設計責任是在進場當下記錄退出路徑：資料模型沿平台特性設計（反正規化結構、平台專屬同步語意）、遷出等於重做資料層；認證可攜性要先查證（Firebase Auth 可匯出密碼雜湊、屬於少數友善案例）。授權規則要當成程式碼管理 — 進版本控制、有 review、有測試 — 而不是在 console 上長大。判斷該不該採用、以及何時該遷往自建、屬於交付形態選型的判讀。&lt;/p></description><content:encoded><![CDATA[<p>BaaS（Backend as a Service）的核心概念是把後端的常見能力 — 認證、資料庫、檔案儲存、推播、serverless function — 打包成現成模組、應用程式的前端（app / SPA）用平台 SDK 直接連上這些模組、不經過自己寫的後端服務。它讓「沒有後端工程師」的團隊能先把產品做出來、代價是資料模型、查詢能力與授權機制都沿平台的形狀生長。代表服務是 Firebase 與 Supabase。它的長期成本面接回 <a href="/blog/backend/knowledge-cards/vendor-lock-in/" data-link-title="Vendor Lock-In" data-link-desc="說明採用供應商產品後，其 API 與格式滲入程式碼造成的退出成本">Vendor Lock-In</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>BaaS 位在交付形態光譜的中段：比全託管平台（Wix、Shopify 類）保留更多應用程式控制權（前端完全自己寫）、比自建少掉整層後端服務。它跟自建世界的 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a> 與 <a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">object storage</a> 提供同類能力、差別在存取模型：自建走「client → 自己的 API → 資料庫」、BaaS 走「client → SDK → 平台資料庫」、授權邏輯從 API 層下沉到平台的安全規則裡。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合 BaaS 的訊號是產品形態為行動 app 或 SPA、後端需求集中在認證、資料同步與推播、且團隊想把後端工程延後。一個行動端的記帳 app、用 Firebase Auth 處理登入、Firestore 存帳目並即時同步多裝置、Cloud Messaging 推提醒 — 整個 MVP 沒有一行自己的後端程式。</p>
<p>撞到邊界的訊號有三類：複雜查詢（跨集合報表在查詢受限的平台資料庫上變成資料複製工程）、成本曲線轉折（讀寫計費隨流量線性成長、高流量下超過自建）、安全規則失控（client 直連模型把全部授權寫進平台的規則語言、規則長到難以測試與 review）。</p>
<h2 id="設計責任">設計責任</h2>
<p>採用 BaaS 時的設計責任是在進場當下記錄退出路徑：資料模型沿平台特性設計（反正規化結構、平台專屬同步語意）、遷出等於重做資料層；認證可攜性要先查證（Firebase Auth 可匯出密碼雜湊、屬於少數友善案例）。授權規則要當成程式碼管理 — 進版本控制、有 review、有測試 — 而不是在 console 上長大。判斷該不該採用、以及何時該遷往自建、屬於交付形態選型的判讀。</p>
]]></content:encoded></item><item><title>Serverless</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/serverless/</link><pubDate>Thu, 11 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/serverless/</guid><description>&lt;p>Serverless 的核心概念是把「伺服器的存在」從開發者的責任清單移除：程式碼以函式或請求處理單元交給平台、平台負責執行環境、擴縮與閒置歸零、費用按實際用量計（請求數、執行時間、記憶體）。名稱說的是「開發者看不到 server」、伺服器本身仍然存在 — 只是由平台調度。代表形態是 FaaS（AWS Lambda、Cloud Functions）與 serverless 化的資料庫（Aurora Serverless、Cosmos DB serverless）；相對的長駐交付形態見 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/container/" data-link-title="Container" data-link-desc="說明容器如何包裝服務、隔離依賴與影響部署方式">container&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Serverless 位在運算交付模型的光譜上：比 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/container/" data-link-title="Container" data-link-desc="說明容器如何包裝服務、隔離依賴與影響部署方式">container&lt;/a> 平台更往「平台接管」靠 — container 平台管編排、執行單元仍長駐；serverless 連長駐都交給平台、執行單元隨請求出現與消失。它跟 &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> 常被併用但責任不同：BaaS 提供現成的後端模組（認證、資料庫）、serverless 提供「自己的程式碼、別人的執行環境」。閒置歸零的特性接回 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cold-start/" data-link-title="Cold Start" data-link-desc="說明服務或快取剛啟動時尚未累積狀態造成的延遲與壓力">cold start&lt;/a> — 歸零的另一面是喚醒延遲。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>適合 serverless 的訊號是負載間歇且事件驅動：webhook 接收、圖片上傳後的縮圖處理、定時批次 — 流量為零時費用為零、突發時平台自動拉起。一個報名系統的確認信寄送、每天觸發幾百次、每次跑兩秒：常駐主機為它待命整天是浪費、serverless 按兩秒計費。&lt;/p>
&lt;p>撞到邊界的訊號有三類：執行時長上限（長任務被平台切斷）、長連線模型不合（WebSocket 類常駐需求要繞路）、以及計價曲線反轉 — 流量從間歇變成持續高檔後、按請求計費會超過長駐 instance、各家 serverless 資料庫的計價單位差異也直接影響這條曲線的位置。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>採用 serverless 時的設計責任是把「執行單元隨時消失」當前提：狀態放外部（資料庫、object storage）、本地檔案與記憶體只當單次請求的暫存；冷啟動延遲要量測並決定是否預熱；計價要建立用量模型、設帳單 alert — 按用量計費的服務、失控的迴圈或被打的 endpoint 會直接變成帳單事故。&lt;/p></description><content:encoded><![CDATA[<p>Serverless 的核心概念是把「伺服器的存在」從開發者的責任清單移除：程式碼以函式或請求處理單元交給平台、平台負責執行環境、擴縮與閒置歸零、費用按實際用量計（請求數、執行時間、記憶體）。名稱說的是「開發者看不到 server」、伺服器本身仍然存在 — 只是由平台調度。代表形態是 FaaS（AWS Lambda、Cloud Functions）與 serverless 化的資料庫（Aurora Serverless、Cosmos DB serverless）；相對的長駐交付形態見 <a href="/blog/backend/knowledge-cards/container/" data-link-title="Container" data-link-desc="說明容器如何包裝服務、隔離依賴與影響部署方式">container</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Serverless 位在運算交付模型的光譜上：比 <a href="/blog/backend/knowledge-cards/container/" data-link-title="Container" data-link-desc="說明容器如何包裝服務、隔離依賴與影響部署方式">container</a> 平台更往「平台接管」靠 — container 平台管編排、執行單元仍長駐；serverless 連長駐都交給平台、執行單元隨請求出現與消失。它跟 <a href="/blog/backend/knowledge-cards/baas/" data-link-title="BaaS（Backend as a Service）" data-link-desc="說明把認證、資料庫、檔案儲存、推播打包成現成模組、由前端 SDK 直連的後端交付形態">BaaS</a> 常被併用但責任不同：BaaS 提供現成的後端模組（認證、資料庫）、serverless 提供「自己的程式碼、別人的執行環境」。閒置歸零的特性接回 <a href="/blog/backend/knowledge-cards/cold-start/" data-link-title="Cold Start" data-link-desc="說明服務或快取剛啟動時尚未累積狀態造成的延遲與壓力">cold start</a> — 歸零的另一面是喚醒延遲。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>適合 serverless 的訊號是負載間歇且事件驅動：webhook 接收、圖片上傳後的縮圖處理、定時批次 — 流量為零時費用為零、突發時平台自動拉起。一個報名系統的確認信寄送、每天觸發幾百次、每次跑兩秒：常駐主機為它待命整天是浪費、serverless 按兩秒計費。</p>
<p>撞到邊界的訊號有三類：執行時長上限（長任務被平台切斷）、長連線模型不合（WebSocket 類常駐需求要繞路）、以及計價曲線反轉 — 流量從間歇變成持續高檔後、按請求計費會超過長駐 instance、各家 serverless 資料庫的計價單位差異也直接影響這條曲線的位置。</p>
<h2 id="設計責任">設計責任</h2>
<p>採用 serverless 時的設計責任是把「執行單元隨時消失」當前提：狀態放外部（資料庫、object storage）、本地檔案與記憶體只當單次請求的暫存；冷啟動延遲要量測並決定是否預熱；計價要建立用量模型、設帳單 alert — 按用量計費的服務、失控的迴圈或被打的 endpoint 會直接變成帳單事故。</p>
]]></content:encoded></item><item><title>並行期（Parallel Run）</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/parallel-run/</link><pubDate>Thu, 11 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/parallel-run/</guid><description>&lt;p>並行期（parallel run）的核心概念是讓新舊系統共存一段時間、用真實資料驗證新系統的正確性、再執行切換：舊系統維持 &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/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">dual write&lt;/a> 的分界在寫入路徑的控制權：寫入發生在自己的程式碼裡、可以雙寫；寫入發生在外部系統（託管平台、第三方服務）內部、插不進那條路徑、就只能單向同步 — 並行期是後者的標準驗證形態。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>並行期屬於遷移驗證的形態家族：&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">dual write&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/shadow-read/" data-link-title="Shadow Read" data-link-desc="說明正式讀取仍走舊路徑時如何暗中讀新路徑比對結果">shadow read&lt;/a> 適用於寫入路徑可控的自建系統之間、並行期適用於來源系統不可改的情境。驗證手段共用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">data reconciliation&lt;/a> — 定期比對兩邊的筆數、金額與關鍵彙總；結束點是一段 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-window/" data-link-title="Cutover Window" data-link-desc="說明正式切換發生的觀察窗口、停止條件與回退判讀範圍">cutover window&lt;/a>、由收斂且穩定的對帳差異率觸發排程。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>一個跑在託管電商平台上的店、決定遷往自建：webhook 與排程匯出把平台的新訂單持續餵進自建資料庫、對帳 job 每天比對兩邊的訂單數與金額總和、內部報表與客服查詢先改走新系統 — 顧客仍在平台下單、新系統用真實流量驗證資料轉換。健康訊號是對帳差異率逐週收斂並穩定；反向訊號是並行期拖過原定窗口仍未排 cutover — 雙系統維運、平台月費與同步管道的持有成本持續累積、並行是驗證階段、長期共存要當成明確決策而非慣性。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>進入並行期的設計責任有四件：同步管道的完整性（漏事件直接變成對帳差異、來源限流與重試要先設計）、對帳 job 與差異率門檻（沒有量化門檻就沒有「收斂」可言）、內部流量先行（報表、後台查詢先走新系統、讓驗證涵蓋真實讀取模式）、明確的結束條件 — 差異率達標後排 cutover、或在成本反轉時承認部分共存為長期形態並記錄重評條件。&lt;/p></description><content:encoded><![CDATA[<p>並行期（parallel run）的核心概念是讓新舊系統共存一段時間、用真實資料驗證新系統的正確性、再執行切換：舊系統維持 <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/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">dual write</a> 的分界在寫入路徑的控制權：寫入發生在自己的程式碼裡、可以雙寫；寫入發生在外部系統（託管平台、第三方服務）內部、插不進那條路徑、就只能單向同步 — 並行期是後者的標準驗證形態。</p>
<h2 id="概念位置">概念位置</h2>
<p>並行期屬於遷移驗證的形態家族：<a href="/blog/backend/knowledge-cards/dual-write/" data-link-title="Dual Write" data-link-desc="說明同一變更同時寫入兩個系統時的一致性風險">dual write</a> 與 <a href="/blog/backend/knowledge-cards/shadow-read/" data-link-title="Shadow Read" data-link-desc="說明正式讀取仍走舊路徑時如何暗中讀新路徑比對結果">shadow read</a> 適用於寫入路徑可控的自建系統之間、並行期適用於來源系統不可改的情境。驗證手段共用 <a href="/blog/backend/knowledge-cards/data-reconciliation/" data-link-title="Data Reconciliation" data-link-desc="說明多個資料來源不一致時如何比對、修復與留下證據">data reconciliation</a> — 定期比對兩邊的筆數、金額與關鍵彙總；結束點是一段 <a href="/blog/backend/knowledge-cards/cutover-window/" data-link-title="Cutover Window" data-link-desc="說明正式切換發生的觀察窗口、停止條件與回退判讀範圍">cutover window</a>、由收斂且穩定的對帳差異率觸發排程。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>一個跑在託管電商平台上的店、決定遷往自建：webhook 與排程匯出把平台的新訂單持續餵進自建資料庫、對帳 job 每天比對兩邊的訂單數與金額總和、內部報表與客服查詢先改走新系統 — 顧客仍在平台下單、新系統用真實流量驗證資料轉換。健康訊號是對帳差異率逐週收斂並穩定；反向訊號是並行期拖過原定窗口仍未排 cutover — 雙系統維運、平台月費與同步管道的持有成本持續累積、並行是驗證階段、長期共存要當成明確決策而非慣性。</p>
<h2 id="設計責任">設計責任</h2>
<p>進入並行期的設計責任有四件：同步管道的完整性（漏事件直接變成對帳差異、來源限流與重試要先設計）、對帳 job 與差異率門檻（沒有量化門檻就沒有「收斂」可言）、內部流量先行（報表、後台查詢先走新系統、讓驗證涵蓋真實讀取模式）、明確的結束條件 — 差異率達標後排 cutover、或在成本反轉時承認部分共存為長期形態並記錄重評條件。</p>
]]></content:encoded></item><item><title>Capability Outsourcing Depth（外包深度）</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/capability-outsourcing-depth/</link><pubDate>Sun, 14 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/capability-outsourcing-depth/</guid><description>&lt;p>外包深度的核心概念是：把一塊後端能力交出去有深淺之分、不是「全有或全無」的二元 — 同樣是「不自己寫」、把維運交出去跟把整塊能力連業務邏輯一起交出去、保留的控制權與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/vendor-lock-in/" data-link-title="Vendor Lock-In" data-link-desc="說明採用供應商產品後，其 API 與格式滲入程式碼造成的退出成本">Vendor Lock-In&lt;/a> 的退出成本差一個量級。三種深度由淺到深是 managed 基礎設施、feature SaaS 與 BaaS bundle — 這條軸只涵蓋雲端託管側、自架 OSS 或 on-prem 授權、只租控制平面的自管形態鎖定在運維 know-how 與授權、屬軸外的另一類。判斷一塊能力該外包到哪個深度、是選型時與「買還是建」並列的問題。它跟 &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> 的差別在抽象層級：BaaS 是最深那一層的具體交付形態、外包深度是涵蓋三層的判讀軸。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>外包深度位在「買 vs 建」決策的下一層：決定了某塊能力要買之後、還要決定買到多深。最淺的 managed 基礎設施只外包維運、schema 與 query 仍是自己的、跟自建世界的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database&lt;/a> 共用同一套資料模型控制權；中間的 feature SaaS 透過 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/provider-adapter/" data-link-title="Provider Adapter" data-link-desc="說明第三方服務如何被包裝成內部穩定介面">Provider Adapter&lt;/a> 消費一組 API、整塊能力的內部邏輯交給 vendor；最深的 BaaS bundle 一個 vendor 同時交付多塊能力、用整合當賣點。深度越深、保留的控制權越少、遷出時要拆解的整合面越大。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>辨識深度看「撞牆時你改得動的邊界在哪」。一個跑在 Aurora 或 Neon 上的服務撞到慢查詢、可以自己加 index、改 schema、重寫 query — 能動的邊界很寬、只有底層硬體與維運落在 vendor 手上、這是 managed 基礎設施（managed 內部還有梯度：受限的 serverless 或 BaaS 內嵌的 Postgres 可能沒有 superuser、裝不了 extension、能動的邊界比一台完整 managed 實例窄）。換成 Auth0 或 Algolia、撞到的是 vendor 沒開放的客製：它的擴展點到哪、邊界就到哪、再過去只能在它之外另搭一層 — 這是 feature SaaS、Auth0、Algolia、Stripe 在 dev-tool 端、Ragic、SurveyCake、Airtable 在同深度的 no-code 端、差別在誰來維護。最深一層撞牆時連邊界都不只一條：Supabase 把 Postgres、Auth、Storage、Realtime 用同一套身分綁在一起、想搬走資料層、得連帶拆掉它跟認證、儲存的接點 — 這是 BaaS bundle。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>選定外包深度時的設計責任是把深度對應的遷出代價先記進選型結論。managed 基礎設施遷出代價低到中、資料是標準格式、換家主要是搬資料改連線；feature SaaS 中到高、資料模型與業務規則沿 vendor 特性長出來；BaaS bundle 最高、代價落在被同一套整合綁住的能力之間、不在資料量。深度不是越淺越好 — 越深省下的整合與維運越多、bundle 的整合本身就是它的價值；責任是讓「省下多少」與「綁住多深」在同一筆帳上算清、而不是只看其中一邊。判斷一塊能力該外包到哪個深度、屬於能力級買 vs 建的選型判讀。&lt;/p></description><content:encoded><![CDATA[<p>外包深度的核心概念是：把一塊後端能力交出去有深淺之分、不是「全有或全無」的二元 — 同樣是「不自己寫」、把維運交出去跟把整塊能力連業務邏輯一起交出去、保留的控制權與 <a href="/blog/backend/knowledge-cards/vendor-lock-in/" data-link-title="Vendor Lock-In" data-link-desc="說明採用供應商產品後，其 API 與格式滲入程式碼造成的退出成本">Vendor Lock-In</a> 的退出成本差一個量級。三種深度由淺到深是 managed 基礎設施、feature SaaS 與 BaaS bundle — 這條軸只涵蓋雲端託管側、自架 OSS 或 on-prem 授權、只租控制平面的自管形態鎖定在運維 know-how 與授權、屬軸外的另一類。判斷一塊能力該外包到哪個深度、是選型時與「買還是建」並列的問題。它跟 <a href="/blog/backend/knowledge-cards/baas/" data-link-title="BaaS（Backend as a Service）" data-link-desc="說明把認證、資料庫、檔案儲存、推播打包成現成模組、由前端 SDK 直連的後端交付形態">BaaS</a> 的差別在抽象層級：BaaS 是最深那一層的具體交付形態、外包深度是涵蓋三層的判讀軸。</p>
<h2 id="概念位置">概念位置</h2>
<p>外包深度位在「買 vs 建」決策的下一層：決定了某塊能力要買之後、還要決定買到多深。最淺的 managed 基礎設施只外包維運、schema 與 query 仍是自己的、跟自建世界的 <a href="/blog/backend/knowledge-cards/database/" data-link-title="Database" data-link-desc="說明 database 在後端系統中如何承擔正式狀態、查詢與一致性責任">database</a> 共用同一套資料模型控制權；中間的 feature SaaS 透過 <a href="/blog/backend/knowledge-cards/provider-adapter/" data-link-title="Provider Adapter" data-link-desc="說明第三方服務如何被包裝成內部穩定介面">Provider Adapter</a> 消費一組 API、整塊能力的內部邏輯交給 vendor；最深的 BaaS bundle 一個 vendor 同時交付多塊能力、用整合當賣點。深度越深、保留的控制權越少、遷出時要拆解的整合面越大。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>辨識深度看「撞牆時你改得動的邊界在哪」。一個跑在 Aurora 或 Neon 上的服務撞到慢查詢、可以自己加 index、改 schema、重寫 query — 能動的邊界很寬、只有底層硬體與維運落在 vendor 手上、這是 managed 基礎設施（managed 內部還有梯度：受限的 serverless 或 BaaS 內嵌的 Postgres 可能沒有 superuser、裝不了 extension、能動的邊界比一台完整 managed 實例窄）。換成 Auth0 或 Algolia、撞到的是 vendor 沒開放的客製：它的擴展點到哪、邊界就到哪、再過去只能在它之外另搭一層 — 這是 feature SaaS、Auth0、Algolia、Stripe 在 dev-tool 端、Ragic、SurveyCake、Airtable 在同深度的 no-code 端、差別在誰來維護。最深一層撞牆時連邊界都不只一條：Supabase 把 Postgres、Auth、Storage、Realtime 用同一套身分綁在一起、想搬走資料層、得連帶拆掉它跟認證、儲存的接點 — 這是 BaaS bundle。</p>
<h2 id="設計責任">設計責任</h2>
<p>選定外包深度時的設計責任是把深度對應的遷出代價先記進選型結論。managed 基礎設施遷出代價低到中、資料是標準格式、換家主要是搬資料改連線；feature SaaS 中到高、資料模型與業務規則沿 vendor 特性長出來；BaaS bundle 最高、代價落在被同一套整合綁住的能力之間、不在資料量。深度不是越淺越好 — 越深省下的整合與維運越多、bundle 的整合本身就是它的價值；責任是讓「省下多少」與「綁住多深」在同一筆帳上算清、而不是只看其中一邊。判斷一塊能力該外包到哪個深度、屬於能力級買 vs 建的選型判讀。</p>
]]></content:encoded></item><item><title>Processing Semantics</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/processing-semantics/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/processing-semantics/</guid><description>&lt;p>Processing semantics 的核心概念是「consumer 處理事件後，業務結果是否正確」。broker 把訊息送到只代表投遞成功，consumer 的副作用是否正確是另一層責任。它回答副作用能否承受重複、亂序與部分失敗。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Processing semantics 位在 delivery 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/recovery-semantics/" data-link-title="Recovery Semantics" data-link-desc="說明事件處理失敗後能否透過 replay、checkpoint 與補償重建正確狀態並驗證">recovery semantics&lt;/a> 之間。投遞語意把訊息交給 consumer，處理語意決定這次處理是否讓系統狀態正確，依賴 &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;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>同樣是 at-least-once 投遞，寄信 consumer 重複會寄出兩封、開 invoice 重複會重複計帳、search index sync 重複則天生冪等。副作用形狀不同，能承受的處理語意就不同。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時對每個副作用標明能否承受重複、亂序與部分失敗。承受不了的補 idempotency key 或 dedup store，把處理結果穩定在一次。&lt;/p></description><content:encoded><![CDATA[<p>Processing semantics 的核心概念是「consumer 處理事件後，業務結果是否正確」。broker 把訊息送到只代表投遞成功，consumer 的副作用是否正確是另一層責任。它回答副作用能否承受重複、亂序與部分失敗。 可先對照 <a href="/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">Delivery Semantics</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Processing semantics 位在 delivery 與 <a href="/blog/backend/knowledge-cards/recovery-semantics/" data-link-title="Recovery Semantics" data-link-desc="說明事件處理失敗後能否透過 replay、checkpoint 與補償重建正確狀態並驗證">recovery semantics</a> 之間。投遞語意把訊息交給 consumer，處理語意決定這次處理是否讓系統狀態正確，依賴 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 把重複投遞收斂成一次結果。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>同樣是 at-least-once 投遞，寄信 consumer 重複會寄出兩封、開 invoice 重複會重複計帳、search index sync 重複則天生冪等。副作用形狀不同，能承受的處理語意就不同。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時對每個副作用標明能否承受重複、亂序與部分失敗。承受不了的補 idempotency key 或 dedup store，把處理結果穩定在一次。</p>
]]></content:encoded></item><item><title>Recovery Semantics</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/recovery-semantics/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/recovery-semantics/</guid><description>&lt;p>Recovery semantics 的核心概念是「處理失敗或資料錯亂後，系統能否重建正確狀態並驗證」。它回答 replay、checkpoint、offset 與補償流程是否可重播、可稽核，是 queue 三層語意中最後一層。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/processing-semantics/" data-link-title="Processing Semantics" data-link-desc="說明 consumer 處理事件後業務結果是否正確，與投遞成功分屬不同責任">Processing Semantics&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Recovery semantics 接在 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/processing-semantics/" data-link-title="Processing Semantics" data-link-desc="說明 consumer 處理事件後業務結果是否正確，與投遞成功分屬不同責任">processing semantics&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;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間處理流程如何記錄可恢復進度">checkpoint&lt;/a> 與可控的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/replay-window/" data-link-title="Replay Window" data-link-desc="說明事件可重播的時間或 offset 範圍邊界，由 retention 與 checkpoint 決定">replay window&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>consumer 處理到一半 crash，重啟後從哪個 offset 接續、會不會重做已完成的副作用，由恢復語意決定。能任意 offset replay 的事件流（Kafka）跟 ack 後即刪的工作佇列（RabbitMQ）恢復能力不同。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時把 replay 範圍、checkpoint 粒度與補償路徑寫進 runbook，並保留驗證證據（replay 前後的計數與抽樣），讓恢復後能確認狀態正確而非只是「跑完了」。&lt;/p></description><content:encoded><![CDATA[<p>Recovery semantics 的核心概念是「處理失敗或資料錯亂後，系統能否重建正確狀態並驗證」。它回答 replay、checkpoint、offset 與補償流程是否可重播、可稽核，是 queue 三層語意中最後一層。 可先對照 <a href="/blog/backend/knowledge-cards/processing-semantics/" data-link-title="Processing Semantics" data-link-desc="說明 consumer 處理事件後業務結果是否正確，與投遞成功分屬不同責任">Processing Semantics</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Recovery semantics 接在 <a href="/blog/backend/knowledge-cards/processing-semantics/" data-link-title="Processing Semantics" data-link-desc="說明 consumer 處理事件後業務結果是否正確，與投遞成功分屬不同責任">processing semantics</a> 之後。處理語意保證單次結果正確，恢復語意保證出錯後能回到正確狀態，依賴 <a href="/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">offset</a>、<a href="/blog/backend/knowledge-cards/checkpoint/" data-link-title="Checkpoint" data-link-desc="說明長時間處理流程如何記錄可恢復進度">checkpoint</a> 與可控的 <a href="/blog/backend/knowledge-cards/replay-window/" data-link-title="Replay Window" data-link-desc="說明事件可重播的時間或 offset 範圍邊界，由 retention 與 checkpoint 決定">replay window</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>consumer 處理到一半 crash，重啟後從哪個 offset 接續、會不會重做已完成的副作用，由恢復語意決定。能任意 offset replay 的事件流（Kafka）跟 ack 後即刪的工作佇列（RabbitMQ）恢復能力不同。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時把 replay 範圍、checkpoint 粒度與補償路徑寫進 runbook，並保留驗證證據（replay 前後的計數與抽樣），讓恢復後能確認狀態正確而非只是「跑完了」。</p>
]]></content:encoded></item><item><title>Replay Window</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/replay-window/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/replay-window/</guid><description>&lt;p>Replay window 的核心概念是「事件能往回重播的範圍」。它由 broker 的 retention 與 consumer 的 checkpoint 共同界定，決定出事後能補送多久以前的事件。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/recovery-semantics/" data-link-title="Recovery Semantics" data-link-desc="說明事件處理失敗後能否透過 replay、checkpoint 與補償重建正確狀態並驗證">Recovery Semantics&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Replay window 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/recovery-semantics/" data-link-title="Recovery Semantics" data-link-desc="說明事件處理失敗後能否透過 replay、checkpoint 與補償重建正確狀態並驗證">recovery semantics&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> 或時間區間：超出 retention 的事件已被刪除、無法重播，補償就要改走資料庫或上游來源。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>Kafka 設 7 天 retention，replay window 就是 7 天，第 8 天的錯誤要重算就找不到原始事件；SQS 最長保留 14 天、Pub/Sub 預設 7 天，managed 佇列的 replay window 由保留期上限決定。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時把 replay window 對齊事故偵測到修復的最長時間。偵測延遲若可能超過 retention，就拉長保留期或在下游留可重算的來源，避免事件已過期才發現要補。&lt;/p></description><content:encoded><![CDATA[<p>Replay window 的核心概念是「事件能往回重播的範圍」。它由 broker 的 retention 與 consumer 的 checkpoint 共同界定，決定出事後能補送多久以前的事件。 可先對照 <a href="/blog/backend/knowledge-cards/recovery-semantics/" data-link-title="Recovery Semantics" data-link-desc="說明事件處理失敗後能否透過 replay、checkpoint 與補償重建正確狀態並驗證">Recovery Semantics</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Replay window 是 <a href="/blog/backend/knowledge-cards/recovery-semantics/" data-link-title="Recovery Semantics" data-link-desc="說明事件處理失敗後能否透過 replay、checkpoint 與補償重建正確狀態並驗證">recovery semantics</a> 的具體邊界。它把「可恢復」量化成一段 <a href="/blog/backend/knowledge-cards/offset/" data-link-title="Offset" data-link-desc="說明 consumer 在事件流中的讀取位置與重放基準">offset</a> 或時間區間：超出 retention 的事件已被刪除、無法重播，補償就要改走資料庫或上游來源。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>Kafka 設 7 天 retention，replay window 就是 7 天，第 8 天的錯誤要重算就找不到原始事件；SQS 最長保留 14 天、Pub/Sub 預設 7 天，managed 佇列的 replay window 由保留期上限決定。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時把 replay window 對齊事故偵測到修復的最長時間。偵測延遲若可能超過 retention，就拉長保留期或在下游留可重算的來源，避免事件已過期才發現要補。</p>
]]></content:encoded></item><item><title>Consumer Pause</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-pause/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/consumer-pause/</guid><description>&lt;p>Consumer pause 的核心概念是「主動停止消費，止住錯誤副作用繼續擴大」。當下游故障、毒訊息卡關或處理邏輯有 bug 時，暫停消費讓事件留在 broker、爭取修復時間，是事故當下的控制手段。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Consumer pause 是事故處理的閥門。暫停期間 &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/replay-window/" data-link-title="Replay Window" data-link-desc="說明事件可重播的時間或 offset 範圍邊界，由 retention 與 checkpoint 決定">replay window&lt;/a> 內，前提是暫停時間短於 retention，恢復後可從原 offset 接續。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>下游資料庫過載時，繼續消費只會放大寫入壓力與重試風暴；暫停消費讓壓力停在 broker，下游恢復後再 resume。毒訊息卡住整個 partition 時，暫停加上把該訊息送 &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;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時讓消費可被快速暫停與恢復，並把 pause、drain、resume 的決策與時點記進 decision log，避免暫停後忘記恢復造成 lag 無聲累積。&lt;/p></description><content:encoded><![CDATA[<p>Consumer pause 的核心概念是「主動停止消費，止住錯誤副作用繼續擴大」。當下游故障、毒訊息卡關或處理邏輯有 bug 時，暫停消費讓事件留在 broker、爭取修復時間，是事故當下的控制手段。 可先對照 <a href="/blog/backend/knowledge-cards/consumer-lag/" data-link-title="Consumer Lag" data-link-desc="說明 consumer lag 如何反映訊息堆積、處理能力與容量風險">Consumer Lag</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Consumer pause 是事故處理的閥門。暫停期間 <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/replay-window/" data-link-title="Replay Window" data-link-desc="說明事件可重播的時間或 offset 範圍邊界，由 retention 與 checkpoint 決定">replay window</a> 內，前提是暫停時間短於 retention，恢復後可從原 offset 接續。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>下游資料庫過載時，繼續消費只會放大寫入壓力與重試風暴；暫停消費讓壓力停在 broker，下游恢復後再 resume。毒訊息卡住整個 partition 時，暫停加上把該訊息送 <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> 比硬重試更快止血。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時讓消費可被快速暫停與恢復，並把 pause、drain、resume 的決策與時點記進 decision log，避免暫停後忘記恢復造成 lag 無聲累積。</p>
]]></content:encoded></item><item><title>Event Schema Compatibility</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/event-schema-compatibility/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/event-schema-compatibility/</guid><description>&lt;p>Event schema compatibility 的核心概念是「event schema 改版後，新舊 producer 與 consumer 能否互通」。它用 forward、backward、full 三種相容性等級界定演進規則，是跨服務事件契約能安全升級的前提。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Event schema compatibility 是事件契約的演進規則，直接影響 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/processing-semantics/" data-link-title="Processing Semantics" data-link-desc="說明 consumer 處理事件後業務結果是否正確，與投遞成功分屬不同責任">processing semantics&lt;/a>：schema 不相容會讓 consumer 解析失敗、變成 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/poison-message/" data-link-title="Poison Message" data-link-desc="說明特定訊息內容如何穩定造成 consumer 失敗">poison message&lt;/a>。backward 相容讓新 consumer 讀舊事件、forward 相容讓舊 consumer 讀新事件、full 兩者都要。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>producer 加一個必填欄位但未設預設值，舊 consumer 解析失敗、訊息卡在 partition；改成可選欄位或帶預設值就維持 backward 相容。Kafka 用 Schema Registry enforce compatibility level、Pub/Sub 用 schema enforcement，RabbitMQ 與 NATS 多半靠應用層約定。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時先定相容性等級再演進 schema：高頻跨服務契約用 full 或 backward、內部單向通訊可放寬。新增欄位帶預設、刪欄位分兩步（先停用再移除），避免一次破壞性改版打掛下游。&lt;/p></description><content:encoded><![CDATA[<p>Event schema compatibility 的核心概念是「event schema 改版後，新舊 producer 與 consumer 能否互通」。它用 forward、backward、full 三種相容性等級界定演進規則，是跨服務事件契約能安全升級的前提。 可先對照 <a href="/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">Delivery Semantics</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Event schema compatibility 是事件契約的演進規則，直接影響 <a href="/blog/backend/knowledge-cards/processing-semantics/" data-link-title="Processing Semantics" data-link-desc="說明 consumer 處理事件後業務結果是否正確，與投遞成功分屬不同責任">processing semantics</a>：schema 不相容會讓 consumer 解析失敗、變成 <a href="/blog/backend/knowledge-cards/poison-message/" data-link-title="Poison Message" data-link-desc="說明特定訊息內容如何穩定造成 consumer 失敗">poison message</a>。backward 相容讓新 consumer 讀舊事件、forward 相容讓舊 consumer 讀新事件、full 兩者都要。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>producer 加一個必填欄位但未設預設值，舊 consumer 解析失敗、訊息卡在 partition；改成可選欄位或帶預設值就維持 backward 相容。Kafka 用 Schema Registry enforce compatibility level、Pub/Sub 用 schema enforcement，RabbitMQ 與 NATS 多半靠應用層約定。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時先定相容性等級再演進 schema：高頻跨服務契約用 full 或 backward、內部單向通訊可放寬。新增欄位帶預設、刪欄位分兩步（先停用再移除），避免一次破壞性改版打掛下游。</p>
]]></content:encoded></item><item><title>DLQ Drain</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/dlq-drain/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/dlq-drain/</guid><description>&lt;p>DLQ drain 的核心概念是「把 dead-letter queue 累積的訊息重新處理或清空的受控流程」。訊息進 DLQ 只是被隔離，drain 決定它們最終被修復重送、丟棄還是歸檔，是 DLQ 不無限長大的收尾步驟。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>DLQ drain 接在 &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/poison-message-quarantine/" data-link-title="Poison-Message Quarantine" data-link-desc="說明把毒訊息從主處理路徑隔離出來的機制，讓正常訊息繼續前進">poison-message quarantine&lt;/a> 隔離訊息之後。drain 前要先確認根因已修，否則重送只會再次失敗、訊息又繞回 DLQ。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>DLQ depth 持續上升代表有未處理的失敗累積；修好 consumer bug 後，用 redrive（SQS）或重新 publish 把 DLQ 訊息送回主 queue 重處理。無法修復的（過期、業務上已失效）則歸檔後刪除，而非放著佔空間。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時把 drain 當受控操作：先驗根因已解、分批重送、邊送邊看成功率，並把 drain 的時點、批量與結果記進 decision log，避免一次全量重送打垮剛恢復的下游。&lt;/p></description><content:encoded><![CDATA[<p>DLQ drain 的核心概念是「把 dead-letter queue 累積的訊息重新處理或清空的受控流程」。訊息進 DLQ 只是被隔離，drain 決定它們最終被修復重送、丟棄還是歸檔，是 DLQ 不無限長大的收尾步驟。 可先對照 <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>。</p>
<h2 id="概念位置">概念位置</h2>
<p>DLQ drain 接在 <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-quarantine/" data-link-title="Poison-Message Quarantine" data-link-desc="說明把毒訊息從主處理路徑隔離出來的機制，讓正常訊息繼續前進">poison-message quarantine</a> 隔離訊息之後。drain 前要先確認根因已修，否則重送只會再次失敗、訊息又繞回 DLQ。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>DLQ depth 持續上升代表有未處理的失敗累積；修好 consumer bug 後，用 redrive（SQS）或重新 publish 把 DLQ 訊息送回主 queue 重處理。無法修復的（過期、業務上已失效）則歸檔後刪除，而非放著佔空間。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時把 drain 當受控操作：先驗根因已解、分批重送、邊送邊看成功率，並把 drain 的時點、批量與結果記進 decision log，避免一次全量重送打垮剛恢復的下游。</p>
]]></content:encoded></item><item><title>Poison-Message Quarantine</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/poison-message-quarantine/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/poison-message-quarantine/</guid><description>&lt;p>Poison-message quarantine 的核心概念是「把穩定造成失敗的訊息從主處理路徑移開」。它是對 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/poison-message/" data-link-title="Poison Message" data-link-desc="說明特定訊息內容如何穩定造成 consumer 失敗">poison message&lt;/a> 這個現象的處置：用投遞次數上限把壞訊息送進隔離區，讓正常訊息繼續前進。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/poison-message/" data-link-title="Poison Message" data-link-desc="說明特定訊息內容如何穩定造成 consumer 失敗">Poison Message&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Poison-message quarantine 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/poison-message/" data-link-title="Poison Message" data-link-desc="說明特定訊息內容如何穩定造成 consumer 失敗">poison message&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>（隔離區）之間的機制層。它靠 max delivery / maxReceiveCount 計數，超過門檻就把訊息移出主 queue，後續走 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/dlq-drain/" data-link-title="DLQ Drain" data-link-desc="說明把 dead-letter queue 累積的訊息重新處理或排空的受控流程">DLQ drain&lt;/a> 修復或歸檔。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>同一訊息 redelivery 次數持續累加而從不成功，就是隔離訊號。SQS 用 redrive policy 的 maxReceiveCount、RabbitMQ 用 DLX + 投遞計數、Kafka 多半在 consumer 端自行計數後送隔離 topic。沒有隔離機制時，一則毒訊息會卡住整個 partition 或 queue。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時把投遞次數上限設在「足夠容忍暫時性失敗、又不會無限重試」之間，並在隔離時保留原始 payload 與失敗原因，讓後續診斷與 drain 有足夠證據。&lt;/p></description><content:encoded><![CDATA[<p>Poison-message quarantine 的核心概念是「把穩定造成失敗的訊息從主處理路徑移開」。它是對 <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/poison-message/" data-link-title="Poison Message" data-link-desc="說明特定訊息內容如何穩定造成 consumer 失敗">Poison Message</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Poison-message quarantine 是 <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/dead-letter-queue/" data-link-title="Dead-Letter Queue" data-link-desc="說明 dead-letter queue 如何隔離多次處理失敗的訊息">dead-letter queue</a>（隔離區）之間的機制層。它靠 max delivery / maxReceiveCount 計數，超過門檻就把訊息移出主 queue，後續走 <a href="/blog/backend/knowledge-cards/dlq-drain/" data-link-title="DLQ Drain" data-link-desc="說明把 dead-letter queue 累積的訊息重新處理或排空的受控流程">DLQ drain</a> 修復或歸檔。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>同一訊息 redelivery 次數持續累加而從不成功，就是隔離訊號。SQS 用 redrive policy 的 maxReceiveCount、RabbitMQ 用 DLX + 投遞計數、Kafka 多半在 consumer 端自行計數後送隔離 topic。沒有隔離機制時，一則毒訊息會卡住整個 partition 或 queue。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時把投遞次數上限設在「足夠容忍暫時性失敗、又不會無限重試」之間，並在隔離時保留原始 payload 與失敗原因，讓後續診斷與 drain 有足夠證據。</p>
]]></content:encoded></item><item><title>Fencing Token</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/fencing-token/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/fencing-token/</guid><description>&lt;p>Fencing token 的核心概念是「每次取鎖發一個單調遞增的編號，持鎖者對下游的每個寫入都帶上它，下游記住見過的最大編號並拒絕比它小的寫入」。它把互斥的正確性從鎖本身下沉到擁有正式狀態的那一層。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-lock/" data-link-title="Distributed Lock" data-link-desc="跨機器跨 process 的互斥鎖、用 lease 機制處理 holder 失效">Distributed Lock&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Fencing token 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/distributed-lock/" data-link-title="Distributed Lock" data-link-desc="跨機器跨 process 的互斥鎖、用 lease 機制處理 holder 失效">distributed lock&lt;/a> 在「鎖可能因 GC 暫停、網路分割而失效」這個固有時序窗口下的補強機制。鎖只負責減少競爭，fencing token 讓下游成為最終仲裁者，與 &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/distributed-lock/" data-link-title="Distributed Lock" data-link-desc="跨機器跨 process 的互斥鎖、用 lease 機制處理 holder 失效">Distributed Lock&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 fencing token 的訊號是「鎖牽涉正確性、雙寫會造成金錢或資料損壞」。節點 A 取得鎖後發生長 GC 暫停、租約到期被 B 接手，A 醒來仍以為持鎖而寫入：A 帶 token 33、B 帶 token 34，下游接受過 34 後就拒絕 33。ZooKeeper 的 zxid、etcd 的 revision、資料庫的版本欄位都可以充當 fencing token。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要確認下游有能力驗證 token（記住最大值並拒絕較小者）。下游若無法條件寫入（例如第三方 API），fencing token 無法成立，這時要把互斥下沉到資料層的唯一約束或條件更新。token 的生成要保證取鎖動作本身嚴格遞增，用原子計數器或鎖服務序號實作。&lt;/p></description><content:encoded><![CDATA[<p>Fencing token 的核心概念是「每次取鎖發一個單調遞增的編號，持鎖者對下游的每個寫入都帶上它，下游記住見過的最大編號並拒絕比它小的寫入」。它把互斥的正確性從鎖本身下沉到擁有正式狀態的那一層。 可先對照 <a href="/blog/backend/knowledge-cards/distributed-lock/" data-link-title="Distributed Lock" data-link-desc="跨機器跨 process 的互斥鎖、用 lease 機制處理 holder 失效">Distributed Lock</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Fencing token 是 <a href="/blog/backend/knowledge-cards/distributed-lock/" data-link-title="Distributed Lock" data-link-desc="跨機器跨 process 的互斥鎖、用 lease 機制處理 holder 失效">distributed lock</a> 在「鎖可能因 GC 暫停、網路分割而失效」這個固有時序窗口下的補強機制。鎖只負責減少競爭，fencing token 讓下游成為最終仲裁者，與 <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 同屬「即使協調層失效，結果仍正確」的防線。 可先對照 <a href="/blog/backend/knowledge-cards/distributed-lock/" data-link-title="Distributed Lock" data-link-desc="跨機器跨 process 的互斥鎖、用 lease 機制處理 holder 失效">Distributed Lock</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 fencing token 的訊號是「鎖牽涉正確性、雙寫會造成金錢或資料損壞」。節點 A 取得鎖後發生長 GC 暫停、租約到期被 B 接手，A 醒來仍以為持鎖而寫入：A 帶 token 33、B 帶 token 34，下游接受過 34 後就拒絕 33。ZooKeeper 的 zxid、etcd 的 revision、資料庫的版本欄位都可以充當 fencing token。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要確認下游有能力驗證 token（記住最大值並拒絕較小者）。下游若無法條件寫入（例如第三方 API），fencing token 無法成立，這時要把互斥下沉到資料層的唯一約束或條件更新。token 的生成要保證取鎖動作本身嚴格遞增，用原子計數器或鎖服務序號實作。</p>
]]></content:encoded></item><item><title>Cache Penetration</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-penetration/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/cache-penetration/</guid><description>&lt;p>Cache penetration 的核心概念是「查詢必定不存在的 key，讓請求全部 miss 並穿透到資料庫，把快取的保護作用繞過」。它跟 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">cache stampede&lt;/a> 不同：stampede 是同一個熱門 key 同時失效，penetration 是大量不同的不存在 key 從不命中。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">Cache Stampede&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Cache penetration 是快取放大面的攻擊向量，與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">cache stampede&lt;/a>、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/thundering-herd/" data-link-title="Thundering Herd" data-link-desc="說明大量工作同時被喚醒或同時競爭資源時的尖峰風險">thundering herd&lt;/a> 並列「快取從保護層變成放大層」的失效模式。它的觸發源是惡意或意外的不存在 key 枚舉，主要防護是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/negative-cache/" data-link-title="Negative Cache" data-link-desc="說明把「查無此 key」的結果也快取一小段時間，擋掉重複穿透的防護與代價">negative cache&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>，與 stampede 的 soft-TTL / single-flight 防護路徑不同。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/negative-cache/" data-link-title="Negative Cache" data-link-desc="說明把「查無此 key」的結果也快取一小段時間，擋掉重複穿透的防護與代價">Negative Cache&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>判讀訊號是「大量查詢不存在的 key、回源 QPS 飆但 cache 命中率不變」。攻擊者用不連續的 id、構造的非法 slug 枚舉，每個查詢都 miss、穿透到資料庫。電商商品頁被查詢大量不存在的商品 id，資料庫被迫對每個都做一次「查無此商品」的查詢，快取完全沒擋住。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要把不存在的結果也納入快取（negative cache），並對回源路徑加 rate limit 與請求來源限制。判讀時要先區分這是 penetration（不存在的 key 枚舉）還是 stampede（熱門 key 同時失效），兩者防護不同，誤套解法會無效。&lt;/p></description><content:encoded><![CDATA[<p>Cache penetration 的核心概念是「查詢必定不存在的 key，讓請求全部 miss 並穿透到資料庫，把快取的保護作用繞過」。它跟 <a href="/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">cache stampede</a> 不同：stampede 是同一個熱門 key 同時失效，penetration 是大量不同的不存在 key 從不命中。 可先對照 <a href="/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">Cache Stampede</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Cache penetration 是快取放大面的攻擊向量，與 <a href="/blog/backend/knowledge-cards/cache-stampede/" data-link-title="Cache Stampede" data-link-desc="說明快取同時失效時大量 request 如何壓垮正式來源">cache stampede</a>、<a href="/blog/backend/knowledge-cards/thundering-herd/" data-link-title="Thundering Herd" data-link-desc="說明大量工作同時被喚醒或同時競爭資源時的尖峰風險">thundering herd</a> 並列「快取從保護層變成放大層」的失效模式。它的觸發源是惡意或意外的不存在 key 枚舉，主要防護是 <a href="/blog/backend/knowledge-cards/negative-cache/" data-link-title="Negative Cache" data-link-desc="說明把「查無此 key」的結果也快取一小段時間，擋掉重複穿透的防護與代價">negative cache</a> 與回源 <a href="/blog/backend/knowledge-cards/rate-limit/" data-link-title="Rate Limit" data-link-desc="說明限流如何保護服務入口、下游依賴與租戶公平性">rate limit</a>，與 stampede 的 soft-TTL / single-flight 防護路徑不同。 可先對照 <a href="/blog/backend/knowledge-cards/negative-cache/" data-link-title="Negative Cache" data-link-desc="說明把「查無此 key」的結果也快取一小段時間，擋掉重複穿透的防護與代價">Negative Cache</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>判讀訊號是「大量查詢不存在的 key、回源 QPS 飆但 cache 命中率不變」。攻擊者用不連續的 id、構造的非法 slug 枚舉，每個查詢都 miss、穿透到資料庫。電商商品頁被查詢大量不存在的商品 id，資料庫被迫對每個都做一次「查無此商品」的查詢，快取完全沒擋住。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要把不存在的結果也納入快取（negative cache），並對回源路徑加 rate limit 與請求來源限制。判讀時要先區分這是 penetration（不存在的 key 枚舉）還是 stampede（熱門 key 同時失效），兩者防護不同，誤套解法會無效。</p>
]]></content:encoded></item><item><title>Negative Cache</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/negative-cache/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/negative-cache/</guid><description>&lt;p>Negative cache 的核心概念是「把『查無此 key』這個結果也快取一小段時間，讓重複的不存在查詢不再每次都穿透到資料庫」。它是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-penetration/" data-link-title="Cache Penetration" data-link-desc="說明查詢必定不存在的 key 繞過快取直接打向 origin 的弱點與防護">cache penetration&lt;/a> 的主要防護工具。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-penetration/" data-link-title="Cache Penetration" data-link-desc="說明查詢必定不存在的 key 繞過快取直接打向 origin 的弱點與防護">Cache Penetration&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Negative cache 是 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-penetration/" data-link-title="Cache Penetration" data-link-desc="說明查詢必定不存在的 key 繞過快取直接打向 origin 的弱點與防護">cache penetration&lt;/a> 防護的主工具，與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-hit-miss/" data-link-title="Cache Hit / Miss" data-link-desc="說明快取命中與未命中如何影響讀取成本與下游壓力">cache hit / miss&lt;/a> 的差別是它快取的是「miss 這個結果」而非資料本身。它跟一般快取共用 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/ttl/" data-link-title="TTL" data-link-desc="說明資料過期時間如何影響快取新鮮度、成本與一致性">TTL&lt;/a> 機制，但 TTL 策略相反：要短到避免遮擋真實資料、又長到擋住重複穿透。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cache-penetration/" data-link-title="Cache Penetration" data-link-desc="說明查詢必定不存在的 key 繞過快取直接打向 origin 的弱點與防護">Cache Penetration&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要 negative cache 的訊號是「大量重複查詢同一批不存在的 key、回源被無謂打爆」。把「查無此商品」用很短的 TTL 快取，第二次以後的相同查詢直接命中 negative 項、不再打資料庫。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>negative cache 自身有代價：真實資料建立後要等 negative 項過期才會被命中，TTL 太長會讓新上架資料短暫不可見。設計時 TTL 要明顯短於正常資料的快取週期，並在資料寫入路徑主動失效對應的 negative 項，避免新資料被「查無」結果遮擋。&lt;/p></description><content:encoded><![CDATA[<p>Negative cache 的核心概念是「把『查無此 key』這個結果也快取一小段時間，讓重複的不存在查詢不再每次都穿透到資料庫」。它是 <a href="/blog/backend/knowledge-cards/cache-penetration/" data-link-title="Cache Penetration" data-link-desc="說明查詢必定不存在的 key 繞過快取直接打向 origin 的弱點與防護">cache penetration</a> 的主要防護工具。 可先對照 <a href="/blog/backend/knowledge-cards/cache-penetration/" data-link-title="Cache Penetration" data-link-desc="說明查詢必定不存在的 key 繞過快取直接打向 origin 的弱點與防護">Cache Penetration</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Negative cache 是 <a href="/blog/backend/knowledge-cards/cache-penetration/" data-link-title="Cache Penetration" data-link-desc="說明查詢必定不存在的 key 繞過快取直接打向 origin 的弱點與防護">cache penetration</a> 防護的主工具，與 <a href="/blog/backend/knowledge-cards/cache-hit-miss/" data-link-title="Cache Hit / Miss" data-link-desc="說明快取命中與未命中如何影響讀取成本與下游壓力">cache hit / miss</a> 的差別是它快取的是「miss 這個結果」而非資料本身。它跟一般快取共用 <a href="/blog/backend/knowledge-cards/ttl/" data-link-title="TTL" data-link-desc="說明資料過期時間如何影響快取新鮮度、成本與一致性">TTL</a> 機制，但 TTL 策略相反：要短到避免遮擋真實資料、又長到擋住重複穿透。 可先對照 <a href="/blog/backend/knowledge-cards/cache-penetration/" data-link-title="Cache Penetration" data-link-desc="說明查詢必定不存在的 key 繞過快取直接打向 origin 的弱點與防護">Cache Penetration</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要 negative cache 的訊號是「大量重複查詢同一批不存在的 key、回源被無謂打爆」。把「查無此商品」用很短的 TTL 快取，第二次以後的相同查詢直接命中 negative 項、不再打資料庫。</p>
<h2 id="設計責任">設計責任</h2>
<p>negative cache 自身有代價：真實資料建立後要等 negative 項過期才會被命中，TTL 太長會讓新上架資料短暫不可見。設計時 TTL 要明顯短於正常資料的快取週期，並在資料寫入路徑主動失效對應的 negative 項，避免新資料被「查無」結果遮擋。</p>
]]></content:encoded></item><item><title>Visibility Timeout</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/visibility-timeout/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/visibility-timeout/</guid><description>&lt;p>Visibility timeout 的核心概念是「訊息被一個 consumer 取走後，在一段時間內對其他 consumer 不可見；consumer 在這段時間內處理完並刪除訊息，否則 timeout 後訊息重新變可見、被重新投遞」。它是任務佇列模型（如 SQS）實作 at-least-once 的核心機制。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Visibility timeout 是 &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> 在「拉取式佇列」上的一種實作：consumer 沒有顯式長連線，而是靠「取走訊息 + 限時處理 + 刪除確認」三步完成 ack。處理超時等同 nack，訊息回到可見狀態觸發 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/redelivery/" data-link-title="Redelivery" data-link-desc="說明 broker 重新投遞訊息時 consumer 需要承擔的重入責任">redelivery&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/redelivery/" data-link-title="Redelivery" data-link-desc="說明 broker 重新投遞訊息時 consumer 需要承擔的重入責任">Redelivery&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要調整 visibility timeout 的訊號是「同一訊息被處理多次、或處理完的訊息仍被重投」。timeout 設太短，慢任務還沒處理完就被重新投遞給別的 consumer 造成重複處理；設太長，crash 的 consumer 持有的訊息要等很久才被接手。SQS 的 visibility timeout 預設 30 秒、可依任務耗時調整，長任務用 ChangeMessageVisibility 動態延長。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要把 visibility timeout 對著任務耗時分布校準：明顯長於正常處理時間以避免誤重投，又不能長到讓失效 consumer 的訊息卡住太久。長尾任務用動態延長（heartbeat 式續期），並確認處理是 idempotent，因為 at-least-once 下重複投遞無法完全避免。&lt;/p></description><content:encoded><![CDATA[<p>Visibility timeout 的核心概念是「訊息被一個 consumer 取走後，在一段時間內對其他 consumer 不可見；consumer 在這段時間內處理完並刪除訊息，否則 timeout 後訊息重新變可見、被重新投遞」。它是任務佇列模型（如 SQS）實作 at-least-once 的核心機制。 可先對照 <a href="/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">ack / nack</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Visibility timeout 是 <a href="/blog/backend/knowledge-cards/ack-nack/" data-link-title="Ack / Nack" data-link-desc="說明 consumer 如何向 broker 回報訊息處理結果">ack / nack</a> 在「拉取式佇列」上的一種實作：consumer 沒有顯式長連線，而是靠「取走訊息 + 限時處理 + 刪除確認」三步完成 ack。處理超時等同 nack，訊息回到可見狀態觸發 <a href="/blog/backend/knowledge-cards/redelivery/" data-link-title="Redelivery" data-link-desc="說明 broker 重新投遞訊息時 consumer 需要承擔的重入責任">redelivery</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/redelivery/" data-link-title="Redelivery" data-link-desc="說明 broker 重新投遞訊息時 consumer 需要承擔的重入責任">Redelivery</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要調整 visibility timeout 的訊號是「同一訊息被處理多次、或處理完的訊息仍被重投」。timeout 設太短，慢任務還沒處理完就被重新投遞給別的 consumer 造成重複處理；設太長，crash 的 consumer 持有的訊息要等很久才被接手。SQS 的 visibility timeout 預設 30 秒、可依任務耗時調整，長任務用 ChangeMessageVisibility 動態延長。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要把 visibility timeout 對著任務耗時分布校準：明顯長於正常處理時間以避免誤重投，又不能長到讓失效 consumer 的訊息卡住太久。長尾任務用動態延長（heartbeat 式續期），並確認處理是 idempotent，因為 at-least-once 下重複投遞無法完全避免。</p>
]]></content:encoded></item><item><title>Exactly-Once</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/exactly-once/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/exactly-once/</guid><description>&lt;p>Exactly-once 的核心概念是「一則訊息對最終結果剛好生效一次，不漏也不重複」。它是三種投遞語意中最難實作、代價最高的一種，多數系統實際採用的是 at-least-once 投遞加上消費端 idempotency，用較低成本達到等效結果。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Exactly-once 是 &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> 的一種，與 at-most-once、at-least-once 並列。真正的 end-to-end exactly-once 需要 broker、producer 與 consumer 在同一套交易邊界內協作（如 Kafka 的 transactional producer + read-committed），成本高且邊界窄。實務上更常用 at-least-once + &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/duplicate-delivery/" data-link-title="Duplicate Delivery" data-link-desc="說明同一個訊息被處理多次時如何保持結果穩定">duplicate delivery&lt;/a>，把「不重複」的責任放到消費端。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>把 exactly-once 當預設目標是常見的過度設計訊號。多數業務（出貨、扣款、通知）真正需要的是「重複處理不造成重複副作用」，這用 idempotency key 就能達成，不需要 broker 層的 exactly-once 承諾。誤把 at-least-once 系統當成 exactly-once 依賴、消費端不做去重，則是反向的危險假設。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時先問「重複生效的代價是什麼」：可重建投影的事件重複只增加成本、用 at-least-once 即可；會扣款出貨的事件要靠消費端 idempotency 或唯一約束擋重複，而非寄望 broker 的 exactly-once。只有在跨系統交易必須原子、且願意承擔吞吐與複雜度代價時，才採真正的 exactly-once。&lt;/p></description><content:encoded><![CDATA[<p>Exactly-once 的核心概念是「一則訊息對最終結果剛好生效一次，不漏也不重複」。它是三種投遞語意中最難實作、代價最高的一種，多數系統實際採用的是 at-least-once 投遞加上消費端 idempotency，用較低成本達到等效結果。 可先對照 <a href="/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">Delivery Semantics</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Exactly-once 是 <a href="/blog/backend/knowledge-cards/delivery-semantics/" data-link-title="Delivery Semantics" data-link-desc="說明事件投遞語意如何定義遺失、重複、順序與補償策略">delivery semantics</a> 的一種，與 at-most-once、at-least-once 並列。真正的 end-to-end exactly-once 需要 broker、producer 與 consumer 在同一套交易邊界內協作（如 Kafka 的 transactional producer + read-committed），成本高且邊界窄。實務上更常用 at-least-once + <a href="/blog/backend/knowledge-cards/idempotency/" data-link-title="Idempotency" data-link-desc="說明同一操作執行多次時如何保持結果一致">idempotency</a> 處理 <a href="/blog/backend/knowledge-cards/duplicate-delivery/" data-link-title="Duplicate Delivery" data-link-desc="說明同一個訊息被處理多次時如何保持結果穩定">duplicate delivery</a>，把「不重複」的責任放到消費端。 可先對照 <a href="/blog/backend/knowledge-cards/duplicate-delivery/" data-link-title="Duplicate Delivery" data-link-desc="說明同一個訊息被處理多次時如何保持結果穩定">Duplicate Delivery</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>把 exactly-once 當預設目標是常見的過度設計訊號。多數業務（出貨、扣款、通知）真正需要的是「重複處理不造成重複副作用」，這用 idempotency key 就能達成，不需要 broker 層的 exactly-once 承諾。誤把 at-least-once 系統當成 exactly-once 依賴、消費端不做去重，則是反向的危險假設。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時先問「重複生效的代價是什麼」：可重建投影的事件重複只增加成本、用 at-least-once 即可；會扣款出貨的事件要靠消費端 idempotency 或唯一約束擋重複，而非寄望 broker 的 exactly-once。只有在跨系統交易必須原子、且願意承擔吞吐與複雜度代價時，才採真正的 exactly-once。</p>
]]></content:encoded></item><item><title>Admin Endpoint</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/admin-endpoint/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/admin-endpoint/</guid><description>&lt;p>Admin Endpoint 的核心概念是「只給受信任角色使用的高權限入口」。它通常處理管理、調整、匯出或修正資料的操作。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">Alert Fatigue&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Admin Endpoint 位在內部網路、身份驗證與授權層之後，和一般 public API 分開管理。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">Alert Fatigue&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 admin endpoint 的訊號是操作會影響大量使用者、資料完整性或金流狀態，且需要額外稽核與來源限制。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>後台修改使用者角色、停用帳號、調整活動規則、匯出敏感報表，都應透過 admin endpoint 完成，並保留 audit log。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義更嚴格的身份驗證、授權、來源限制、操作追蹤與錯誤回應。Admin Endpoint 的失敗後果通常比 public API 更高。&lt;/p></description><content:encoded><![CDATA[<p>Admin Endpoint 的核心概念是「只給受信任角色使用的高權限入口」。它通常處理管理、調整、匯出或修正資料的操作。 可先對照 <a href="/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">Alert Fatigue</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Admin Endpoint 位在內部網路、身份驗證與授權層之後，和一般 public API 分開管理。 可先對照 <a href="/blog/backend/knowledge-cards/alert-fatigue/" data-link-title="Alert Fatigue" data-link-desc="說明過多低品質告警如何降低 on-call 反應品質">Alert Fatigue</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 admin endpoint 的訊號是操作會影響大量使用者、資料完整性或金流狀態，且需要額外稽核與來源限制。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>後台修改使用者角色、停用帳號、調整活動規則、匯出敏感報表，都應透過 admin endpoint 完成，並保留 audit log。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義更嚴格的身份驗證、授權、來源限制、操作追蹤與錯誤回應。Admin Endpoint 的失敗後果通常比 public API 更高。</p>
]]></content:encoded></item><item><title>API Contract</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/api-contract/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/api-contract/</guid><description>&lt;p>API Contract 的核心概念是「client 與 service 對 request / response 行為達成一致」。它定義欄位、錯誤、版本相容與破壞性變更。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>API Contract 位在 client、&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> 與 application 之間。當外部呼叫者依賴穩定格式時，就需要這種 contract。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 API contract 的訊號是不同團隊會共同整合，且欄位、錯誤碼或版本變動可能直接影響外部使用者。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>查詢訂單、建立付款、更新會員資料或回傳錯誤資訊，都應遵守 API contract，並以 contract test 驗證。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>API Contract 要定義欄位名稱、必要欄位、預設值、錯誤格式與相容版本。破壞性變更需要受控發布與回復路徑。&lt;/p></description><content:encoded><![CDATA[<p>API Contract 的核心概念是「client 與 service 對 request / response 行為達成一致」。它定義欄位、錯誤、版本相容與破壞性變更。 可先對照 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>API Contract 位在 client、<a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a> 與 application 之間。當外部呼叫者依賴穩定格式時，就需要這種 contract。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 API contract 的訊號是不同團隊會共同整合，且欄位、錯誤碼或版本變動可能直接影響外部使用者。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>查詢訂單、建立付款、更新會員資料或回傳錯誤資訊，都應遵守 API contract，並以 contract test 驗證。</p>
<h2 id="設計責任">設計責任</h2>
<p>API Contract 要定義欄位名稱、必要欄位、預設值、錯誤格式與相容版本。破壞性變更需要受控發布與回復路徑。</p>
]]></content:encoded></item><item><title>Authentication Middleware</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/authentication-middleware/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/authentication-middleware/</guid><description>&lt;p>Authentication Middleware 的核心概念是「在 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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Authentication Middleware 位在 transport layer 與 handler 之間。它負責把 token、session、signature 或其他身份憑證轉成已驗證的 caller context。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 authentication middleware 的訊號是多數 handler 都要先確認身份，且驗證規則應集中管理。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>&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> 驗證 bearer token、內部服務驗證 service token、webhook 驗證簽章，都屬於 authentication middleware 的責任範圍。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Authentication Middleware 要處理憑證提取、驗證失敗回應、context 寫入與錯誤分類，不應混入業務邏輯。&lt;/p></description><content:encoded><![CDATA[<p>Authentication Middleware 的核心概念是「在 request 進入業務處理前，先確認呼叫者是誰」。 可先對照 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Authentication Middleware 位在 transport layer 與 handler 之間。它負責把 token、session、signature 或其他身份憑證轉成已驗證的 caller context。 可先對照 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 authentication middleware 的訊號是多數 handler 都要先確認身份，且驗證規則應集中管理。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p><a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a> 驗證 bearer token、內部服務驗證 service token、webhook 驗證簽章，都屬於 authentication middleware 的責任範圍。</p>
<h2 id="設計責任">設計責任</h2>
<p>Authentication Middleware 要處理憑證提取、驗證失敗回應、context 寫入與錯誤分類，不應混入業務邏輯。</p>
]]></content:encoded></item><item><title>Authorization Middleware</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/authorization-middleware/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/authorization-middleware/</guid><description>&lt;p>Authorization Middleware 的核心概念是「在 request 進入業務處理前，先確認呼叫者能不能做這件事」。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Authorization Middleware 位在 authentication 之後、業務 handler 之前。它依角色、資源或 tenant 來判斷可否操作。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 authorization middleware 的訊號是很多 handler 都在重複做權限檢查，且權限規則需要一致。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>admin 操作、資源 owner 檢查、tenant boundary 檢查與欄位級權限，都常放在 authorization middleware。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Authorization Middleware 要定義決策輸入、拒絕回應、稽核欄位與錯誤分類，不應把 policy 分散到各個 handler。&lt;/p></description><content:encoded><![CDATA[<p>Authorization Middleware 的核心概念是「在 request 進入業務處理前，先確認呼叫者能不能做這件事」。 可先對照 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Authorization Middleware 位在 authentication 之後、業務 handler 之前。它依角色、資源或 tenant 來判斷可否操作。 可先對照 <a href="/blog/backend/knowledge-cards/authorization/" data-link-title="Authorization" data-link-desc="說明授權如何判斷誰能對哪些資源執行哪些操作">Authorization</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 authorization middleware 的訊號是很多 handler 都在重複做權限檢查，且權限規則需要一致。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>admin 操作、資源 owner 檢查、tenant boundary 檢查與欄位級權限，都常放在 authorization middleware。</p>
<h2 id="設計責任">設計責任</h2>
<p>Authorization Middleware 要定義決策輸入、拒絕回應、稽核欄位與錯誤分類，不應把 policy 分散到各個 handler。</p>
]]></content:encoded></item><item><title>Boundary Contract</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/contract/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/contract/</guid><description>&lt;p>Boundary Contract 的核心概念是「邊界兩端共同承認的約定」。它描述不同系統、元件或流程在互相協作時，需要遵守的共同規則。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Boundary Contract 位在 client 與 service、service 與 service、程式與平台之間。當兩端都需要依同一份規則運作時，就需要 contract 來避免含糊地帶。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 boundary contract 的訊號包括：不同團隊共同整合、版本需要相容、欄位變更可能影響下游、健康檢查與接流量條件要明確。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>API contract 會定義欄位名稱、必要欄位、錯誤格式與相容版本；deployment contract 會定義 readiness、shutdown、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">resource limit&lt;/a>；queue contract 會定義 ack、重試與重複投遞行為；load balancer contract 會定義流量切換、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">health check&lt;/a> 與排空行為。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Boundary Contract 設計要清楚定義版本、相容性、破壞性變更、驗證方式與回復流程。若 contract 不穩，應搭配 contract test、&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;/p></description><content:encoded><![CDATA[<p>Boundary Contract 的核心概念是「邊界兩端共同承認的約定」。它描述不同系統、元件或流程在互相協作時，需要遵守的共同規則。 可先對照 <a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Boundary Contract 位在 client 與 service、service 與 service、程式與平台之間。當兩端都需要依同一份規則運作時，就需要 contract 來避免含糊地帶。 可先對照 <a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 boundary contract 的訊號包括：不同團隊共同整合、版本需要相容、欄位變更可能影響下游、健康檢查與接流量條件要明確。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>API contract 會定義欄位名稱、必要欄位、錯誤格式與相容版本；deployment contract 會定義 readiness、shutdown、<a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining</a> 與 <a href="/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">resource limit</a>；queue contract 會定義 ack、重試與重複投遞行為；load balancer contract 會定義流量切換、<a href="/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">health check</a> 與排空行為。</p>
<h2 id="設計責任">設計責任</h2>
<p>Boundary Contract 設計要清楚定義版本、相容性、破壞性變更、驗證方式與回復流程。若 contract 不穩，應搭配 contract test、<a href="/blog/backend/knowledge-cards/release-gate/" data-link-title="Release Gate" data-link-desc="說明變更在正式釋出前如何通過或阻擋">Release Gate</a> 與文件化規則。</p>
]]></content:encoded></item><item><title>Credential</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/credential/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/credential/</guid><description>&lt;p>Credential 的核心概念是「讓主體能證明自己並取得存取權的秘密資料」。常見 credential 包含 password、API key、token、private key、service account secret 與 database credential。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">Cutover / Switchover&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Credential 位在 authentication、authorization、secret management 與 service-to-service access 的交界。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">Cutover / Switchover&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 credential 管理的訊號包括：多個服務共用高權限帳號、需要定期輪替、需要撤銷、或需要在不同環境使用不同存取權。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>登入用 credential 要有過期與撤銷；database credential 要依服務分離；webhook secret 要能驗證來源；內部服務 credential 要配合 mTLS 或 signed request。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Credential 設計要包含保存方式、權限範圍、輪替、撤銷、稽核與事故回復。原則上應遵守 least privilege，避免單一 credential 擁有過大權限。&lt;/p></description><content:encoded><![CDATA[<p>Credential 的核心概念是「讓主體能證明自己並取得存取權的秘密資料」。常見 credential 包含 password、API key、token、private key、service account secret 與 database credential。 可先對照 <a href="/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">Cutover / Switchover</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Credential 位在 authentication、authorization、secret management 與 service-to-service access 的交界。 可先對照 <a href="/blog/backend/knowledge-cards/cutover-switchover/" data-link-title="Cutover / Switchover" data-link-desc="說明遷移期間如何把正式流量切到新路徑">Cutover / Switchover</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 credential 管理的訊號包括：多個服務共用高權限帳號、需要定期輪替、需要撤銷、或需要在不同環境使用不同存取權。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>登入用 credential 要有過期與撤銷；database credential 要依服務分離；webhook secret 要能驗證來源；內部服務 credential 要配合 mTLS 或 signed request。</p>
<h2 id="設計責任">設計責任</h2>
<p>Credential 設計要包含保存方式、權限範圍、輪替、撤銷、稽核與事故回復。原則上應遵守 least privilege，避免單一 credential 擁有過大權限。</p>
]]></content:encoded></item><item><title>Deployment Contract</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/deployment-contract/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/deployment-contract/</guid><description>&lt;p>Deployment Contract 的核心概念是「application 與平台對啟動、存活、接流量與停止方式達成一致」。它把服務生命週期變成可預期的協作規則。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Deployment Contract 位在 application、container、Kubernetes、systemd 與 rollout control 之間。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 deployment contract 的訊號是發版、擴容、回滾或停止流程會影響流量與狀態保存。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>readiness、shutdown、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">resource limit&lt;/a> 都屬於 deployment contract。實際發版節奏與批次切換則交給 &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> 或 cutover 類卡片處理。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Deployment Contract 要明確定義何時可接流量、何時應停止接流量、資源不足時如何回應，以及變更失敗時如何回復。&lt;/p></description><content:encoded><![CDATA[<p>Deployment Contract 的核心概念是「application 與平台對啟動、存活、接流量與停止方式達成一致」。它把服務生命週期變成可預期的協作規則。 可先對照 <a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Deployment Contract 位在 application、container、Kubernetes、systemd 與 rollout control 之間。 可先對照 <a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">Draining</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 deployment contract 的訊號是發版、擴容、回滾或停止流程會影響流量與狀態保存。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>readiness、shutdown、<a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining</a> 與 <a href="/blog/backend/knowledge-cards/resource-limit/" data-link-title="Resource Limit" data-link-desc="說明服務可使用的 CPU、memory 與相關資源上限如何影響行為">resource limit</a> 都屬於 deployment contract。實際發版節奏與批次切換則交給 <a href="/blog/backend/knowledge-cards/rolling-update/" data-link-title="Rolling Update" data-link-desc="說明逐批替換服務版本的發版策略與風險控制">rolling update</a> 或 cutover 類卡片處理。</p>
<h2 id="設計責任">設計責任</h2>
<p>Deployment Contract 要明確定義何時可接流量、何時應停止接流量、資源不足時如何回應，以及變更失敗時如何回復。</p>
]]></content:encoded></item><item><title>Diagnostic Endpoint</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/diagnostic-endpoint/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/diagnostic-endpoint/</guid><description>&lt;p>Diagnostic Endpoint 的核心概念是「讓平台或工程師查詢服務狀態，但不暴露業務資料」。它包含 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">health check&lt;/a>、readiness、metrics snapshot、debug info 等入口。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Diagnostic Endpoint 位在運維系統、負載平衡器、監控工具與 application 之間。它通常不承擔產品功能，而是承擔操作判斷。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">Health Check&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 diagnostic endpoint 的訊號是平台要判斷服務是否可接流量，或工程師需要快速確認特定狀態，但不想翻 log。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">health check&lt;/a>、readiness 檢查、liveness 檢查、debug status、版本資訊與依賴健康狀態，都可能透過 diagnostic endpoint 暴露。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要限制可見資訊、避免透露敏感設定，並把用途與 public API 明確分開。Diagnostic Endpoint 應優先服務平台決策，而不是人手排障的便利性。&lt;/p></description><content:encoded><![CDATA[<p>Diagnostic Endpoint 的核心概念是「讓平台或工程師查詢服務狀態，但不暴露業務資料」。它包含 <a href="/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">health check</a>、readiness、metrics snapshot、debug info 等入口。</p>
<h2 id="概念位置">概念位置</h2>
<p>Diagnostic Endpoint 位在運維系統、負載平衡器、監控工具與 application 之間。它通常不承擔產品功能，而是承擔操作判斷。 可先對照 <a href="/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">Health Check</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 diagnostic endpoint 的訊號是平台要判斷服務是否可接流量，或工程師需要快速確認特定狀態，但不想翻 log。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p><a href="/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">health check</a>、readiness 檢查、liveness 檢查、debug status、版本資訊與依賴健康狀態，都可能透過 diagnostic endpoint 暴露。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要限制可見資訊、避免透露敏感設定，並把用途與 public API 明確分開。Diagnostic Endpoint 應優先服務平台決策，而不是人手排障的便利性。</p>
]]></content:encoded></item><item><title>Integration Adapter</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/adapter/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/adapter/</guid><description>&lt;p>Integration Adapter 的核心概念是「把外部系統的介面轉成 application 需要的形狀」。它是 service boundary 與具體技術之間的轉譯層。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Integration Adapter 位在 application port 與外部服務之間。repository adapter、provider adapter、notification adapter 都屬於這個角色。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 integration adapter 的訊號包括：外部系統介面常變、錯誤碼不一致、同一個功能需要支援多個供應商、業務邏輯不應直接耦合外部介面細節。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>資料庫 adapter 負責 SQL row mapping 與錯誤轉換；付款 adapter 負責 provider API 與內部訂單狀態對齊；通知 adapter 負責把 domain event 轉成 email、push 或 webhook payload。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Integration Adapter 要隔離介面差異、做錯誤分類、保留觀測欄位、避免把業務規則塞進整合層。若 adapter 過厚，應把純轉換和流程控制分開。&lt;/p></description><content:encoded><![CDATA[<p>Integration Adapter 的核心概念是「把外部系統的介面轉成 application 需要的形狀」。它是 service boundary 與具體技術之間的轉譯層。 可先對照 <a href="/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Integration Adapter 位在 application port 與外部服務之間。repository adapter、provider adapter、notification adapter 都屬於這個角色。 可先對照 <a href="/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 integration adapter 的訊號包括：外部系統介面常變、錯誤碼不一致、同一個功能需要支援多個供應商、業務邏輯不應直接耦合外部介面細節。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>資料庫 adapter 負責 SQL row mapping 與錯誤轉換；付款 adapter 負責 provider API 與內部訂單狀態對齊；通知 adapter 負責把 domain event 轉成 email、push 或 webhook payload。</p>
<h2 id="設計責任">設計責任</h2>
<p>Integration Adapter 要隔離介面差異、做錯誤分類、保留觀測欄位、避免把業務規則塞進整合層。若 adapter 過厚，應把純轉換和流程控制分開。</p>
]]></content:encoded></item><item><title>Internal Endpoint</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/internal-endpoint/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/internal-endpoint/</guid><description>&lt;p>Internal Endpoint 的核心概念是「只供系統內部服務彼此呼叫的入口」。它不是公開給外部 client 的功能入口。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Internal Endpoint 位在 service discovery、internal network、&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> 與 application 之間，並可能受到 &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> 影響。它通常依賴封閉網段、服務身份與內部流量控制。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 internal endpoint 的訊號是多個服務之間要交換資料，但不希望這些入口暴露到外部網路。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>內部訂單同步、跨服務查詢、background worker 呼叫下游系統，或 control plane 對 service 下發設定，都會使用 internal endpoint。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要定義內部網路邊界、授權方式、服務發現與變更時的回復策略。Internal Endpoint 的暴露範圍應比 public API 更嚴格。&lt;/p></description><content:encoded><![CDATA[<p>Internal Endpoint 的核心概念是「只供系統內部服務彼此呼叫的入口」。它不是公開給外部 client 的功能入口。 可先對照 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Internal Endpoint 位在 service discovery、internal network、<a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a> 與 application 之間，並可能受到 <a href="/blog/backend/knowledge-cards/request-routing/" data-link-title="Request Routing" data-link-desc="說明入口流量如何依規則被導向不同服務或處理路徑">Request Routing</a> 影響。它通常依賴封閉網段、服務身份與內部流量控制。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 internal endpoint 的訊號是多個服務之間要交換資料，但不希望這些入口暴露到外部網路。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>內部訂單同步、跨服務查詢、background worker 呼叫下游系統，或 control plane 對 service 下發設定，都會使用 internal endpoint。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要定義內部網路邊界、授權方式、服務發現與變更時的回復策略。Internal Endpoint 的暴露範圍應比 public API 更嚴格。</p>
]]></content:encoded></item><item><title>Load Balancer Contract</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/load-balancer-contract/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/load-balancer-contract/</guid><description>&lt;p>Load Balancer Contract 的核心概念是「服務如何告訴流量入口自己能否安全接流量」。它描述 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">health check&lt;/a>、排空、切流與超時行為。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Load Balancer Contract 位在 application、load balancer、ingress 與 service discovery 之間。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">Health Check&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 load balancer contract 的訊號是流量分散、rolling update、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining&lt;/a> 或 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">idle timeout&lt;/a> 直接影響使用者請求。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">health check&lt;/a>、readiness、&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining&lt;/a> 與 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">idle timeout&lt;/a> 都屬於 load balancer contract；&lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/sticky-session/" data-link-title="Sticky Session" data-link-desc="說明同一 client 如何在一段時間內持續命中同一個後端實例">sticky session&lt;/a> 則是另一種負載分派策略，應獨立理解。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Load Balancer Contract 要定義什麼情況可接新流量、什麼情況要排空、切換需要等待多久，以及健康檢查失敗後的處理方式。&lt;/p></description><content:encoded><![CDATA[<p>Load Balancer Contract 的核心概念是「服務如何告訴流量入口自己能否安全接流量」。它描述 <a href="/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">health check</a>、排空、切流與超時行為。</p>
<h2 id="概念位置">概念位置</h2>
<p>Load Balancer Contract 位在 application、load balancer、ingress 與 service discovery 之間。 可先對照 <a href="/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">Health Check</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 load balancer contract 的訊號是流量分散、rolling update、<a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining</a> 或 <a href="/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">idle timeout</a> 直接影響使用者請求。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p><a href="/blog/backend/knowledge-cards/health-check/" data-link-title="Health Check" data-link-desc="說明服務如何對外提供可供平台判斷狀態的健康回應">health check</a>、readiness、<a href="/blog/backend/knowledge-cards/draining/" data-link-title="Draining" data-link-desc="說明服務如何先停止接收新流量，再讓既有工作完成">draining</a> 與 <a href="/blog/backend/knowledge-cards/idle-timeout/" data-link-title="Idle Timeout" data-link-desc="說明連線或會話在多久沒有活動後應該被回收">idle timeout</a> 都屬於 load balancer contract；<a href="/blog/backend/knowledge-cards/sticky-session/" data-link-title="Sticky Session" data-link-desc="說明同一 client 如何在一段時間內持續命中同一個後端實例">sticky session</a> 則是另一種負載分派策略，應獨立理解。</p>
<h2 id="設計責任">設計責任</h2>
<p>Load Balancer Contract 要定義什麼情況可接新流量、什麼情況要排空、切換需要等待多久，以及健康檢查失敗後的處理方式。</p>
]]></content:encoded></item><item><title>Message Protocol</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/message-protocol/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/message-protocol/</guid><description>&lt;p>Message Protocol 的核心概念是「producer 與 consumer 對訊息格式、處理順序與失敗結果達成一致」。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">Metric Cardinality&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Message Protocol 位在 producer、broker 與 consumer 之間。它適用於 queue、stream 與事件傳遞。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">Metric Cardinality&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 message protocol 的訊號是工作離開 request 後仍要被處理，而且需要明確的 schema、重試語意與去重責任。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>訂單事件、付款事件、通知事件與分析事件都需要 message protocol。消息格式變更時，producer 與 consumer 都要能解讀版本演進。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Message Protocol 要定義欄位結構、版本相容、錯誤處理與重播安全。它與 queue contract 不同，前者偏向資料交換語意，後者偏向交付保證。&lt;/p></description><content:encoded><![CDATA[<p>Message Protocol 的核心概念是「producer 與 consumer 對訊息格式、處理順序與失敗結果達成一致」。 可先對照 <a href="/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">Metric Cardinality</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Message Protocol 位在 producer、broker 與 consumer 之間。它適用於 queue、stream 與事件傳遞。 可先對照 <a href="/blog/backend/knowledge-cards/metric-cardinality/" data-link-title="Metric Cardinality" data-link-desc="說明 metric label 組合數量如何影響觀測成本與查詢穩定性">Metric Cardinality</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 message protocol 的訊號是工作離開 request 後仍要被處理，而且需要明確的 schema、重試語意與去重責任。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>訂單事件、付款事件、通知事件與分析事件都需要 message protocol。消息格式變更時，producer 與 consumer 都要能解讀版本演進。</p>
<h2 id="設計責任">設計責任</h2>
<p>Message Protocol 要定義欄位結構、版本相容、錯誤處理與重播安全。它與 queue contract 不同，前者偏向資料交換語意，後者偏向交付保證。</p>
]]></content:encoded></item><item><title>Notification Adapter</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/notification-adapter/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/notification-adapter/</guid><description>&lt;p>Notification Adapter 的核心概念是「把 domain event 或業務狀態，轉成 email、push、webhook 或其他通知格式」。 可先對照 &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;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Notification Adapter 位在 application 與通知渠道之間。它負責把內部事件轉成適合發送的外部 payload。 可先對照 &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;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 notification adapter 的訊號是同一個事件要送到多種通知渠道，且各渠道格式、限制與失敗行為不同。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>付款完成後寄送 email、訂單更新後送 push、事件變更後發 webhook，通常都由 notification adapter 負責。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Notification Adapter 要處理 payload mapping、模板選擇、渠道限制、發送失敗與重試責任，避免通知細節污染業務流程。&lt;/p></description><content:encoded><![CDATA[<p>Notification Adapter 的核心概念是「把 domain event 或業務狀態，轉成 email、push、webhook 或其他通知格式」。 可先對照 <a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">Object Storage</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Notification Adapter 位在 application 與通知渠道之間。它負責把內部事件轉成適合發送的外部 payload。 可先對照 <a href="/blog/backend/knowledge-cards/object-storage/" data-link-title="Object Storage" data-link-desc="說明大型非結構化檔案的保存、存取與生命週期管理">Object Storage</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 notification adapter 的訊號是同一個事件要送到多種通知渠道，且各渠道格式、限制與失敗行為不同。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>付款完成後寄送 email、訂單更新後送 push、事件變更後發 webhook，通常都由 notification adapter 負責。</p>
<h2 id="設計責任">設計責任</h2>
<p>Notification Adapter 要處理 payload mapping、模板選擇、渠道限制、發送失敗與重試責任，避免通知細節污染業務流程。</p>
]]></content:encoded></item><item><title>Observability Middleware</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/observability-middleware/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/observability-middleware/</guid><description>&lt;p>Observability Middleware 的核心概念是「在 request 進入與離開 handler 的過程中，補上可觀測欄位與上下文」。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">Offline Catch-up&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Observability Middleware 位在 transport layer 與業務 handler 之間。它通常負責 request id、trace context、log context 與 timing。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">Offline Catch-up&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 observability middleware 的訊號是很多 handler 都需要相同的追蹤欄位與可查詢上下文。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>request id 注入、trace context 傳遞、latency 記錄與結束時的操作 log，都屬於 observability middleware 的責任。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Observability Middleware 要穩定傳遞 context、避免打斷 error chain，並讓後續 log、metric、trace 可以共用欄位。&lt;/p></description><content:encoded><![CDATA[<p>Observability Middleware 的核心概念是「在 request 進入與離開 handler 的過程中，補上可觀測欄位與上下文」。 可先對照 <a href="/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">Offline Catch-up</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Observability Middleware 位在 transport layer 與業務 handler 之間。它通常負責 request id、trace context、log context 與 timing。 可先對照 <a href="/blog/backend/knowledge-cards/offline-catchup/" data-link-title="Offline Catch-up" data-link-desc="說明訂閱者離線後如何補回缺失事件或狀態">Offline Catch-up</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 observability middleware 的訊號是很多 handler 都需要相同的追蹤欄位與可查詢上下文。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>request id 注入、trace context 傳遞、latency 記錄與結束時的操作 log，都屬於 observability middleware 的責任。</p>
<h2 id="設計責任">設計責任</h2>
<p>Observability Middleware 要穩定傳遞 context、避免打斷 error chain，並讓後續 log、metric、trace 可以共用欄位。</p>
]]></content:encoded></item><item><title>Provider Adapter</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/provider-adapter/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/provider-adapter/</guid><description>&lt;p>Provider Adapter 的核心概念是「把外部供應商的 API、錯誤與限制，轉成 application 需要的形狀」。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Provider Adapter 位在 application 與 payment、notification、storage、identity 等第三方服務之間。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 provider adapter 的訊號是同一個功能可能切換供應商，或第三方 API 經常變動、錯誤碼不一致、回應格式不穩定。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>付款 provider adapter、簡訊 provider adapter、email provider adapter 都是 provider adapter 的例子。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Provider Adapter 要隔離外部 API 差異、標準化錯誤、保留關聯欄位，並確保供應商更換不會直接擾動業務邏輯。&lt;/p></description><content:encoded><![CDATA[<p>Provider Adapter 的核心概念是「把外部供應商的 API、錯誤與限制，轉成 application 需要的形狀」。 可先對照 <a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">Pub/Sub</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Provider Adapter 位在 application 與 payment、notification、storage、identity 等第三方服務之間。 可先對照 <a href="/blog/backend/knowledge-cards/pub-sub/" data-link-title="Pub/Sub" data-link-desc="說明 publish-subscribe 如何把事件即時分發給多個訂閱者">Pub/Sub</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 provider adapter 的訊號是同一個功能可能切換供應商，或第三方 API 經常變動、錯誤碼不一致、回應格式不穩定。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>付款 provider adapter、簡訊 provider adapter、email provider adapter 都是 provider adapter 的例子。</p>
<h2 id="設計責任">設計責任</h2>
<p>Provider Adapter 要隔離外部 API 差異、標準化錯誤、保留關聯欄位，並確保供應商更換不會直接擾動業務邏輯。</p>
]]></content:encoded></item><item><title>Public API Endpoint</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/public-api-endpoint/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/public-api-endpoint/</guid><description>&lt;p>Public API Endpoint 的核心概念是「外部 client 直接呼叫服務時，所經過的穩定入口」。它承載產品功能對外的 request / response 邊界。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Public API Endpoint 位在 client、&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> 與 load balancer 之間。它通常是最需要版本穩定、文件清楚與錯誤回應一致的入口。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 public API endpoint 的訊號是產品功能要直接暴露給使用者、合作夥伴或 SDK，且需要清楚的授權、節流與回應格式。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>查詢訂單、建立付款、更新會員資料或取得 dashboard 資料，通常都會暴露成 public API endpoint，並搭配 authentication、authorization 與 rate limit。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>設計時要維持 request / response contract、版本相容、錯誤碼穩定與觀測欄位一致。Public API Endpoint 不應混入管理操作或內部調試責任。&lt;/p></description><content:encoded><![CDATA[<p>Public API Endpoint 的核心概念是「外部 client 直接呼叫服務時，所經過的穩定入口」。它承載產品功能對外的 request / response 邊界。 可先對照 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Public API Endpoint 位在 client、<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> 與 load balancer 之間。它通常是最需要版本穩定、文件清楚與錯誤回應一致的入口。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 public API endpoint 的訊號是產品功能要直接暴露給使用者、合作夥伴或 SDK，且需要清楚的授權、節流與回應格式。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>查詢訂單、建立付款、更新會員資料或取得 dashboard 資料，通常都會暴露成 public API endpoint，並搭配 authentication、authorization 與 rate limit。</p>
<h2 id="設計責任">設計責任</h2>
<p>設計時要維持 request / response contract、版本相容、錯誤碼穩定與觀測欄位一致。Public API Endpoint 不應混入管理操作或內部調試責任。</p>
]]></content:encoded></item><item><title>Queue Contract</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/queue-contract/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/queue-contract/</guid><description>&lt;p>Queue Contract 的核心概念是「producer、queue 與 consumer 對工作如何被確認與重送達成一致」。它描述的是交付語意，而不是單純的格式。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Queue Contract 位在 producer、broker 與 consumer 之間。當工作要可靠排隊與重試時，就需要清楚的 contract。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 queue contract 的訊號是工作可能重試、可能重複投遞，且 consumer 需要知道確認失敗後會發生什麼。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>ack / nack、retry、dead-letter、duplicate delivery 與 redelivery 都屬於 queue contract 的範圍。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Queue Contract 要定義確認語意、重試策略、重送條件、隔離方式與去重責任，避免 broker 與 consumer 對失敗結果理解不同。&lt;/p></description><content:encoded><![CDATA[<p>Queue Contract 的核心概念是「producer、queue 與 consumer 對工作如何被確認與重送達成一致」。它描述的是交付語意，而不是單純的格式。 可先對照 <a href="/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">Queue Depth</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Queue Contract 位在 producer、broker 與 consumer 之間。當工作要可靠排隊與重試時，就需要清楚的 contract。 可先對照 <a href="/blog/backend/knowledge-cards/queue-depth/" data-link-title="Queue Depth" data-link-desc="說明 queue 中等待處理的訊息數如何反映 backlog 與容量壓力">Queue Depth</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 queue contract 的訊號是工作可能重試、可能重複投遞，且 consumer 需要知道確認失敗後會發生什麼。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>ack / nack、retry、dead-letter、duplicate delivery 與 redelivery 都屬於 queue contract 的範圍。</p>
<h2 id="設計責任">設計責任</h2>
<p>Queue Contract 要定義確認語意、重試策略、重送條件、隔離方式與去重責任，避免 broker 與 consumer 對失敗結果理解不同。</p>
]]></content:encoded></item><item><title>Repository Adapter</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/repository-adapter/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/repository-adapter/</guid><description>&lt;p>Repository Adapter 的核心概念是「把 application 的 repository port 轉成資料庫或其他持久化存取方式」。 可先對照 &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>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Repository Adapter 位在 application 與 database 之間。它處理 row mapping、查詢組合與錯誤轉換。 可先對照 &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>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 repository adapter 的訊號是 domain 模型不能直接依賴 SQL 細節，但 application 需要穩定地讀寫正式狀態。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>訂單 repository、會員 repository、付款紀錄 repository 都是 repository adapter 的例子。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Repository Adapter 要處理資料映射、一致性邊界、錯誤分類與 contract test，避免把 SQL 細節滲透到業務層。&lt;/p></description><content:encoded><![CDATA[<p>Repository Adapter 的核心概念是「把 application 的 repository port 轉成資料庫或其他持久化存取方式」。 可先對照 <a href="/blog/backend/knowledge-cards/request-id/" data-link-title="Request ID" data-link-desc="說明單次 request 的識別碼如何支援 log 搜尋與問題定位">Request ID</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Repository Adapter 位在 application 與 database 之間。它處理 row mapping、查詢組合與錯誤轉換。 可先對照 <a href="/blog/backend/knowledge-cards/request-id/" data-link-title="Request ID" data-link-desc="說明單次 request 的識別碼如何支援 log 搜尋與問題定位">Request ID</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 repository adapter 的訊號是 domain 模型不能直接依賴 SQL 細節，但 application 需要穩定地讀寫正式狀態。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>訂單 repository、會員 repository、付款紀錄 repository 都是 repository adapter 的例子。</p>
<h2 id="設計責任">設計責任</h2>
<p>Repository Adapter 要處理資料映射、一致性邊界、錯誤分類與 contract test，避免把 SQL 細節滲透到業務層。</p>
]]></content:encoded></item><item><title>Request Middleware</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/middleware/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/middleware/</guid><description>&lt;p>Request Middleware 的核心概念是「在 request 進入 handler 前後插入共通處理」。它承接多個 handler 共用的攔截層與前後置處理。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Request Middleware 位在 transport layer 與業務 handler 之間。它處理多個 endpoint 共用的橫切關注，而不是單一業務規則本身。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 request middleware 的訊號包括：很多 handler 都在重複驗證、關聯 request id、補 log、做權限檢查或遮罩敏感資料。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>&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> middleware 可以先驗證 token；&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> middleware 可以先做授權與 audit；webhook middleware 可以先驗證 signature 與來源限制。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Request Middleware 要定義執行順序、短路條件、context 傳遞與副作用界線。安全、觀測與錯誤處理的 middleware 特別需要穩定，不應把業務流程藏在攔截層。&lt;/p></description><content:encoded><![CDATA[<p>Request Middleware 的核心概念是「在 request 進入 handler 前後插入共通處理」。它承接多個 handler 共用的攔截層與前後置處理。 可先對照 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Request Middleware 位在 transport layer 與業務 handler 之間。它處理多個 endpoint 共用的橫切關注，而不是單一業務規則本身。 可先對照 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 request middleware 的訊號包括：很多 handler 都在重複驗證、關聯 request id、補 log、做權限檢查或遮罩敏感資料。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p><a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a> middleware 可以先驗證 token；<a href="/blog/backend/knowledge-cards/admin-endpoint/" data-link-title="Admin Endpoint" data-link-desc="說明管理入口如何承擔高權限操作與稽核責任">Admin Endpoint</a> middleware 可以先做授權與 audit；webhook middleware 可以先驗證 signature 與來源限制。</p>
<h2 id="設計責任">設計責任</h2>
<p>Request Middleware 要定義執行順序、短路條件、context 傳遞與副作用界線。安全、觀測與錯誤處理的 middleware 特別需要穩定，不應把業務流程藏在攔截層。</p>
]]></content:encoded></item><item><title>Request/Response Protocol</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/request-response-protocol/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/request-response-protocol/</guid><description>&lt;p>Request/Response Protocol 的核心概念是「client 發出請求，service 回應結果時，雙方如何對齊格式、錯誤與語意」。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Request/Response Protocol 位在 client、&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>、service 與 RPC layer 之間。它適用於同步互動的請求/回應模型。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 request/response protocol 的訊號是呼叫方必須等待結果，且錯誤格式、重試條件與版本相容需要穩定。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>HTTP API、gRPC method 與內部 RPC call 都屬於 request/response protocol。這類通訊要明確定義 request schema、response schema 與 error shape。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Request/Response Protocol 要定義欄位名稱、必填欄位、錯誤碼、逾時期待與版本演進方式。它討論的是同步互動的約定，transport 細節在其他層處理。&lt;/p></description><content:encoded><![CDATA[<p>Request/Response Protocol 的核心概念是「client 發出請求，service 回應結果時，雙方如何對齊格式、錯誤與語意」。 可先對照 <a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Request/Response Protocol 位在 client、<a href="/blog/backend/knowledge-cards/api-gateway/" data-link-title="API Gateway" data-link-desc="說明外部流量如何先收斂到一層可集中控制的入口">API Gateway</a>、service 與 RPC layer 之間。它適用於同步互動的請求/回應模型。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 request/response protocol 的訊號是呼叫方必須等待結果，且錯誤格式、重試條件與版本相容需要穩定。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>HTTP API、gRPC method 與內部 RPC call 都屬於 request/response protocol。這類通訊要明確定義 request schema、response schema 與 error shape。</p>
<h2 id="設計責任">設計責任</h2>
<p>Request/Response Protocol 要定義欄位名稱、必填欄位、錯誤碼、逾時期待與版本演進方式。它討論的是同步互動的約定，transport 細節在其他層處理。</p>
]]></content:encoded></item><item><title>Security Middleware</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/security-middleware/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/security-middleware/</guid><description>&lt;p>Security Middleware 的核心概念是「在 request 進入業務處理前，先套用共通安全控制」。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/security-misconfiguration/" data-link-title="Security Misconfiguration" data-link-desc="說明錯誤設定如何讓安全控制失效或暴露內部能力">Security Misconfiguration&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Security Middleware 位在 transport layer 與 handler 之間。它處理 rate limit、redaction、來源限制或其他共通防護。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/security-misconfiguration/" data-link-title="Security Misconfiguration" data-link-desc="說明錯誤設定如何讓安全控制失效或暴露內部能力">Security Misconfiguration&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 security middleware 的訊號是安全控制會影響多個 endpoint，且不應散落在每個 handler 中。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>rate limit、來源 IP 限制、敏感資訊遮罩與 webhook replay 防護，都可能由 security middleware 承擔。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Security Middleware 要把共通安全策略放在邊界上，並維持穩定的拒絕語意與稽核輸出。&lt;/p></description><content:encoded><![CDATA[<p>Security Middleware 的核心概念是「在 request 進入業務處理前，先套用共通安全控制」。 可先對照 <a href="/blog/backend/knowledge-cards/security-misconfiguration/" data-link-title="Security Misconfiguration" data-link-desc="說明錯誤設定如何讓安全控制失效或暴露內部能力">Security Misconfiguration</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Security Middleware 位在 transport layer 與 handler 之間。它處理 rate limit、redaction、來源限制或其他共通防護。 可先對照 <a href="/blog/backend/knowledge-cards/security-misconfiguration/" data-link-title="Security Misconfiguration" data-link-desc="說明錯誤設定如何讓安全控制失效或暴露內部能力">Security Misconfiguration</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 security middleware 的訊號是安全控制會影響多個 endpoint，且不應散落在每個 handler 中。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>rate limit、來源 IP 限制、敏感資訊遮罩與 webhook replay 防護，都可能由 security middleware 承擔。</p>
<h2 id="設計責任">設計責任</h2>
<p>Security Middleware 要把共通安全策略放在邊界上，並維持穩定的拒絕語意與稽核輸出。</p>
]]></content:encoded></item><item><title>Throughput</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/throughput/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/throughput/</guid><description>&lt;p>Throughput 的核心概念是「系統在一段時間內完成多少工作」。它和 latency 不同，throughput 看總量與持續處理能力，latency 看單次完成時間。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/thundering-herd/" data-link-title="Thundering Herd" data-link-desc="說明大量工作同時被喚醒或同時競爭資源時的尖峰風險">Thundering Herd&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Throughput 位在容量、排程與流量控制的交界。queue、broker、stream、load test 與 partitioning 都會直接影響 throughput。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/thundering-herd/" data-link-title="Thundering Herd" data-link-desc="說明大量工作同時被喚醒或同時競爭資源時的尖峰風險">Thundering Herd&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 throughput 指標的訊號包括：queue lag 上升、consumer 跟不上 producer、load test 失敗、CPU 或 I/O 長期飽和。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>checkout 每分鐘要處理多少訂單、consumer group 每秒可消化多少事件、load balancer 後面每個 instance 的穩定處理量，都是 throughput 問題。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Throughput 設計要定義測量單位、瓶頸位置、單節點與整體容量、以及在哪些條件下需要 backpressure、rate limit 或 scale out。&lt;/p></description><content:encoded><![CDATA[<p>Throughput 的核心概念是「系統在一段時間內完成多少工作」。它和 latency 不同，throughput 看總量與持續處理能力，latency 看單次完成時間。 可先對照 <a href="/blog/backend/knowledge-cards/thundering-herd/" data-link-title="Thundering Herd" data-link-desc="說明大量工作同時被喚醒或同時競爭資源時的尖峰風險">Thundering Herd</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Throughput 位在容量、排程與流量控制的交界。queue、broker、stream、load test 與 partitioning 都會直接影響 throughput。 可先對照 <a href="/blog/backend/knowledge-cards/thundering-herd/" data-link-title="Thundering Herd" data-link-desc="說明大量工作同時被喚醒或同時競爭資源時的尖峰風險">Thundering Herd</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 throughput 指標的訊號包括：queue lag 上升、consumer 跟不上 producer、load test 失敗、CPU 或 I/O 長期飽和。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>checkout 每分鐘要處理多少訂單、consumer group 每秒可消化多少事件、load balancer 後面每個 instance 的穩定處理量，都是 throughput 問題。</p>
<h2 id="設計責任">設計責任</h2>
<p>Throughput 設計要定義測量單位、瓶頸位置、單節點與整體容量、以及在哪些條件下需要 backpressure、rate limit 或 scale out。</p>
]]></content:encoded></item><item><title>Validation Middleware</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/validation-middleware/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/validation-middleware/</guid><description>&lt;p>Validation Middleware 的核心概念是「在 request 進入業務處理前，先確認輸入格式與基本條件」。 可先對照 &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;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Validation Middleware 位在 transport layer 與 handler 之間。它負責共通輸入驗證，而不是 domain 規則本身。 可先對照 &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;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 validation middleware 的訊號是很多 handler 都要重複檢查格式、必要欄位或基本範圍。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>JSON schema 檢查、header 驗證、基本參數完整性與 payload shape 檢查，都適合放在 validation middleware。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Validation Middleware 要快速拒絕明顯無效的 request，並把輸入錯誤與 domain 錯誤區分開。&lt;/p></description><content:encoded><![CDATA[<p>Validation Middleware 的核心概念是「在 request 進入業務處理前，先確認輸入格式與基本條件」。 可先對照 <a href="/blog/backend/knowledge-cards/waf/" data-link-title="WAF" data-link-desc="說明 Web Application Firewall 如何在入口層過濾常見攻擊與濫用">WAF</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Validation Middleware 位在 transport layer 與 handler 之間。它負責共通輸入驗證，而不是 domain 規則本身。 可先對照 <a href="/blog/backend/knowledge-cards/waf/" data-link-title="WAF" data-link-desc="說明 Web Application Firewall 如何在入口層過濾常見攻擊與濫用">WAF</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 validation middleware 的訊號是很多 handler 都要重複檢查格式、必要欄位或基本範圍。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>JSON schema 檢查、header 驗證、基本參數完整性與 payload shape 檢查，都適合放在 validation middleware。</p>
<h2 id="設計責任">設計責任</h2>
<p>Validation Middleware 要快速拒絕明顯無效的 request，並把輸入錯誤與 domain 錯誤區分開。</p>
]]></content:encoded></item><item><title>Webhook Protocol</title><link>https://tarrragon.github.io/blog/backend/knowledge-cards/webhook-protocol/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/knowledge-cards/webhook-protocol/</guid><description>&lt;p>Webhook Protocol 的核心概念是「外部系統把事件送進來時，雙方如何對齊驗證、payload 與失敗語意」。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">Webhook&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Webhook Protocol 位在 external system、HTTP endpoint 與 service 之間。它是外部事件導入的通訊約定。 可先對照 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">Webhook&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>系統需要 webhook protocol 的訊號是第三方會主動呼叫服務，而且需要簽章驗證、重放防護與穩定 payload。&lt;/p>
&lt;h2 id="接近真實網路服務的例子">接近真實網路服務的例子&lt;/h2>
&lt;p>付款通知、物流更新、SaaS 事件同步與第三方 callback 都會使用 webhook protocol。呼叫方與接收方都需要知道成功與失敗時的行為。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Webhook Protocol 要定義簽章、timestamp、重送、payload schema 與錯誤回應。它應與 public API 分開看待，因為它承擔的是外部推送而不是主動查詢。&lt;/p></description><content:encoded><![CDATA[<p>Webhook Protocol 的核心概念是「外部系統把事件送進來時，雙方如何對齊驗證、payload 與失敗語意」。 可先對照 <a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">Webhook</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>Webhook Protocol 位在 external system、HTTP endpoint 與 service 之間。它是外部事件導入的通訊約定。 可先對照 <a href="/blog/backend/knowledge-cards/webhook/" data-link-title="Webhook" data-link-desc="說明外部系統回呼事件的接收、驗證與處理邊界">Webhook</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>系統需要 webhook protocol 的訊號是第三方會主動呼叫服務，而且需要簽章驗證、重放防護與穩定 payload。</p>
<h2 id="接近真實網路服務的例子">接近真實網路服務的例子</h2>
<p>付款通知、物流更新、SaaS 事件同步與第三方 callback 都會使用 webhook protocol。呼叫方與接收方都需要知道成功與失敗時的行為。</p>
<h2 id="設計責任">設計責任</h2>
<p>Webhook Protocol 要定義簽章、timestamp、重送、payload schema 與錯誤回應。它應與 public API 分開看待，因為它承擔的是外部推送而不是主動查詢。</p>
]]></content:encoded></item></channel></rss>