<?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>Playbook on Tarragon</title><link>https://tarrragon.github.io/blog/tags/playbook/</link><description>Recent content in Playbook on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Wed, 27 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/playbook/index.xml" rel="self" type="application/rss+xml"/><item><title>Migration Playbook：Cloud SQL for PostgreSQL → Cloud Spanner</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/spanner/migrate-from-cloud-sql-pg/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/spanner/migrate-from-cloud-sql-pg/</guid><description>&lt;blockquote>
&lt;p>本文是 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/spanner/" data-link-title="Google Cloud Spanner" data-link-desc="全球分散式 strong-consistency OLTP、TrueTime API、線性擴展到 10 億 req/sec">Cloud Spanner&lt;/a> overview 的 &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration&lt;/a> playbook。走 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendor-article-spec/" data-link-title="資料庫 Vendor 文章撰寫規格" data-link-desc="把 PostgreSQL 與 MySQL batch 的正文經驗整理成資料庫 vendor overview、deep article 與 migration playbook 的撰寫規格">vendor-article-spec&lt;/a> Migration Playbook 規格 + &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">migration-playbook-methodology&lt;/a> Type E（paradigm shift）。每階段切換用 &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> 把關 — Evidence 段列的證據是 gate 通過條件、不是 nice-to-have。&lt;/p>&lt;/blockquote>
&lt;hr>
&lt;h2 id="driver為什麼遷什麼條件不該遷">Driver：為什麼遷、什麼條件不該遷&lt;/h2>
&lt;h3 id="啟動壓力">啟動壓力&lt;/h3>
&lt;p>single-region Cloud SQL PostgreSQL primary 觸到容量上限（connection、write throughput、storage IOPS、region 故障風險）、產品要求跨 region active-active write、external consistency 是契約而非 nice-to-have。讀者要先確認自己面對的是「real 跨 region write residency」、不是「想用更強的技術」 — driver 段的核心責任是排除空泛動機。&lt;/p>
&lt;h3 id="主要-driver-候選">主要 driver 候選&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Global write residency&lt;/strong>：用戶分散全球、各地寫入本地 region、跨 region 一致性是產品要求&lt;/li>
&lt;li>&lt;strong>External consistency 對帳契約&lt;/strong>：跨 region 交易順序錯誤會導致對帳爆炸（金融、計費、ticketing）&lt;/li>
&lt;li>&lt;strong>單 primary 容量天花板&lt;/strong>：Cloud SQL 最大 instance 仍撐不住、應用層 sharding 是大工程&lt;/li>
&lt;li>&lt;strong>跨 region read latency&lt;/strong>：read 從各地直接打本地 replica、Cloud SQL read replica 受 single-primary 寫入 throughput 限制&lt;/li>
&lt;/ul>
&lt;h3 id="no-go-condition基礎">No-go condition（基礎）&lt;/h3>
&lt;p>流量集中單 region、跨 region 只是 DR 需求 → 維持 Cloud SQL + read replica + cross-region async DR 更便宜。這條 no-go 不複雜、但團隊常被 marketing 推著跳過 — 在自家 traffic dashboard 上 audit 一遍「write 來自哪些 region、各占比多少」、若 90%+ 來自單 region、Spanner 沒有 benefit。&lt;/p>
&lt;h3 id="no-go-conditionsizing-barrier">No-go condition（sizing barrier）&lt;/h3>
&lt;p>小 / 中型 PostgreSQL workload 的成本門檻 — Spanner 早期最小單位 100 processing units（≈ 1 node）對中小負載偏貴、過去是 sizing barrier；2021+ 推出 100 pu 起跳的 granular sizing 後雖然可從小開始、但 100 pu × per-pu monthly cost 加上跨 region replication 仍可能比 Cloud SQL HA 設定貴數倍。&lt;/p></description><content:encoded><![CDATA[<blockquote>
<p>本文是 <a href="/blog/backend/01-database/vendors/spanner/" data-link-title="Google Cloud Spanner" data-link-desc="全球分散式 strong-consistency OLTP、TrueTime API、線性擴展到 10 億 req/sec">Cloud Spanner</a> overview 的 <a href="/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration</a> playbook。走 <a href="/blog/backend/01-database/vendor-article-spec/" data-link-title="資料庫 Vendor 文章撰寫規格" data-link-desc="把 PostgreSQL 與 MySQL batch 的正文經驗整理成資料庫 vendor overview、deep article 與 migration playbook 的撰寫規格">vendor-article-spec</a> Migration Playbook 規格 + <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">migration-playbook-methodology</a> Type E（paradigm shift）。每階段切換用 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate</a> 把關 — Evidence 段列的證據是 gate 通過條件、不是 nice-to-have。</p></blockquote>
<hr>
<h2 id="driver為什麼遷什麼條件不該遷">Driver：為什麼遷、什麼條件不該遷</h2>
<h3 id="啟動壓力">啟動壓力</h3>
<p>single-region Cloud SQL PostgreSQL primary 觸到容量上限（connection、write throughput、storage IOPS、region 故障風險）、產品要求跨 region active-active write、external consistency 是契約而非 nice-to-have。讀者要先確認自己面對的是「real 跨 region write residency」、不是「想用更強的技術」 — driver 段的核心責任是排除空泛動機。</p>
<h3 id="主要-driver-候選">主要 driver 候選</h3>
<ul>
<li><strong>Global write residency</strong>：用戶分散全球、各地寫入本地 region、跨 region 一致性是產品要求</li>
<li><strong>External consistency 對帳契約</strong>：跨 region 交易順序錯誤會導致對帳爆炸（金融、計費、ticketing）</li>
<li><strong>單 primary 容量天花板</strong>：Cloud SQL 最大 instance 仍撐不住、應用層 sharding 是大工程</li>
<li><strong>跨 region read latency</strong>：read 從各地直接打本地 replica、Cloud SQL read replica 受 single-primary 寫入 throughput 限制</li>
</ul>
<h3 id="no-go-condition基礎">No-go condition（基礎）</h3>
<p>流量集中單 region、跨 region 只是 DR 需求 → 維持 Cloud SQL + read replica + cross-region async DR 更便宜。這條 no-go 不複雜、但團隊常被 marketing 推著跳過 — 在自家 traffic dashboard 上 audit 一遍「write 來自哪些 region、各占比多少」、若 90%+ 來自單 region、Spanner 沒有 benefit。</p>
<h3 id="no-go-conditionsizing-barrier">No-go condition（sizing barrier）</h3>
<p>小 / 中型 PostgreSQL workload 的成本門檻 — Spanner 早期最小單位 100 processing units（≈ 1 node）對中小負載偏貴、過去是 sizing barrier；2021+ 推出 100 pu 起跳的 granular sizing 後雖然可從小開始、但 100 pu × per-pu monthly cost 加上跨 region replication 仍可能比 Cloud SQL HA 設定貴數倍。</p>
<p><strong>來源 9.C10「判讀」段第 3 點</strong>：Spanner 早期 100 pu 起跳是 sizing barrier、後來推出 granular sizing 才讓中小負載可從小開始。<strong>Dogfood 邊界明示</strong>：9.C10 case 揭露的 sizing 結構是 Google 內部 dogfood 的 capacity 規劃語言、不是 customer-facing pricing 承諾；客戶實際成本要看當期 Spanner pricing + region + replication config。</p>
<p>觸發 sizing no-go 的條件：</p>
<table>
  <thead>
      <tr>
          <th>信號</th>
          <th>判讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>workload row count &lt; 數百萬</td>
          <td>100 pu 對這個資料量過 over-provision</td>
      </tr>
      <tr>
          <td>QPS &lt; 1000</td>
          <td>100 pu 容量遠超實際 traffic、cost / QPS ratio 高</td>
      </tr>
      <tr>
          <td>單 region 即可滿足合規</td>
          <td>跨 region replication cost 是純浪費</td>
      </tr>
      <tr>
          <td>Cloud SQL HA 設定已 cover SLA</td>
          <td>升 Spanner 沒 marginal benefit</td>
      </tr>
  </tbody>
</table>
<p>觸發任一條 → 強烈建議走 Cloud SQL HA、不升 Spanner。判讀時要把 Cloud SQL HA cost vs Spanner 100 pu cost 對比清楚、避免讀者「想用新技術」而升級。</p>
<h3 id="no-go-condition應用層延遲容忍">No-go condition（應用層延遲容忍）</h3>
<p>應用層延遲容忍 &lt; 50ms write 的 workload 不該升 Spanner — 跨 region Spanner write 在物理光速硬限下達 100-200ms（<a href="../consistency-models-comparison/">consistency-models-comparison</a> 的 cross-region quorum 段）。延遲敏感 workload 升級後會在 p99 直接撞牆、回退時資料已經寫進 Spanner、roll back 成本巨大。</p>
<p><strong>來源 9.C10「判讀」段第 2 點 + 「策略」段第 3 點</strong>：「external consistency 必須等多區 quorum、跨洲交易延遲可達 100-200ms」。<strong>Dogfood 邊界明示</strong>：9.C10 揭露的數量級是 Google internal observation、客戶實際 latency 隨 voting region 配置變化、引用時要附條件。</p>
<p>觸發 latency no-go 的場景：</p>
<ul>
<li>實時報價系統（毫秒級回應）</li>
<li>高頻交易（HFT）</li>
<li>遊戲 leaderboard 寫入</li>
<li>低延遲 OLTP（金融下單、支付路由）</li>
</ul>
<p>觸發任一條 → 強烈建議走 Cloud SQL 單 region、或考慮把 <em>跨 region 一致性需求</em> 重新審視（是否真的需要強一致、能不能改 event-driven async reconcile）。</p>
<h3 id="替代方案排除">替代方案排除</h3>
<ul>
<li><strong>Aurora DSQL</strong>：AWS 生態、若團隊在 GCP、跨雲不合</li>
<li><strong>CockroachDB</strong>：要自管或想 PostgreSQL wire 但不選 GCP 託管時可考慮、本 playbook 不對照</li>
<li><strong>Citus on Cloud SQL</strong>：multi-region write 不是強項、不解 cross-region external consistency 需求</li>
</ul>
<h3 id="case-anchor--dogfood-邊界">Case anchor + dogfood 邊界</h3>
<p><strong>無強 customer case</strong>。9.C10 是 Google 內部 dogfood、不是公開遷移 case；本 playbook 用 Spanner overview 的 PostgreSQL dialect 路徑 + 官方 migration guide + 通用 pattern。引用時必須明示「9.C10 揭露的線性 scaling / line-rate 設計目標是 Spanner 設計依據、不等於客戶遷移後可獲得的 capacity」。</p>
<p>對照 case：<a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered Aurora 受監管 banking</a> — 雖然是 Aurora、不是 Spanner、但揭露「受監管 OLTP 遷移要算合規 lead time」「資料駐留限制 = 容量規劃 per-市場」這兩條結論在 Spanner 遷移同樣適用。讀者若是受監管產業、跨 region instance config 還要疊上 voting region 是否落在合規市場的 audit。</p>
<h2 id="diff-audit6-規格面--sizing--cost-第-7-面">Diff Audit（6 規格面 + sizing / cost 第 7 面）</h2>
<h3 id="schema-diff">Schema diff</h3>
<p>PostgreSQL DDL → Spanner PostgreSQL dialect 對照：</p>
<table>
  <thead>
      <tr>
          <th>PostgreSQL 特性</th>
          <th>Spanner 對應</th>
          <th>動作</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>SERIAL</code></td>
          <td>bit-reversed sequence</td>
          <td>改 primary key 策略、避免 hot split</td>
      </tr>
      <tr>
          <td><code>JSONB</code></td>
          <td><code>JSON</code> type</td>
          <td>大部分相容、複雜 path query 重寫</td>
      </tr>
      <tr>
          <td><code>ARRAY</code></td>
          <td><code>ARRAY</code></td>
          <td>OK</td>
      </tr>
      <tr>
          <td><code>PARTITION BY</code></td>
          <td>不直接支援</td>
          <td>改成 interleaved table 或單表</td>
      </tr>
      <tr>
          <td><code>FOREIGN KEY</code></td>
          <td>保留 FK constraint + 考慮 <a href="/blog/backend/knowledge-cards/interleaved-table/" data-link-title="Interleaved Table" data-link-desc="Spanner 把 parent / child table row 物理交錯儲存、parent &#43; child JOIN 不跨 split">Interleaved Table</a></td>
          <td>parent-child access pattern 改 interleaved</td>
      </tr>
      <tr>
          <td><code>B-tree INDEX</code></td>
          <td>OK</td>
          <td>直接遷</td>
      </tr>
      <tr>
          <td><code>GIN / GiST INDEX</code></td>
          <td>不支援</td>
          <td>用 <code>STORING</code> column 取代部分需求、其餘改應用層</td>
      </tr>
      <tr>
          <td><code>CHECK constraint</code></td>
          <td>部分支援（time-sensitive、查最新文件）</td>
          <td>audit 每條 constraint</td>
      </tr>
      <tr>
          <td><code>UDF / stored procedure</code></td>
          <td>少數支援</td>
          <td>改應用層或 client-side compute</td>
      </tr>
      <tr>
          <td><code>TRIGGER</code></td>
          <td>不支援</td>
          <td>改 application 層或 Spanner change streams</td>
      </tr>
  </tbody>
</table>
<p>interleaved table 設計參考 <a href="../schema-migration-interleaved-tables/">schema-migration-interleaved-tables</a>。讀者要在 schema audit 階段就決定哪些 parent-child 該 interleave、避免後悔成本。</p>
<h3 id="operational-diff">Operational diff</h3>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Cloud SQL</th>
          <th>Spanner</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>基礎架構</td>
          <td>VM-based</td>
          <td>API-based</td>
      </tr>
      <tr>
          <td>認證</td>
          <td>postgres user / role</td>
          <td>IAM role / service account</td>
      </tr>
      <tr>
          <td>備份</td>
          <td>pg_dump / pgBackRest</td>
          <td>point-in-time backup（PITR）</td>
      </tr>
      <tr>
          <td>監控</td>
          <td>postgres-flavor（pg_stat_*）</td>
          <td>Cloud Monitoring <code>spanner.*</code></td>
      </tr>
      <tr>
          <td>Connection pool</td>
          <td>PgBouncer</td>
          <td>SDK 內 gRPC pool</td>
      </tr>
      <tr>
          <td>Vacuum</td>
          <td>必要</td>
          <td>不存在（MVCC 機制不同）</td>
      </tr>
      <tr>
          <td>Replication lag</td>
          <td>需監控</td>
          <td>不存在 single-primary 概念</td>
      </tr>
  </tbody>
</table>
<p>不再需要的 Cloud SQL 責任：vacuum、autovacuum tuning、connection pool（PgBouncer）、replication lag 監控、Patroni HA。</p>
<p>新增 Spanner 責任：processing unit capacity 預測、TrueTime ε 觀測（<a href="../truetime-api-depth/">truetime-api-depth</a>）、long-running schema operation 跟蹤、IAM 細粒度權限。</p>
<h3 id="paradigm-diff">Paradigm diff</h3>
<p>從 single-primary OLTP → 跨 region distributed SQL：</p>
<ul>
<li>transaction commit latency：&lt; 5ms → 50-200ms（跨洲、含 <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> + cross-region quorum）</li>
<li>external consistency 是 default（不再是 isolation level 選擇題）</li>
<li>transaction 上限：Cloud SQL 無硬限 → Spanner 10s timeout、要重構成短交易</li>
<li>read consistency：default eventual → default strong、需顯式選 bounded staleness</li>
</ul>
<p>詳細 consistency model 差異看 <a href="../consistency-models-comparison/">consistency-models-comparison</a>。</p>
<h3 id="component-diff">Component diff</h3>
<p>退役：</p>
<ul>
<li>PgBouncer / pgcat（connection pool）</li>
<li>Cloud SQL HA / Patroni cluster</li>
<li>pgBackRest（備份外掛）</li>
<li>Citus extension（若有用）</li>
<li>各種 postgres extension（時間敏感、逐個 audit 是否 Spanner 支援等效）</li>
</ul>
<p>新增：</p>
<ul>
<li>Spanner client library（Go / Java / Node / Python）</li>
<li>Dataflow（用於 bulk export-import）</li>
<li>Datastream / Database Migration Service（用於 CDC catch-up）</li>
<li>Spanner Studio（query UI）</li>
</ul>
<h3 id="application-diff">Application diff</h3>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Cloud SQL（PostgreSQL client）</th>
          <th>Spanner</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>ORM</td>
          <td>全 PG ORM 相容</td>
          <td>PostgreSQL dialect 相容部分 ORM、查最新 dialect 支援列表</td>
      </tr>
      <tr>
          <td>Connection model</td>
          <td>process-per-connection（postgres）</td>
          <td>stateless gRPC client（SDK 內 pool）</td>
      </tr>
      <tr>
          <td>Transaction model</td>
          <td>可長交易</td>
          <td>10s timeout、需短交易</td>
      </tr>
      <tr>
          <td>Timestamp 使用</td>
          <td>app 內 <code>now()</code> / <code>CURRENT_TIMESTAMP</code></td>
          <td>改用 <code>PENDING_COMMIT_TIMESTAMP</code> sentinel</td>
      </tr>
      <tr>
          <td>Cursor / prepared statement</td>
          <td>全支援</td>
          <td>部分支援、查 SDK 文件</td>
      </tr>
      <tr>
          <td>Stored procedure</td>
          <td>全支援</td>
          <td>少數支援、業務邏輯改應用層</td>
      </tr>
  </tbody>
</table>
<p>ORM 兼容性是 time-sensitive claim — JPA / Hibernate / SQLAlchemy 在 Spanner PostgreSQL dialect 上的行為隨 dialect 版本演進、實作前查最新 vendor docs。讀者要把 ORM 兼容測試放 Phase 0、不能假設「PostgreSQL ORM 直接搬到 Spanner」。</p>
<h3 id="data-topology-diff">Data topology diff</h3>
<ul>
<li>Single primary（write）+ read replica → multi-region voting + read-only replica</li>
<li>Primary key 設計：避免單調遞增（SERIAL）造成 hot split、改 UUID 或 bit-reversed</li>
<li>Partition：PostgreSQL declarative partition → Spanner 不需要顯式 partition（自動 split）</li>
</ul>
<h3 id="sizing--cost-diff第-7-規格面">Sizing / cost diff（第 7 規格面）</h3>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>Cloud SQL</th>
          <th>Spanner</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>計費單位</td>
          <td>instance class（vCPU / RAM）+ storage IOPS + HA add-on</td>
          <td>100 processing units 起跳 ≈ 1 node</td>
      </tr>
      <tr>
          <td>起跳成本</td>
          <td>小型 instance 月成本可控（小型 HA $50-200/月）</td>
          <td>100 pu × per-pu monthly rate、月成本是 Cloud SQL 小型 HA 的數倍</td>
      </tr>
      <tr>
          <td>Storage</td>
          <td>獨立計費（GB / month）</td>
          <td>含在 node count 內、無單獨 storage charge</td>
      </tr>
      <tr>
          <td>Throughput cap</td>
          <td>隨 instance class</td>
          <td>隨 pu 線性擴展</td>
      </tr>
      <tr>
          <td>跨 region replication</td>
          <td>額外 read replica cost</td>
          <td>含在 multi-region instance config 內</td>
      </tr>
      <tr>
          <td>Egress</td>
          <td>跨 region 額外</td>
          <td>跨 region 額外</td>
      </tr>
  </tbody>
</table>
<p>觸發 sizing audit 的時機：workload 行數、QPS、跨 region 需求都明確後、把「Cloud SQL HA monthly bill」對「Spanner 100 pu × monthly rate + egress」做 cost crossover 分析、無法 cost crossover 證明 → 不升。</p>
<p>Cost crossover 不是「Spanner 成本必須低於 Cloud SQL」、是「Spanner 多付的成本要對應到具體 benefit」：</p>
<ul>
<li>若 benefit 是 multi-region write residency、Spanner 多付的 cost 換得跨 region 一致性 — 對齊</li>
<li>若 benefit 只是「更新的技術」、Spanner 多付的 cost 沒對應產品價值 — 不升</li>
</ul>
<h3 id="type-判定">Type 判定</h3>
<p><strong>Type E（paradigm shift）</strong>、不是 drop-in。schema / app / operation / data topology / cost 五軸都動、不能用 Type B（drop-in）思路規劃 phase。詳細 type 判定方法看 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">migration-playbook-methodology</a>。</p>
<h2 id="phase-plan9-段每段有驗證門檻">Phase Plan：9 段、每段有驗證門檻</h2>
<h3 id="phase-0--compatibility-audit--sizing-audit">Phase 0 — Compatibility audit + sizing audit</h3>
<p>跑 schema-converter（pgloader / Spanner migration tool）、列出 incompatible feature、決定哪些改 schema、哪些改 app。hot key 風險評估（SERIAL primary key、單調遞增 timestamp）。</p>
<p>同時跑 sizing audit：</p>
<ul>
<li>估 target Spanner pu 數（基於 QPS、storage size、cross-region replication factor）</li>
<li>做 Cloud SQL HA cost vs Spanner cost crossover 分析</li>
<li>若 cost crossover 證明不出來 → halt migration、回到 driver 段重審</li>
</ul>
<p>Phase 0 是 migration 的決策閘門 — 不過閘門就停、不浪費 Phase 1+ 的 engineering effort。</p>
<h3 id="phase-1--target-schema-design">Phase 1 — Target schema design</h3>
<ul>
<li>interleaved table 設計（base on Phase 0 access pattern audit）</li>
<li>Index 重寫（GIN / GiST 用 STORING column 替代、其他用 B-tree）</li>
<li>Primary key 反序（避免 hot split）</li>
<li>Storing column 選擇（trade-off：query latency vs index size）</li>
</ul>
<p>Output 是 target DDL、跟原 PostgreSQL schema 並排 diff 文件、給 application 團隊審。</p>
<h3 id="phase-2--application-dual-target-preparation">Phase 2 — Application dual-target preparation</h3>
<ul>
<li>抽象 DB layer（repository pattern、避免直接呼 SQL）</li>
<li>SDK 並存（go-pg + Spanner client）</li>
<li>Feature flag 控制讀寫路徑（read-from-pg / read-from-spanner / dual-write）</li>
<li>Transaction 模式 audit（長交易拆短）</li>
</ul>
<h3 id="phase-3--bulk-initial-load">Phase 3 — Bulk initial load</h3>
<p>Cloud SQL → Cloud Storage（CSV / Avro）→ Dataflow → Spanner。Row count + checksum 驗證、column-level diff sample。</p>
<h3 id="phase-4--cdc-catch-up">Phase 4 — CDC catch-up</h3>
<p>Datastream from Cloud SQL → Dataflow → Spanner。Replication lag &lt; 1s 為前進門檻、sustained 24h。</p>
<h3 id="phase-5--shadow-read">Phase 5 — Shadow read</h3>
<p>Production read 同時打 Cloud SQL 跟 Spanner、diff log 異常。至少 7 天觀察、divergence rate &lt; 0.1%、p99 latency Spanner &lt; 1.5x Cloud SQL。</p>
<h3 id="phase-6--dual-write">Phase 6 — Dual write</h3>
<p>Cloud SQL 為 source-of-truth、Spanner 為 mirror。偵測 dual write divergence、評估是否提早升 source-of-truth。</p>
<h3 id="phase-7--cutover">Phase 7 — Cutover</h3>
<p>read-only window（&lt; 5 min）→ 最後 catch-up → switch source-of-truth → cutover application write。</p>
<h3 id="phase-8--cleanup">Phase 8 — Cleanup</h3>
<p>退役 Cloud SQL primary、保留 backup、清 PgBouncer / Patroni / 監控 dashboard。</p>
<h3 id="stage-0-variant-規劃">Stage 0 variant 規劃</h3>
<p>若 read-only window 不可接受（24/7 不能停機的金融 / 醫療系統）、Phase 6 dual write 期間做 conflict resolution（last-writer-wins + manual reconcile）、進入 fail-forward 模式、不走 read-only cutover。</p>
<h2 id="evidence每階段驗證材料">Evidence：每階段驗證材料</h2>
<table>
  <thead>
      <tr>
          <th>Phase</th>
          <th>Evidence</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Phase 0</td>
          <td>incompatible feature 清單、預估改動 SP、hot key 風險 row count、<strong>sizing audit 報告</strong>（target pu 數估算 + Cloud SQL HA vs Spanner cost crossover 月 / 年成本對比）</td>
      </tr>
      <tr>
          <td>Phase 1</td>
          <td>DDL diff report、預估 backfill 時間（基於 row count + Spanner 文件）</td>
      </tr>
      <tr>
          <td>Phase 3</td>
          <td>row count 對齊、column-level checksum、payload sample diff</td>
      </tr>
      <tr>
          <td>Phase 4</td>
          <td>CDC lag &lt; 1s sustained 24h、error rate &lt; 0.01%</td>
      </tr>
      <tr>
          <td>Phase 5</td>
          <td>shadow read divergence rate &lt; 0.1%、p99 latency Spanner &lt; 1.5x Cloud SQL</td>
      </tr>
      <tr>
          <td>Phase 6</td>
          <td>dual write divergence &lt; 0.01%、reconcile queue 不積壓</td>
      </tr>
      <tr>
          <td>Phase 7</td>
          <td>cutover window 內 write 一致性、回到 Phase 6 的條件（rollback path）</td>
      </tr>
  </tbody>
</table>
<p><strong>Cost crossover 報告</strong>（Phase 0 必交付）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Item                          | Cloud SQL HA | Spanner 100 pu | Delta
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">------------------------------|--------------|----------------|------
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">Compute monthly               | $X           | $Y             | $Y-X
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">Storage monthly               | $A           | (included)     | -$A
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">Cross-region replication      | $B           | (included)     | -$B
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">Egress (est)                  | $C           | $C             | $0
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">Total monthly                 | $X+A+B+C     | $Y+C           | $Y-X-A-B
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">Annual                        | 12*above     | 12*above       | -
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">Benefit (qualitative)         | -            | multi-region write residency / external consistency | -
</span></span><span class="line"><span class="ln">10</span><span class="cl">Crossover verdict             | -            | proceed / halt | -</span></span></code></pre></div><p>Verdict = <code>proceed</code> 才進 Phase 1；<code>halt</code> → 回到 Driver 段重審 driver 是否成立。</p>
<p>所有 evidence 進 incident decision log、回 <a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a>。</p>
<h2 id="cutover決策與-rollback">Cutover：決策與 rollback</h2>
<h3 id="cutover-window">Cutover window</h3>
<p>選用戶最低流量時段、&lt; 5 min read-only freeze、預先通知。受監管產業（對照 <a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered</a>）要算合規 lead time、每市場各自審。</p>
<h3 id="decision-owner">Decision owner</h3>
<p>DB lead + product lead + on-call SRE 共同 sign-off。受監管產業多加合規 owner。</p>
<h3 id="rollback-condition">Rollback condition</h3>
<ul>
<li>cutover 後 30 min 內 p99 write latency 持續 &gt; SLA 2x → rollback</li>
<li>error rate &gt; 1% sustained 5 min → rollback</li>
<li>對帳系統發現 divergence &gt; 0.1% → rollback</li>
</ul>
<h3 id="rollback-機制">Rollback 機制</h3>
<p>保留 Cloud SQL 為 read-only mirror 14 天、Spanner 改 read-only、reverse CDC（Spanner → Cloud SQL）需事先準備。Reverse CDC 在 Phase 4-6 期間就要 dry-run 過、不能 cutover 才第一次試。</p>
<p>連結 <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/rollback-condition/" data-link-title="Rollback Condition" data-link-desc="說明決策執行後出現哪些訊號時要撤回、回退或改路線">rollback-condition</a>。</p>
<h2 id="cleanup退役清單跟保留責任">Cleanup：退役清單跟保留責任</h2>
<h3 id="退役清單">退役清單</h3>
<ul>
<li>Cloud SQL primary instance</li>
<li>PgBouncer 配置</li>
<li>Patroni cluster</li>
<li>pgBackRest backup job（保留歸檔 90 天、依產業合規）</li>
<li>Datastream pipeline</li>
<li>Dataflow job</li>
</ul>
<h3 id="監控清理">監控清理</h3>
<p>postgres-specific dashboard（exporter / wal lag / autovacuum）改成 Spanner dashboard（commit_latencies / clock_skew_ms / cpu_utilization_by_priority）。</p>
<h3 id="文件--runbook-更新">文件 / runbook 更新</h3>
<p>postgres operation runbook 標記 deprecated、Spanner runbook 上線。新 runbook 含：</p>
<ul>
<li>DDL long-running operation 監控</li>
<li>TrueTime ε 異常處理</li>
<li>Cross-region instance failover drill</li>
<li>Cost monitoring alert</li>
</ul>
<h3 id="稽核--合規">稽核 / 合規</h3>
<p>保留 final pg_dump 7 年（依產業）、incident write-back 完成、合規市場各自留檔（對照 Standard Chartered case 的 per-市場合規 lead time）。</p>
<h2 id="邊界與整合sibling對照anti-recommendation">邊界與整合：sibling、對照、anti-recommendation</h2>
<h3 id="sibling-deep-articles">Sibling deep articles</h3>
<ul>
<li><a href="../truetime-api-depth/">truetime-api-depth</a>：app 對 timestamp 假設審計（Phase 2 必讀）</li>
<li><a href="../schema-migration-interleaved-tables/">schema-migration-interleaved-tables</a>：Phase 1 target schema 設計</li>
<li><a href="../consistency-models-comparison/">consistency-models-comparison</a>：Phase 0 應用層一致性要求釐清、Driver 段 latency no-go 的物理硬限</li>
</ul>
<h3 id="跟其他-migration-對照">跟其他 migration 對照</h3>
<ul>
<li><a href="/blog/backend/01-database/vendors/postgresql/migrate-to-aurora-dsql/" data-link-title="PostgreSQL → Aurora DSQL Migration：PG wire-compatible Distributed SQL 的 Paradigm Shift" data-link-desc="Aurora DSQL（2024-12 re:Invent preview / 2025-05 GA）是 AWS 推的 PG wire-compatible *active-active distributed SQL*、跟 self-managed PG / Aurora PG 不同 paradigm（OCC &#43; snapshot isolation &#43; multi-region strong consistency）。Migration 結構是 *protocol drop-in &#43; paradigm shift*：app SQL 不太改、但 transaction retry / extension 缺位 / 多 region 一致性需重設計。本文走 DSQL vs Aurora PG vs self-managed PG 三軸對比、為什麼遷的三條 driver（global write / operational zero-touch / region resiliency）、Type E phased plan、5 production 踩雷（transaction retry 沒處理 / extension 缺位 / sequence throughput 限制 / Aurora PG 直升 DSQL 不可行 / region failover semantic）、跟 PG → Aurora 跟 PG → CockroachDB 對比">PostgreSQL → Aurora DSQL Migration</a>：兩者都是 PostgreSQL → distributed SQL paradigm shift、選 GCP / AWS 看生態</li>
<li><a href="/blog/backend/01-database/large-scale-db-migration/" data-link-title="1.12 大規模 DB 遷移實戰" data-link-desc="跨 DB 遷移的 dual-write、[shadow read](/backend/knowledge-cards/shadow-read/)、cutover、rollback 流程 — 從實戰案例提煉的工程做法">1.12 大規模 DB 遷移實戰</a>：通用大規模遷移方法論</li>
</ul>
<h3 id="跟-case-對照">跟 case 對照</h3>
<ul>
<li><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 Cloud Spanner planetary scale</a>：dogfood case、揭露 Spanner 設計目標、不是 customer-facing capacity reference</li>
<li><a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered Aurora banking</a>：受監管產業遷移要算合規 lead time、per-市場容量規劃</li>
</ul>
<h3 id="anti-recommendation">Anti-recommendation</h3>
<p>讀者讀完本文應該能判斷：</p>
<ul>
<li>若 driver 只是「想用新技術」→ 回 Cloud SQL</li>
<li>若 workload 小（QPS &lt; 1000、行數 &lt; 數百萬）→ Cloud SQL HA 更划算</li>
<li>若應用層延遲容忍 &lt; 50ms write → Cloud SQL 單 region</li>
<li>若 cost crossover 證明不出來 → halt migration、不升</li>
</ul>
<p>Driver 是真正跨 region write residency / external consistency 對帳契約 / 單 primary 容量天花板 → 才升。Migration playbook 的目標不是把所有 Cloud SQL workload 升到 Spanner、是把「適合升」的部分用低風險路徑遷過去。</p>
]]></content:encoded></item><item><title>從自管 PostgreSQL / MySQL 遷到 Aurora：operational redesign migration playbook</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/aurora/migrate-from-self-managed-pg-mysql/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/aurora/migrate-from-self-managed-pg-mysql/</guid><description>&lt;p>從自管 PostgreSQL / MySQL 遷到 Aurora 是 &lt;em>operational redesign hybrid&lt;/em>（Type C &lt;a href="https://tarrragon.github.io/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration&lt;/a>）— wire protocol 相容、application 不改、但 HA / backup / monitoring / capacity 模型完全不同。本 playbook 走 &lt;a href="https://tarrragon.github.io/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">migration playbook 6 規格面&lt;/a>（Driver / Diff audit / Phase plan / Evidence / Cutover / Cleanup）、補三個 Aurora-specific 議題：(1) 合規禁止跨境複製的 no-go condition、(2) 合規驅動遷移的時程模型（市場數 × 平均審查月份）、(3) Aurora 不是 all-purpose store 邊界。每階段進入下一步前都要過 &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> — Evidence 段列出的證據是 gate 條件、不是 nice-to-have。&lt;/p>
&lt;p>本 playbook 不重複 Aurora overview（請看 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&amp;#43;75% 效能改善的 production 證據">Aurora vendor 頁&lt;/a>）— 前置閱讀建議 &lt;a href="../storage-architecture/">Aurora storage architecture&lt;/a>（理解為什麼 operational redesign）、&lt;a href="../cross-az-failover-rto/">Aurora cross-AZ failover RTO&lt;/a>（HA redesign 主項）、&lt;a href="../read-replica-scaling/">Aurora read replica scaling&lt;/a>（fleet 治理 SSoT、含合規 driver）。&lt;/p>
&lt;h2 id="migration-type-判定">Migration type 判定&lt;/h2>
&lt;p>本 playbook 是 &lt;em>Type C：Operational redesign hybrid&lt;/em>：&lt;/p>
&lt;ul>
&lt;li>PostgreSQL / MySQL → Aurora wire protocol 相容、application 多數不改&lt;/li>
&lt;li>但 operational model（HA / backup / monitoring / capacity）完全不同、需要 redesign&lt;/li>
&lt;li>跟 Type A schema translation 差：不需要翻譯 application SQL&lt;/li>
&lt;li>跟 Type B drop-in 差：HA / backup / monitoring / capacity 模型需要 redesign&lt;/li>
&lt;li>跟 Type E paradigm shift 差：保留 single-primary SQL 跟 ACID transaction 語意&lt;/li>
&lt;/ul>
&lt;p>對照其他 Aurora-related migration playbook：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/postgresql/migrate-to-aurora-dsql/" data-link-title="PostgreSQL → Aurora DSQL Migration：PG wire-compatible Distributed SQL 的 Paradigm Shift" data-link-desc="Aurora DSQL（2024-12 re:Invent preview / 2025-05 GA）是 AWS 推的 PG wire-compatible *active-active distributed SQL*、跟 self-managed PG / Aurora PG 不同 paradigm（OCC &amp;#43; snapshot isolation &amp;#43; multi-region strong consistency）。Migration 結構是 *protocol drop-in &amp;#43; paradigm shift*：app SQL 不太改、但 transaction retry / extension 缺位 / 多 region 一致性需重設計。本文走 DSQL vs Aurora PG vs self-managed PG 三軸對比、為什麼遷的三條 driver（global write / operational zero-touch / region resiliency）、Type E phased plan、5 production 踩雷（transaction retry 沒處理 / extension 缺位 / sequence throughput 限制 / Aurora PG 直升 DSQL 不可行 / region failover semantic）、跟 PG → Aurora 跟 PG → CockroachDB 對比">PG → Aurora DSQL&lt;/a> 是 Type E paradigm shift（distributed SQL、multi-region active-active）&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/postgresql/migrate-to-cockroachdb/" data-link-title="PostgreSQL → CockroachDB：三維皆 High 的多重歸類 migration" data-link-desc="PostgreSQL → CockroachDB 是 Schema / Operational / Paradigm 三維皆 High 的 multi-axis migration、實證 [#127](/report/content-structure-by-max-diff-dimension/) 的「多重歸類跟 tie-breaking」規則；主結構走 Type E paradigm shift、Schema 差 &amp;#43; Operational redesign 抽出獨立段；涵蓋 transaction model 重設計、SQL dialect gap、5 個 production 踩雷">PG → CockroachDB&lt;/a> 是 Type E paradigm shift + cross-cloud&lt;/li>
&lt;/ul>
&lt;h2 id="driver為什麼遷">Driver：為什麼遷&lt;/h2>
&lt;h3 id="主要-driver">主要 driver&lt;/h3>
&lt;ul>
&lt;li>團隊規模成長、DBA bandwidth 飽和、backup / failover / patch 操作負擔超過產品價值&lt;/li>
&lt;li>Read replica scaling 需求（傳統 streaming replication lag 秒級、Aurora 10-30ms — 詳見 &lt;a href="../read-replica-scaling/">Aurora read replica scaling&lt;/a>）&lt;/li>
&lt;li>Storage growth 痛點（local SSD 上限、resize 要 downtime、Aurora 自動 grow 到 128 TB）&lt;/li>
&lt;/ul>
&lt;h3 id="次要-driver">次要 driver&lt;/h3>
&lt;ul>
&lt;li>HA model 簡化（Patroni / Orchestrator → Aurora cluster endpoint、見 &lt;a href="../cross-az-failover-rto/">cross-AZ failover RTO&lt;/a>）&lt;/li>
&lt;li>Backup 自動化（pgBackRest / xtrabackup → Aurora automated backup + PITR）&lt;/li>
&lt;li>Multi-region DR 需求（&lt;a href="../global-database-multi-region/">Aurora Global Database&lt;/a>、但合規場景例外）&lt;/li>
&lt;/ul>
&lt;h3 id="no-go-condition嚴格遵守">No-go condition（嚴格遵守）&lt;/h3>
&lt;p>跨雲 / on-prem 需求觸動 &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> — Aurora storage layer 是 AWS 專屬、wire protocol 相容不代表退出成本低、long-term 跨雲策略未定時 self-managed PG / MySQL 反而保留路徑。&lt;/p></description><content:encoded><![CDATA[<p>從自管 PostgreSQL / MySQL 遷到 Aurora 是 <em>operational redesign hybrid</em>（Type C <a href="/blog/backend/knowledge-cards/migration/" data-link-title="Migration" data-link-desc="說明系統如何把資料、流量或結構從舊狀態移到新狀態">migration</a>）— wire protocol 相容、application 不改、但 HA / backup / monitoring / capacity 模型完全不同。本 playbook 走 <a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">migration playbook 6 規格面</a>（Driver / Diff audit / Phase plan / Evidence / Cutover / Cleanup）、補三個 Aurora-specific 議題：(1) 合規禁止跨境複製的 no-go condition、(2) 合規驅動遷移的時程模型（市場數 × 平均審查月份）、(3) Aurora 不是 all-purpose store 邊界。每階段進入下一步前都要過 <a href="/blog/backend/knowledge-cards/migration-gate/" data-link-title="Migration Gate" data-link-desc="說明遷移流程何時可以進入下一階段或正式切換">migration gate</a> — Evidence 段列出的證據是 gate 條件、不是 nice-to-have。</p>
<p>本 playbook 不重複 Aurora overview（請看 <a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor 頁</a>）— 前置閱讀建議 <a href="../storage-architecture/">Aurora storage architecture</a>（理解為什麼 operational redesign）、<a href="../cross-az-failover-rto/">Aurora cross-AZ failover RTO</a>（HA redesign 主項）、<a href="../read-replica-scaling/">Aurora read replica scaling</a>（fleet 治理 SSoT、含合規 driver）。</p>
<h2 id="migration-type-判定">Migration type 判定</h2>
<p>本 playbook 是 <em>Type C：Operational redesign hybrid</em>：</p>
<ul>
<li>PostgreSQL / MySQL → Aurora wire protocol 相容、application 多數不改</li>
<li>但 operational model（HA / backup / monitoring / capacity）完全不同、需要 redesign</li>
<li>跟 Type A schema translation 差：不需要翻譯 application SQL</li>
<li>跟 Type B drop-in 差：HA / backup / monitoring / capacity 模型需要 redesign</li>
<li>跟 Type E paradigm shift 差：保留 single-primary SQL 跟 ACID transaction 語意</li>
</ul>
<p>對照其他 Aurora-related migration playbook：</p>
<ul>
<li><a href="/blog/backend/01-database/vendors/postgresql/migrate-to-aurora-dsql/" data-link-title="PostgreSQL → Aurora DSQL Migration：PG wire-compatible Distributed SQL 的 Paradigm Shift" data-link-desc="Aurora DSQL（2024-12 re:Invent preview / 2025-05 GA）是 AWS 推的 PG wire-compatible *active-active distributed SQL*、跟 self-managed PG / Aurora PG 不同 paradigm（OCC &#43; snapshot isolation &#43; multi-region strong consistency）。Migration 結構是 *protocol drop-in &#43; paradigm shift*：app SQL 不太改、但 transaction retry / extension 缺位 / 多 region 一致性需重設計。本文走 DSQL vs Aurora PG vs self-managed PG 三軸對比、為什麼遷的三條 driver（global write / operational zero-touch / region resiliency）、Type E phased plan、5 production 踩雷（transaction retry 沒處理 / extension 缺位 / sequence throughput 限制 / Aurora PG 直升 DSQL 不可行 / region failover semantic）、跟 PG → Aurora 跟 PG → CockroachDB 對比">PG → Aurora DSQL</a> 是 Type E paradigm shift（distributed SQL、multi-region active-active）</li>
<li><a href="/blog/backend/01-database/vendors/postgresql/migrate-to-cockroachdb/" data-link-title="PostgreSQL → CockroachDB：三維皆 High 的多重歸類 migration" data-link-desc="PostgreSQL → CockroachDB 是 Schema / Operational / Paradigm 三維皆 High 的 multi-axis migration、實證 [#127](/report/content-structure-by-max-diff-dimension/) 的「多重歸類跟 tie-breaking」規則；主結構走 Type E paradigm shift、Schema 差 &#43; Operational redesign 抽出獨立段；涵蓋 transaction model 重設計、SQL dialect gap、5 個 production 踩雷">PG → CockroachDB</a> 是 Type E paradigm shift + cross-cloud</li>
</ul>
<h2 id="driver為什麼遷">Driver：為什麼遷</h2>
<h3 id="主要-driver">主要 driver</h3>
<ul>
<li>團隊規模成長、DBA bandwidth 飽和、backup / failover / patch 操作負擔超過產品價值</li>
<li>Read replica scaling 需求（傳統 streaming replication lag 秒級、Aurora 10-30ms — 詳見 <a href="../read-replica-scaling/">Aurora read replica scaling</a>）</li>
<li>Storage growth 痛點（local SSD 上限、resize 要 downtime、Aurora 自動 grow 到 128 TB）</li>
</ul>
<h3 id="次要-driver">次要 driver</h3>
<ul>
<li>HA model 簡化（Patroni / Orchestrator → Aurora cluster endpoint、見 <a href="../cross-az-failover-rto/">cross-AZ failover RTO</a>）</li>
<li>Backup 自動化（pgBackRest / xtrabackup → Aurora automated backup + PITR）</li>
<li>Multi-region DR 需求（<a href="../global-database-multi-region/">Aurora Global Database</a>、但合規場景例外）</li>
</ul>
<h3 id="no-go-condition嚴格遵守">No-go condition（嚴格遵守）</h3>
<p>跨雲 / on-prem 需求觸動 <a href="/blog/backend/knowledge-cards/vendor-lock-in/" data-link-title="Vendor Lock-In" data-link-desc="說明採用供應商產品後，其 API 與格式滲入程式碼造成的退出成本">vendor lock-in</a> — Aurora storage layer 是 AWS 專屬、wire protocol 相容不代表退出成本低、long-term 跨雲策略未定時 self-managed PG / MySQL 反而保留路徑。</p>
<table>
  <thead>
      <tr>
          <th>條件</th>
          <th>為什麼是 no-go</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>跨雲 / on-prem 需求</td>
          <td>Aurora AWS-only、wire protocol 相容但 storage 是 AWS 專屬</td>
      </tr>
      <tr>
          <td>需要 latest upstream 特性</td>
          <td>Aurora 通常落後 upstream PostgreSQL / MySQL 1-2 major version</td>
      </tr>
      <tr>
          <td>預算極敏感</td>
          <td>Aurora 比 self-managed PostgreSQL / MySQL 貴 20-30%</td>
      </tr>
      <tr>
          <td>合規禁止跨境複製</td>
          <td>受監管市場 <a href="/blog/backend/knowledge-cards/data-residency/" data-link-title="Data Residency" data-link-desc="合規要求資料留在特定地理邊界內、跨境複製違反合規、推動 fleet 拓樸決策">Data Residency</a> <em>禁止跨境複製</em>、Aurora Global Database 在這種場景 <em>違反合規</em> — 要改用每市場獨立 cluster</td>
      </tr>
      <tr>
          <td>客製化 storage / I/O</td>
          <td>Aurora storage 是 AWS managed、不能客製化（vs self-managed 可以做 cgroup / quota / 自訂 storage 配置）</td>
      </tr>
  </tbody>
</table>
<p><strong>合規禁止跨境複製 no-go</strong>（<a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered 揭露</a>）：</p>
<p>受監管市場資料不能跨境複製、Aurora Global Database 在這種場景違反合規。讀者規劃 Aurora migration 時不能假設「Aurora 一定有 Global Database 選項」— 要改用每市場獨立 cluster（fleet 拓樸吸收合規邊界、見 <a href="../read-replica-scaling/">Aurora read replica scaling</a> fleet SSoT）。</p>
<h3 id="替代方案">替代方案</h3>
<ul>
<li><strong>RDS PostgreSQL / MySQL</strong>：更接近 upstream、單 AZ 便宜、不重寫 storage</li>
<li><strong>自管 + Patroni HA + pgBackRest</strong>：保留控制、跨雲可用</li>
<li><strong>CockroachDB / Aurora DSQL</strong>：multi-region active-active write 需求</li>
</ul>
<h3 id="case-anchor">Case anchor</h3>
<ul>
<li><a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix Aurora consolidation</a>：多套 RDBMS 統一到 Aurora、driver 是 <em>operational consolidation</em>、不是純效能</li>
<li><a href="/blog/backend/09-performance-capacity/cases/draftkings-aurora-financial-ledger/" data-link-title="9.C4 DraftKings：Aurora 撐 100 萬 ops/min 的體育博彩金融帳本" data-link-desc="DraftKings 用 Aurora MySQL 跑體育博彩金融帳本、Super Bowl 流量 &#43;50% 不影響延遲">9.C4 DraftKings</a>：200 個 cluster、按業務切分（不是一個大 cluster + 200 schema）</li>
<li><a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered</a>：受監管場景、合規 lead time 是時程主項</li>
</ul>
<p><strong>Netflix scope warning（必引用）</strong>：</p>
<ul>
<li><a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">case「需要警惕」段第 2 點原文</a>：「Netflix 數據層遠不止 Aurora — 還有 Cassandra（playback metadata）、EVCache（cache layer）、Iceberg（data warehouse）。Aurora 主要是『需要 ACID 的 OLTP 工作負載』、不是『all-purpose store』」</li>
<li>工程含義：consolidation 是 <em>ACID OLTP 整合到 Aurora</em>、不是 <em>所有 store 整合到 Aurora</em></li>
<li>讀者規劃整合範圍時要明示什麼 workload 不在範圍（cache、analytics、time-series、search、KV 高峰）</li>
<li>「+75% performance improvement 是跨多 workload 的最大改善幅度、不是『每個 workload 都 +75%』。實際每個 workload 改善幅度從 10% 到 75% 不等」（case「需要警惕」段第 1 點）</li>
</ul>
<h2 id="diff-audit6-維-source--target-差異盤點">Diff audit：6 維 source / target 差異盤點</h2>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>差異</th>
          <th>主導程度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Schema</td>
          <td>PostgreSQL extension 相容性（pg_cron 改 Lambda / Step Functions、pg_partman 改 manual / native partitioning、TimescaleDB 不支援、PostGIS 支援）；MySQL plugin（HandlerSocket 不支援、audit plugin 改 CloudTrail）</td>
          <td>中</td>
      </tr>
      <tr>
          <td>Operational</td>
          <td>HA model、backup、monitoring、parameter management（postgresql.conf → DB parameter group / cluster parameter group）</td>
          <td>高（主導）</td>
      </tr>
      <tr>
          <td>Paradigm</td>
          <td>保留（single-primary SQL、ACID transaction、wire protocol）</td>
          <td>無變動</td>
      </tr>
      <tr>
          <td>Components</td>
          <td>connection pool（PgBouncer → RDS Proxy 或保留 PgBouncer in front of Aurora）、logical replication（pglogical / Debezium → Aurora 原生支援、但有版本限制）</td>
          <td>中</td>
      </tr>
      <tr>
          <td>Application</td>
          <td>保留（connection string 改 endpoint、SSL config 改 RDS CA、driver 不改）</td>
          <td>低</td>
      </tr>
      <tr>
          <td>Topology</td>
          <td>保留（single-region scaling、若要 multi-region 走另一條 playbook to DSQL）；fleet 拓樸決策（拆幾個 cluster）詳見 <a href="../read-replica-scaling/">read replica scaling</a> fleet SSoT</td>
          <td>中-高</td>
      </tr>
  </tbody>
</table>
<p><strong>主導差異</strong>：Operational layer（HA / backup / monitoring）、不是 schema 或 application。</p>
<h3 id="schema-diff-細節">Schema diff 細節</h3>
<p><strong>PostgreSQL → Aurora PostgreSQL</strong>：</p>
<table>
  <thead>
      <tr>
          <th>Extension</th>
          <th>Aurora 支援</th>
          <th>Migration 策略</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>pg_cron</td>
          <td>不支援</td>
          <td>改 Lambda 排程 + RDS event 或 Step Functions</td>
      </tr>
      <tr>
          <td>pg_partman</td>
          <td>不支援</td>
          <td>改 native declarative partitioning（PostgreSQL 11+）</td>
      </tr>
      <tr>
          <td>TimescaleDB</td>
          <td>不支援</td>
          <td>改 native partition + materialized view、或保留 self-managed</td>
      </tr>
      <tr>
          <td>PostGIS</td>
          <td>支援</td>
          <td>直接遷</td>
      </tr>
      <tr>
          <td>pgvector</td>
          <td>支援（新版）</td>
          <td>確認 Aurora PostgreSQL version、可能需要升級</td>
      </tr>
      <tr>
          <td>pglogical</td>
          <td>不支援</td>
          <td>改 Aurora 原生 logical replication（有版本限制）</td>
      </tr>
  </tbody>
</table>
<p><strong>MySQL → Aurora MySQL</strong>：</p>
<table>
  <thead>
      <tr>
          <th>Plugin</th>
          <th>Aurora 支援</th>
          <th>Migration 策略</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>HandlerSocket</td>
          <td>不支援</td>
          <td>改 SQL access 或 Aurora-specific KV cache</td>
      </tr>
      <tr>
          <td>Vault audit</td>
          <td>不支援</td>
          <td>改 AWS CloudTrail + RDS audit log</td>
      </tr>
      <tr>
          <td>MyRocks engine</td>
          <td>不支援</td>
          <td>改 InnoDB（Aurora 預設）、評估 storage 成本</td>
      </tr>
      <tr>
          <td>MaxScale</td>
          <td>不支援</td>
          <td>改 Aurora reader endpoint 或 RDS Proxy</td>
      </tr>
  </tbody>
</table>
<h3 id="operational-diff-細節">Operational diff 細節</h3>
<table>
  <thead>
      <tr>
          <th>元素</th>
          <th>Self-managed</th>
          <th>Aurora</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>HA</td>
          <td>Patroni / Orchestrator + etcd / ZooKeeper</td>
          <td>Cluster endpoint + 自動 cross-AZ failover</td>
      </tr>
      <tr>
          <td>Backup</td>
          <td>pgBackRest / xtrabackup + S3 lifecycle</td>
          <td>Automated backup + manual snapshot + PITR</td>
      </tr>
      <tr>
          <td>Monitoring</td>
          <td>Prometheus exporter + Grafana</td>
          <td>CloudWatch + Performance Insights</td>
      </tr>
      <tr>
          <td>Parameter</td>
          <td>postgresql.conf / my.cnf</td>
          <td>DB parameter group / cluster parameter group</td>
      </tr>
      <tr>
          <td>Failover testing</td>
          <td>Patroni <code>patronictl failover</code></td>
          <td><code>aws rds failover-db-cluster</code></td>
      </tr>
      <tr>
          <td>WAL / binlog 觀測</td>
          <td><code>pg_stat_wal</code> / <code>SHOW MASTER STATUS</code></td>
          <td>CloudWatch + Performance Insights wait events</td>
      </tr>
  </tbody>
</table>
<h3 id="application-diff-細節">Application diff 細節</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl"># Self-managed PostgreSQL
</span></span><span class="line"><span class="ln">2</span><span class="cl">jdbc:postgresql://primary.internal:5432/mydb?ssl=true&amp;sslmode=verify-full&amp;sslrootcert=/etc/ssl/postgresql.crt
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"># Aurora PostgreSQL
</span></span><span class="line"><span class="ln">5</span><span class="cl">jdbc:postgresql://my-cluster.cluster-xxx.us-east-1.rds.amazonaws.com:5432/mydb?ssl=true&amp;sslmode=verify-full&amp;sslrootcert=rds-ca.pem</span></span></code></pre></div><p>Application 改動量小：connection string 換 endpoint、SSL CA 換 RDS CA、driver 不變。</p>
<p>對應 knowledge card：<a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">failover</a>、<a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">replication-lag</a>。</p>
<h2 id="phase-plan階段切換">Phase plan：階段切換</h2>
<h3 id="phase-0pre-migration-audit2-4-週">Phase 0：Pre-migration audit（2-4 週）</h3>
<p>工作：</p>
<ul>
<li>Extension audit：<code>SELECT * FROM pg_extension</code> / <code>SHOW PLUGINS</code>、列出 source 使用的 extension</li>
<li>Parameter audit：postgresql.conf vs Aurora parameter group、列差異</li>
<li>Application connection string audit：所有服務的 DB connection 點位</li>
<li>Benchmark baseline：write QPS / read QPS / p99 latency</li>
<li>Cost baseline：current self-managed monthly cost vs Aurora estimate</li>
</ul>
<p>Output：</p>
<ul>
<li>Migration feasibility report（含 no-go condition check）</li>
<li>Aurora cluster sizing 估算</li>
<li>Extension migration plan（each extension 對應的策略）</li>
</ul>
<h3 id="phase-1aurora-infra-準備1-2-週">Phase 1：Aurora infra 準備（1-2 週）</h3>
<p>工作：</p>
<ul>
<li>Aurora cluster 開設（dev / staging / prod）</li>
<li>Parameter group 對位（從 source postgresql.conf / my.cnf 翻譯到 Aurora parameter group）</li>
<li>SG / subnet / IAM 設定</li>
<li>RDS Proxy 配置（如需要）</li>
<li>CloudWatch dashboard + Performance Insights baseline</li>
<li>Backup retention 設定（1-35 天）</li>
</ul>
<p>Output：</p>
<ul>
<li>Aurora cluster 待 data load</li>
<li>Monitoring 已 ready、能對照 source 跟 target</li>
</ul>
<h3 id="phase-2data-migration2-8-週依資料量">Phase 2：Data migration（2-8 週、依資料量）</h3>
<p>三條 path、依場景選：</p>
<h4 id="path-aaws-dms-full-load--cdc">Path A：AWS DMS full load + CDC</h4>
<ul>
<li>適合：&lt; 1 TB、可接受 read-only 短窗口</li>
<li>流程：DMS full load → DMS CDC → application cutover</li>
<li>優點：managed、validation 工具齊全</li>
<li>缺點：CDC lag 受 DMS task config 影響、bulk DDL 不友善</li>
</ul>
<h4 id="path-bpg_dump--mysqldump--logical-replication-catch-up">Path B：pg_dump / mysqldump + logical replication catch-up</h4>
<ul>
<li>適合：&gt; 1 TB、要長 CDC 期、預算敏感</li>
<li>流程：snapshot → pg_dump / mysqldump → restore to Aurora → logical replication catch-up → application cutover</li>
<li>優點：成本低、可控性高</li>
<li>缺點：手動步驟多、要自己管 CDC lag</li>
</ul>
<h4 id="path-csnapshot-restore">Path C：Snapshot restore</h4>
<ul>
<li>適合：已在 RDS PostgreSQL / MySQL</li>
<li>流程：RDS snapshot → Aurora restore-from-snapshot → catch-up → application cutover</li>
<li>優點：最快、AWS-internal 操作</li>
<li>缺點：只適用 RDS source、不適用 self-managed</li>
</ul>
<h3 id="phase-3dual-read-validation1-2-週">Phase 3：Dual-read validation（1-2 週）</h3>
<p>工作：</p>
<ul>
<li>Application read 50/50 split source / target</li>
<li>比對 query 結果（per-table checksum + sampling）</li>
<li>量測 latency（Aurora p99 ≤ source × 1.2）</li>
<li>確認 stale read 比例 &lt; 0.01%</li>
</ul>
<p>Output：</p>
<ul>
<li>Validation report：query 結果差異、latency 對照</li>
<li>Go/no-go decision for cutover</li>
</ul>
<h3 id="phase-4cutover-1-小時-window">Phase 4：Cutover（&lt; 1 小時 window）</h3>
<p>工作：</p>
<ul>
<li>Source set read-only</li>
<li>CDC catch-up final（lag → 0）</li>
<li>Application switch endpoint（DNS / service discovery / config flag）</li>
<li>Smoke test（critical path query + write）</li>
<li>Monitor error rate + latency 1 小時</li>
</ul>
<p>Output：</p>
<ul>
<li>Cutover complete</li>
<li>Source 切到 read-only、保留作為 rollback 餘地</li>
</ul>
<h3 id="phase-5cleanup4-8-週">Phase 5：Cleanup（4-8 週）</h3>
<p>工作：</p>
<ul>
<li>Source 保留 1 個月 read-only（rollback window）</li>
<li>確認穩定後 snapshot → S3 archive → decommission</li>
<li>舊 monitoring / backup / runbook archive</li>
</ul>
<p>Output：</p>
<ul>
<li>Source decommissioned</li>
<li>新 runbook + monitoring 為 SSoT</li>
</ul>
<h3 id="本-phase-plan-適用範圍">本 phase plan 適用範圍</h3>
<p><strong>Non-regulated workload</strong>（一般 SaaS / e-commerce / 內部系統）。受監管場景（銀行 / 保險 / 醫療）請見下方「合規驅動遷移的時程模型」段、技術 phase 不變但 lead time 完全不同。</p>
<h2 id="合規驅動遷移的時程模型">合規驅動遷移的時程模型</h2>
<p>受監管產業遷移的關鍵時程是 <em>合規審查 lead time</em>、不是技術遷移時間 — 本段是補充給銀行 / 保險 / 醫療讀者、避免照本 playbook 走嚴重低估時程。</p>
<h3 id="standard-chartered-揭露的時程模型">Standard Chartered 揭露的時程模型</h3>
<p><a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered case</a> 「判讀」段第 3 點 + 「策略」段第 3 點原文：「每個受監管市場的審查可能 3-12 個月、合計遷移時程是『市場數 × 平均審查月份』、不是『技術遷移月份』」。</p>
<p>工程含義：</p>
<ul>
<li>技術 phase plan 假設 2-8 週 data migration + &lt; 1 小時 cutover</li>
<li>合規 lead time 是 <em>獨立軸</em>、可能比技術時程長一個數量級</li>
<li>不同市場合規進度不同步、可能要分批上線</li>
</ul>
<h3 id="合規時程組合">合規時程組合</h3>
<table>
  <thead>
      <tr>
          <th>軸</th>
          <th>時程估算</th>
          <th>不可壓縮原因</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>技術遷移</td>
          <td>2-8 週 data migration + &lt; 1 小時 cutover</td>
          <td>工程可控</td>
      </tr>
      <tr>
          <td>單市場合規審查</td>
          <td>3-12 個月（Standard Chartered case 揭露）</td>
          <td>監管機構 lead time、不是技術問題</td>
      </tr>
      <tr>
          <td>多市場合規 lead time</td>
          <td>市場數 × 平均審查月份（7 市場 × 6 個月 ≈ 3.5 年最壞情況）</td>
          <td>各市場各自審、平行度受監管機構文化影響</td>
      </tr>
      <tr>
          <td>跨境複製禁令審查</td>
          <td>包含在合規審查內、可能讓 Global Database 從候選變反指標</td>
          <td>監管要求 data residency、無 cross-region replication option</td>
      </tr>
  </tbody>
</table>
<h3 id="讀者判讀">讀者判讀</h3>
<ul>
<li>受監管場景 <em>不能</em> 用本 playbook 的「2-8 週 data migration + &lt; 1 小時 cutover」估時程交付給管理層 — 合規 lead time 是時程主項</li>
<li>受監管場景 <em>不能</em> 假設 Aurora Global Database 是 multi-region DR 選項 — 合規禁止跨境複製場景下 Global Database 違反合規（見 <a href="../global-database-multi-region/">global-database-multi-region</a>），要改用每市場獨立 cluster</li>
<li>合規場景的 phase plan 要把每市場當成獨立 mini-migration、用 <em>市場批次</em> 推進、不是一次 big bang</li>
</ul>
<p><strong>scope warning（必明示、case 自承）</strong>：Standard Chartered case 未公開是 PostgreSQL 還是 MySQL、未公開具體 cost 數字 — 引用時不能擴寫「Standard Chartered 用 Aurora PostgreSQL」這類細節（case 用「相關 case study」匿名標明）。</p>
<p><strong>合規時程 scope 警示</strong>：「3-12 個月、7 市場 × 6 個月 ≈ 3.5 年」是 Standard Chartered case 揭露範圍。實際合規 lead time 隨產業（銀行 / 保險 / 醫療）跟國家（東南亞 / 歐盟 / 北美 / 中東）差異大、不是恆定數字。讀者要把自家對應監管框架的實際 lead time 算進來、不是直接套 Standard Chartered 數字。</p>
<h2 id="evidence每階段驗證資料">Evidence：每階段驗證資料</h2>
<table>
  <thead>
      <tr>
          <th>Phase</th>
          <th>Evidence</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Phase 0</td>
          <td>extension list、parameter diff、application SQL 抽樣 test on Aurora dev cluster</td>
      </tr>
      <tr>
          <td>Phase 1</td>
          <td>Aurora cluster ready、monitoring dashboard 跟 source 對照</td>
      </tr>
      <tr>
          <td>Phase 2</td>
          <td>DMS row count match、checksum（per-table MD5）、CDC replication lag &lt; 5 秒</td>
      </tr>
      <tr>
          <td>Phase 3</td>
          <td>query result diff &lt; 0.01%、p99 latency Aurora ≤ source × 1.2、application error rate baseline</td>
      </tr>
      <tr>
          <td>Phase 4</td>
          <td>cutover 完成後 1 小時內 error rate &lt; baseline × 2、write success rate 100%</td>
      </tr>
      <tr>
          <td>Phase 5</td>
          <td>30 天無 rollback trigger、cost 月帳對齊預估</td>
      </tr>
  </tbody>
</table>
<p><strong>受監管追加 evidence</strong>：</p>
<ul>
<li>每市場合規 sign-off 文件（central bank / 金融監管機關）</li>
<li>跨境複製禁令審查記錄</li>
<li>Data residency 驗證測試（資料未流出受監管市場 boundary）</li>
<li>Audit log 連續性驗證（source / target audit log 銜接）</li>
</ul>
<p><strong>回路徑</strong>：<a href="/blog/backend/04-observability/observability-evidence-package/" data-link-title="4.20 Observability Evidence Package" data-link-desc="把 log、metric、trace、audit 與資料品質限制包成可交接證據">4.20 Observability Evidence Package</a> 抽 CDC / latency evidence。</p>
<h2 id="cutover切流決策">Cutover：切流決策</h2>
<p><strong>Cutover window</strong>：</p>
<ul>
<li>建議 4 AM local time（lowest traffic）</li>
<li>預留 4 小時 buffer</li>
<li>受監管場景可能要在合規規定的 maintenance window（例如某些央行規定週日凌晨）</li>
</ul>
<p><strong>Rollback condition</strong>：</p>
<ul>
<li>error rate &gt; baseline × 5</li>
<li>write latency p99 &gt; baseline × 3 持續 10 分鐘</li>
<li>data corruption signal（checksum mismatch、unexpected row count drop）</li>
</ul>
<p><strong>Rollback path</strong>：</p>
<ul>
<li>Application connection string 切回 source</li>
<li>Source 仍 read-write（cutover 前留 read-write 路徑、若已 read-only 要先解凍）</li>
<li>CDC 反向同步（Aurora → source）catch-up</li>
</ul>
<p><strong>Decision owner</strong>：</p>
<ul>
<li>DBA lead + service owner + on-call SRE 三方 sign-off</li>
<li>受監管場景追加 compliance officer sign-off</li>
<li>Cutover decision log 記錄（<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/rollback-condition/" data-link-title="Rollback Condition" data-link-desc="說明決策執行後出現哪些訊號時要撤回、回退或改路線">rollback condition</a> 文件化）</li>
</ul>
<p>對應 knowledge card：<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/rollback-condition/" data-link-title="Rollback Condition" data-link-desc="說明決策執行後出現哪些訊號時要撤回、回退或改路線">rollback-condition</a>。</p>
<h2 id="cleanup雙軌退役">Cleanup：雙軌退役</h2>
<table>
  <thead>
      <tr>
          <th>元素</th>
          <th>Cleanup 策略</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Source database</td>
          <td>read-only 1 個月、確認穩定後 snapshot → S3 archive → decommission</td>
      </tr>
      <tr>
          <td>舊 monitoring</td>
          <td>Prometheus exporter 拆、Grafana dashboard archive、CloudWatch dashboard 為 SSoT</td>
      </tr>
      <tr>
          <td>舊 backup chain</td>
          <td>pgBackRest / xtrabackup retention 保留至合規邊界（金融 7 年、一般 90 天）</td>
      </tr>
      <tr>
          <td>舊 runbook</td>
          <td>Patroni / Orchestrator runbook archive、新 runbook 對 Aurora cluster endpoint</td>
      </tr>
      <tr>
          <td>舊 CDC connector</td>
          <td>DMS task 留 7 天觀察期 → delete；自管 Debezium / pglogical 在 source decommission 同時退役</td>
      </tr>
  </tbody>
</table>
<p><strong>不可逆 cleanup 邊界</strong>：</p>
<ul>
<li>Source decommission 後資料只能從 backup restore</li>
<li>確保 backup 可用性測試通過再 decommission</li>
<li>受監管場景要保留 source backup 到合規 retention（金融 7 年、可能更長）</li>
</ul>
<h2 id="案例對照">案例對照</h2>
<h3 id="netflix-aurora-consolidationoperational-consolidation-的價值">Netflix Aurora consolidation：operational consolidation 的價值</h3>
<p><a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix</a> 多套 RDBMS（PostgreSQL / MySQL / Oracle）→ Aurora、+75% 效能 / -28% 成本。</p>
<p><strong>驗證的 driver</strong>：</p>
<ul>
<li>DB 種類太多本身是規模化的成本（每多一種 DB 多一套 DBA 知識 / backup / monitoring）</li>
<li>整合到 Aurora 釋放工程資源、不是純效能改善</li>
</ul>
<p><strong>case 自帶警示（必引用）</strong>：</p>
<ul>
<li>「+75% 是跨多 workload 最大改善幅度、不是每 workload 都 +75%」（case「需要警惕」段第 1 點）</li>
<li><strong>Aurora 非 all-purpose store 邊界</strong>：「Netflix 數據層遠不止 Aurora — 還有 Cassandra（playback metadata）、EVCache（cache layer）、Iceberg（data warehouse）。Aurora 主要是『需要 ACID 的 OLTP 工作負載』」（case「需要警惕」段第 2 點）</li>
</ul>
<p>工程含義：consolidation 是「ACID OLTP 整合到 Aurora」、不是「所有 store 整合到 Aurora」。讀者規劃整合範圍時要明示什麼 workload 不在範圍：</p>
<table>
  <thead>
      <tr>
          <th>Workload</th>
          <th>是否在 Aurora consolidation 範圍</th>
          <th>替代</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>ACID OLTP</td>
          <td>是</td>
          <td>-</td>
      </tr>
      <tr>
          <td>Playback metadata</td>
          <td>否（Netflix 用 Cassandra）</td>
          <td>Cassandra / ScyllaDB</td>
      </tr>
      <tr>
          <td>Cache layer</td>
          <td>否（Netflix 用 EVCache）</td>
          <td>EVCache / Redis / Memcached</td>
      </tr>
      <tr>
          <td>Data warehouse</td>
          <td>否（Netflix 用 Iceberg）</td>
          <td>Iceberg / Snowflake / Redshift</td>
      </tr>
      <tr>
          <td>Time-series</td>
          <td>否（性能不適合）</td>
          <td>InfluxDB / TimescaleDB self-managed</td>
      </tr>
      <tr>
          <td>Search</td>
          <td>否（無 inverted index 優化）</td>
          <td>Elasticsearch / OpenSearch</td>
      </tr>
  </tbody>
</table>
<h3 id="draftkingsfleet-拓樸-redesign">DraftKings：fleet 拓樸 redesign</h3>
<p><a href="/blog/backend/09-performance-capacity/cases/draftkings-aurora-financial-ledger/" data-link-title="9.C4 DraftKings：Aurora 撐 100 萬 ops/min 的體育博彩金融帳本" data-link-desc="DraftKings 用 Aurora MySQL 跑體育博彩金融帳本、Super Bowl 流量 &#43;50% 不影響延遲">9.C4 DraftKings</a> 200 個獨立 Aurora cluster、按業務切分（不是一個大 cluster + 200 schema）。</p>
<p><strong>驗證的 driver</strong>：</p>
<ul>
<li>Migration 不只是技術切換、也是 cluster 拓樸 redesign</li>
<li>業務本身可切分（每體育類別 / 每地理 / 每產品線）就在 migration 時順便拆 cluster</li>
<li>Blast radius 隔離跟容量規劃分散一起獲得</li>
</ul>
<p><strong>Fleet 拓樸決策</strong>：詳見 <a href="../read-replica-scaling/">Aurora read replica scaling</a> 邊界段 SSoT。本 playbook 提醒 <em>migration 是拆 cluster 的好時機</em>、不展開拓樸決策本身。</p>
<h3 id="standard-chartered合規-lead-time--跨境複製禁令">Standard Chartered：合規 lead time + 跨境複製禁令</h3>
<p><a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered</a> 受監管場景揭露：</p>
<ul>
<li>合規 lead time 是時程主項（3-12 個月 / 市場）</li>
<li>跨境複製禁止讓 Global Database 變反指標</li>
<li>每市場獨立 cluster + cross-AZ failover 是合規場景的標準解</li>
</ul>
<h3 id="反例aurora-不適合的場景">反例：Aurora 不適合的場景</h3>
<ul>
<li>Multi-region active-active write：見 <a href="/blog/backend/01-database/vendors/postgresql/migrate-to-aurora-dsql/" data-link-title="PostgreSQL → Aurora DSQL Migration：PG wire-compatible Distributed SQL 的 Paradigm Shift" data-link-desc="Aurora DSQL（2024-12 re:Invent preview / 2025-05 GA）是 AWS 推的 PG wire-compatible *active-active distributed SQL*、跟 self-managed PG / Aurora PG 不同 paradigm（OCC &#43; snapshot isolation &#43; multi-region strong consistency）。Migration 結構是 *protocol drop-in &#43; paradigm shift*：app SQL 不太改、但 transaction retry / extension 缺位 / 多 region 一致性需重設計。本文走 DSQL vs Aurora PG vs self-managed PG 三軸對比、為什麼遷的三條 driver（global write / operational zero-touch / region resiliency）、Type E phased plan、5 production 踩雷（transaction retry 沒處理 / extension 缺位 / sequence throughput 限制 / Aurora PG 直升 DSQL 不可行 / region failover semantic）、跟 PG → Aurora 跟 PG → CockroachDB 對比">PG → Aurora DSQL Migration</a></li>
<li>跨雲：見 <a href="/blog/backend/01-database/vendors/postgresql/migrate-to-cockroachdb/" data-link-title="PostgreSQL → CockroachDB：三維皆 High 的多重歸類 migration" data-link-desc="PostgreSQL → CockroachDB 是 Schema / Operational / Paradigm 三維皆 High 的 multi-axis migration、實證 [#127](/report/content-structure-by-max-diff-dimension/) 的「多重歸類跟 tie-breaking」規則；主結構走 Type E paradigm shift、Schema 差 &#43; Operational redesign 抽出獨立段；涵蓋 transaction model 重設計、SQL dialect gap、5 個 production 踩雷">PG → CockroachDB Migration</a></li>
<li>極端寫入吞吐（&gt; 100K WPS）：考慮 sharding、CockroachDB、或 DynamoDB</li>
</ul>
<h2 id="邊界與整合--下一步">邊界與整合 / 下一步</h2>
<p><strong>Sibling playbook</strong>：</p>
<ul>
<li><a href="/blog/backend/01-database/vendors/postgresql/migrate-to-aurora-dsql/" data-link-title="PostgreSQL → Aurora DSQL Migration：PG wire-compatible Distributed SQL 的 Paradigm Shift" data-link-desc="Aurora DSQL（2024-12 re:Invent preview / 2025-05 GA）是 AWS 推的 PG wire-compatible *active-active distributed SQL*、跟 self-managed PG / Aurora PG 不同 paradigm（OCC &#43; snapshot isolation &#43; multi-region strong consistency）。Migration 結構是 *protocol drop-in &#43; paradigm shift*：app SQL 不太改、但 transaction retry / extension 缺位 / 多 region 一致性需重設計。本文走 DSQL vs Aurora PG vs self-managed PG 三軸對比、為什麼遷的三條 driver（global write / operational zero-touch / region resiliency）、Type E phased plan、5 production 踩雷（transaction retry 沒處理 / extension 缺位 / sequence throughput 限制 / Aurora PG 直升 DSQL 不可行 / region failover semantic）、跟 PG → Aurora 跟 PG → CockroachDB 對比">PG → Aurora DSQL</a> — paradigm shift、Type E、multi-region active-active</li>
<li><a href="/blog/backend/01-database/vendors/postgresql/migrate-to-cockroachdb/" data-link-title="PostgreSQL → CockroachDB：三維皆 High 的多重歸類 migration" data-link-desc="PostgreSQL → CockroachDB 是 Schema / Operational / Paradigm 三維皆 High 的 multi-axis migration、實證 [#127](/report/content-structure-by-max-diff-dimension/) 的「多重歸類跟 tie-breaking」規則；主結構走 Type E paradigm shift、Schema 差 &#43; Operational redesign 抽出獨立段；涵蓋 transaction model 重設計、SQL dialect gap、5 個 production 踩雷">PG → CockroachDB</a> — cross-cloud、paradigm shift</li>
<li><a href="/blog/backend/01-database/vendors/postgresql/migrate-to-aurora/" data-link-title="PostgreSQL → Aurora Migration：protocol 相容、operational 重設計" data-link-desc="Aurora 號稱 PostgreSQL-compatible 但 operational model 不同（storage decouple / cluster endpoint / instance class / 自家備份）；遷移流程是混合（protocol drop-in &#43; operational phased）、5 個 production 踩雷（extension 不支援 / replication slot 不直通 / autovacuum 行為差 / IAM 認證強制 / cost model 換算）、跟 Patroni / read replica / DR 對位">PG → Aurora</a> — 既有 PG-specific playbook、可對照本 playbook 的 vendor-neutral 版本</li>
</ul>
<p><strong>Sibling deep article</strong>：</p>
<ul>
<li><a href="../storage-architecture/">Aurora storage architecture</a> — 理解 storage 設計才知道為什麼 operational redesign</li>
<li><a href="../cross-az-failover-rto/">Aurora cross-AZ failover RTO</a> — HA redesign 主項</li>
<li><a href="../read-replica-scaling/">Aurora read replica scaling</a> — fleet 治理 SSoT、含合規 driver</li>
<li><a href="../global-database-multi-region/">Aurora Global Database</a> — 合規禁止跨境複製的 anti-recommendation</li>
</ul>
<p><strong>1.x 章節互引</strong>：</p>
<ul>
<li><a href="/blog/backend/01-database/large-scale-db-migration/" data-link-title="1.12 大規模 DB 遷移實戰" data-link-desc="跨 DB 遷移的 dual-write、[shadow read](/backend/knowledge-cards/shadow-read/)、cutover、rollback 流程 — 從實戰案例提煉的工程做法">1.12 大規模 DB 遷移實戰</a> — migration 上游 framework</li>
</ul>
<p><strong>何時不用本 playbook</strong>：</p>
<ul>
<li>從 Aurora 遷到別處（反向、走對應的反向 playbook）</li>
<li>從 RDS PostgreSQL 升 Aurora PostgreSQL 是 in-place upgrade、用 RDS console「Convert to Aurora」即可、不需要這套 playbook</li>
<li>跨雲遷移：本 playbook 不涵蓋 GCP / Azure SQL → Aurora 流程</li>
</ul>
<h2 id="相關連結">相關連結</h2>
<ul>
<li><a href="/blog/backend/01-database/vendors/aurora/" data-link-title="AWS Aurora" data-link-desc="AWS managed PostgreSQL / MySQL、storage / compute 分離、&#43;75% 效能改善的 production 證據">Aurora vendor overview</a> — 服務定位、適用 / 不適用場景</li>
<li><a href="/blog/backend/knowledge-cards/failover/" data-link-title="Failover" data-link-desc="說明主要服務或節點失效時如何切換到備援能力">Failover 卡片</a> — 概念基底</li>
<li><a href="/blog/backend/knowledge-cards/replication-lag/" data-link-title="Replication Lag" data-link-desc="說明資料副本落後正式來源多久，以及它如何影響讀取正確性">Replication Lag 卡片</a> — operational diff 主軸</li>
<li><a href="/blog/backend/knowledge-cards/rollback-window/" data-link-title="Rollback Window" data-link-desc="說明變更進入 production 後還能用哪種方式回退或改路線的時間與條件">Rollback Window 卡片</a> — cutover decision</li>
<li><a href="/blog/backend/knowledge-cards/rollback-condition/" data-link-title="Rollback Condition" data-link-desc="說明決策執行後出現哪些訊號時要撤回、回退或改路線">Rollback Condition 卡片</a> — rollback trigger</li>
<li><a href="/blog/backend/09-performance-capacity/cases/netflix-aurora-consolidation/" data-link-title="9.C23 Netflix：把關聯式 DB 統一到 Aurora、效能 &#43;75%、成本 -28%" data-link-desc="Netflix 把多套關聯式 DB 統一到 Aurora、效能提升 75%、成本下降 28%、串流數十億小時">9.C23 Netflix</a> — operational consolidation 跟 Aurora 非 all-purpose store 邊界</li>
<li><a href="/blog/backend/09-performance-capacity/cases/draftkings-aurora-financial-ledger/" data-link-title="9.C4 DraftKings：Aurora 撐 100 萬 ops/min 的體育博彩金融帳本" data-link-desc="DraftKings 用 Aurora MySQL 跑體育博彩金融帳本、Super Bowl 流量 &#43;50% 不影響延遲">9.C4 DraftKings</a> — fleet 拓樸 redesign</li>
<li><a href="/blog/backend/09-performance-capacity/cases/standard-chartered-aurora-banking/" data-link-title="9.C14 Standard Chartered：受監管銀行的 Aurora 4000 TPS 容量提升" data-link-desc="Standard Chartered 銀行遷移到 Aurora 後吞吐量提升 10 倍至 4000 TPS、跨 7 個受監管市場">9.C14 Standard Chartered</a> — 合規 lead time + 跨境複製禁令</li>
<li><a href="/blog/posts/migration-playbook-%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84stage-0-variant-%E8%A6%8F%E5%8A%83%E6%8A%8A-collapse-%E7%8E%87%E5%BE%9E-60-%E9%99%8D%E5%88%B0-0/" data-link-title="Migration Playbook 方法論的演化紀錄：Stage 0 variant 規劃把 collapse 率從 60% 降到 0%" data-link-desc="跨 vendor migration playbook 需要獨立寫作方法論的依據，以及這套方法論從三輪 batch dogfood 中演化出來的驗證證據。">Migration Playbook 寫作方法論</a> — 本文遵循的 6 規格面寫作模板</li>
<li>官方：<a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Migrating.html">Aurora migration documentation</a></li>
</ul>
]]></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></channel></rss>