<?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>Auto-Scaling on Tarragon</title><link>https://tarrragon.github.io/blog/tags/auto-scaling/</link><description>Recent content in Auto-Scaling 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/auto-scaling/index.xml" rel="self" type="application/rss+xml"/><item><title>DynamoDB On-Demand vs Provisioned：6 軸決策、auto-scaling 邊界與 cost crossover</title><link>https://tarrragon.github.io/blog/backend/01-database/vendors/dynamodb/on-demand-vs-provisioned/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/01-database/vendors/dynamodb/on-demand-vs-provisioned/</guid><description>&lt;blockquote>
&lt;p>本文是 &lt;a href="https://tarrragon.github.io/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB&lt;/a> overview 的 implementation-layer deep article。寫作參照 &lt;a href="https://tarrragon.github.io/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">vendor deep article methodology&lt;/a>。&lt;/p>&lt;/blockquote>
&lt;p>quarterly review 看 DynamoDB bill 突然漲 80%、追查發現是 dev team 把所有 table 切 on-demand「省 capacity 管理」。finance 反問「於是省了多少 SRE 工時、又多花多少 cost」、team 答不出來。反向情境：Black Friday 前一週 provisioned table auto-scaling 上限是日常 5 倍、但開賣瞬間流量是 50 倍、auto-scaling 反應週期 5 分鐘、前 10 分鐘大量 throttle。兩個 production 痛點指向同一件事 — capacity mode 選擇不能只看「peak/avg ratio &amp;gt; 5x」單軸閾值。&lt;/p>
&lt;p>本文展開 6 軸決策（peak/avg / 讀寫比 trend / surge 性質 / 事件分級 / DBA 工時釋放 / vendor crossover），把單軸決策樹擴成完整判讀框架。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>DynamoDB 適用度前置判讀&lt;/strong>：本篇假設 workload 已通過 DynamoDB 適用度 4 軸（PK 天然均勻 / control plane vs data plane / consistency 可接受 eventual / access pattern 穩定）— 詳見 &lt;a href="../single-table-design-pattern/#dynamodb-%e9%81%a9%e7%94%a8%e5%ba%a6%e5%89%8d%e7%bd%ae%e5%88%a4%e8%ae%804-%e8%bb%b8">single-table-design-pattern 開頭 4 軸前置判讀&lt;/a>、本篇不重複展開。Capacity mode 選擇是 &lt;em>已選 DynamoDB 後&lt;/em> 的成本決策；若 workload 不適用 DynamoDB、mode 選擇無法救回 vendor 選錯的成本。&lt;/p>&lt;/blockquote>
&lt;h2 id="核心機制兩種-mode-的工程差異">核心機制：兩種 mode 的工程差異&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>屬性&lt;/th>
 &lt;th>Provisioned&lt;/th>
 &lt;th>On-demand&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>計費方式&lt;/td>
 &lt;td>預先買 RCU/WCU、按 hour 計&lt;/td>
 &lt;td>按 request 計、無 capacity 預設&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Auto-scaling&lt;/td>
 &lt;td>動態調整、target utilization 70%、min / max&lt;/td>
 &lt;td>自動 scale、仍受單 partition 1000 WCU / 3000 RCU 上限&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Throttle 表現&lt;/td>
 &lt;td>&lt;code>WriteThrottleEvents&lt;/code> 立即可見、exception 拋出&lt;/td>
 &lt;td>不顯示 throttle、表現為 latency spike（hot partition 隱藏）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Cost 模型&lt;/td>
 &lt;td>可預測、低基礎 rate&lt;/td>
 &lt;td>按用量、cost-per-request 約 provisioned base rate 的 6-7 倍&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Mode 切換限制&lt;/td>
 &lt;td>24 小時內只能切一次&lt;/td>
 &lt;td>同左&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Auto-scaling 內部機制&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>CloudWatch alarm 觸發 → scaling activity → 1-5 分鐘調整 capacity&lt;/li>
&lt;li>target utilization 70%（建議值、留 buffer 給 scale latency）&lt;/li>
&lt;li>連續 spike 仍可能 throttle（auto-scaling 反應週期 &amp;gt; spike 速度）&lt;/li>
&lt;/ul>
&lt;p>對應 knowledge card：&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;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;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></description><content:encoded><![CDATA[<blockquote>
<p>本文是 <a href="/blog/backend/01-database/vendors/dynamodb/" data-link-title="DynamoDB" data-link-desc="AWS managed key-value、partition-based scaling、9000 萬 RPS sustained 實戰證據">DynamoDB</a> overview 的 implementation-layer deep article。寫作參照 <a href="/blog/posts/vendor-%E6%B7%B1%E5%BA%A6%E6%8A%80%E8%A1%93%E6%96%87%E7%AB%A0%E6%96%B9%E6%B3%95%E8%AB%96%E7%9A%84%E6%BC%94%E5%8C%96%E7%B4%80%E9%8C%84%E5%90%8C-vendor-%E7%B3%BB%E5%88%97%E7%9A%84%E9%96%8B%E5%A0%B4%E8%BC%AA%E6%9B%BF%E9%A9%97%E8%AD%89/" data-link-title="Vendor 深度技術文章方法論的演化紀錄：同 vendor 系列的開場輪替驗證" data-link-desc="vendor overview 飽和後要寫單一功能深度文章、需要選題與結構依據時回來。這套方法論的驗證來源與 cadence variant 在高風險場景（同 vendor sub-tool 系列）的實證。">vendor deep article methodology</a>。</p></blockquote>
<p>quarterly review 看 DynamoDB bill 突然漲 80%、追查發現是 dev team 把所有 table 切 on-demand「省 capacity 管理」。finance 反問「於是省了多少 SRE 工時、又多花多少 cost」、team 答不出來。反向情境：Black Friday 前一週 provisioned table auto-scaling 上限是日常 5 倍、但開賣瞬間流量是 50 倍、auto-scaling 反應週期 5 分鐘、前 10 分鐘大量 throttle。兩個 production 痛點指向同一件事 — capacity mode 選擇不能只看「peak/avg ratio &gt; 5x」單軸閾值。</p>
<p>本文展開 6 軸決策（peak/avg / 讀寫比 trend / surge 性質 / 事件分級 / DBA 工時釋放 / vendor crossover），把單軸決策樹擴成完整判讀框架。</p>
<blockquote>
<p><strong>DynamoDB 適用度前置判讀</strong>：本篇假設 workload 已通過 DynamoDB 適用度 4 軸（PK 天然均勻 / control plane vs data plane / consistency 可接受 eventual / access pattern 穩定）— 詳見 <a href="../single-table-design-pattern/#dynamodb-%e9%81%a9%e7%94%a8%e5%ba%a6%e5%89%8d%e7%bd%ae%e5%88%a4%e8%ae%804-%e8%bb%b8">single-table-design-pattern 開頭 4 軸前置判讀</a>、本篇不重複展開。Capacity mode 選擇是 <em>已選 DynamoDB 後</em> 的成本決策；若 workload 不適用 DynamoDB、mode 選擇無法救回 vendor 選錯的成本。</p></blockquote>
<h2 id="核心機制兩種-mode-的工程差異">核心機制：兩種 mode 的工程差異</h2>
<table>
  <thead>
      <tr>
          <th>屬性</th>
          <th>Provisioned</th>
          <th>On-demand</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>計費方式</td>
          <td>預先買 RCU/WCU、按 hour 計</td>
          <td>按 request 計、無 capacity 預設</td>
      </tr>
      <tr>
          <td>Auto-scaling</td>
          <td>動態調整、target utilization 70%、min / max</td>
          <td>自動 scale、仍受單 partition 1000 WCU / 3000 RCU 上限</td>
      </tr>
      <tr>
          <td>Throttle 表現</td>
          <td><code>WriteThrottleEvents</code> 立即可見、exception 拋出</td>
          <td>不顯示 throttle、表現為 latency spike（hot partition 隱藏）</td>
      </tr>
      <tr>
          <td>Cost 模型</td>
          <td>可預測、低基礎 rate</td>
          <td>按用量、cost-per-request 約 provisioned base rate 的 6-7 倍</td>
      </tr>
      <tr>
          <td>Mode 切換限制</td>
          <td>24 小時內只能切一次</td>
          <td>同左</td>
      </tr>
  </tbody>
</table>
<p><strong>Auto-scaling 內部機制</strong>：</p>
<ul>
<li>CloudWatch alarm 觸發 → scaling activity → 1-5 分鐘調整 capacity</li>
<li>target utilization 70%（建議值、留 buffer 給 scale latency）</li>
<li>連續 spike 仍可能 throttle（auto-scaling 反應週期 &gt; spike 速度）</li>
</ul>
<p>對應 knowledge card：<a href="/blog/backend/knowledge-cards/peak-forecast/" data-link-title="Peak Forecast" data-link-desc="說明預期峰值流量的預測方法 — 容量規劃的第一個輸入">peak forecast</a>、<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>、<a href="/blog/backend/knowledge-cards/scheduled-scaling/" data-link-title="Scheduled Scaling" data-link-desc="說明按已知時間表預先擴容的 autoscaler 模式">scheduled scaling</a>。</p>
<h2 id="6-軸決策框架">6 軸決策框架</h2>
<p>mode 選擇不是單軸 peak/avg ratio。下面 6 軸是 9 個 production case（Zomato / Zoom / Amazon Ads / Disney+ / Tixcraft / Capcom / Lemino / Genesys / PayPay）跨 case 揭露的真實決策維度。</p>
<h3 id="軸-1peak--average-流量-ratio">軸 1：peak / average 流量 ratio</h3>
<p>最直覺的軸、但是單軸誤判的根源。基本判讀：</p>
<ul>
<li>高 ratio（spiky / flash-sale）傾向 on-demand</li>
<li>穩定 ratio（sustained / 平緩）傾向 provisioned + auto-scaling</li>
</ul>
<blockquote>
<p><strong>Scope warning</strong>：「peak/avg &gt; 5x → on-demand」、「provisioned base rate × 6-7 = on-demand rate」這些具體閾值是經驗值 / 通用工程估算、<code>9.C5</code> / <code>9.C20</code> case 都沒給具體 ratio 數字。實際 crossover 點隨 region pricing + workload shape 變動、不要照搬本文數字。</p></blockquote>
<p>軸 1 單獨不夠用、要跟軸 2-6 合成判讀。</p>
<h3 id="軸-2讀寫比-trend-變化">軸 2：讀寫比 trend 變化</h3>
<p><code>9.C5 Amazon Ads</code> 揭露的觀測軸：「讀寫比 <em>變化</em> 比讀寫比本身更重要」。</p>
<ul>
<li>絕對讀寫比對容量規劃不是最重要（C5 是 18:1、C27 推估 5:1、絕對值各家不同）</li>
<li>業務邏輯改變（新增即時報表 / 新增推播 / 新增分析 query）會讓讀寫比跳一個量級</li>
<li>觀測上加 metric：read / write ratio 7-day rolling average、超過 ±30% 偏移觸發 review</li>
</ul>
<p>把 trend 變化當 capacity mode 重新評估的訊號 — 不是固定週期 review、是 <em>trend 偏移</em> 觸發 review。</p>
<h3 id="軸-3surge-是-暫時-還是-永久-baseline-上移">軸 3：surge 是 <em>暫時</em> 還是 <em>永久 baseline 上移</em></h3>
<p><code>9.C18 Zoom</code> COVID 30x DAU surge 揭露的軸：surge 後 baseline 永久上移、不會回去。</p>
<ul>
<li>暫時 surge（單日活動 / 季節高峰）：on-demand 划算、活動結束 mode 不用調</li>
<li>永久上移後（Zoom COVID、社會行為改變）：原 on-demand 設計會持續燒錢、要重新算 crossover、考慮切回 provisioned</li>
</ul>
<p><strong>Tripwire</strong>：surge 結束後 4-8 週仍維持 surge 期間 baseline 的 70%+、判定為「永久 baseline 上移」、重評 mode。</p>
<blockquote>
<p><strong>Scope warning</strong>：「4-8 週 / 70% 閾值」屬通用工程估算、9.C18 Zoom case 揭露「surge 後 baseline 不會回去」概念、未揭露具體閾值。</p></blockquote>
<h3 id="軸-4predictable-peak-vs-flash-sale">軸 4：predictable-peak vs flash-sale</h3>
<p><code>9.C27 Disney+</code> 跟 <code>9.C15 Tixcraft</code> 對比揭露的軸：兩種 event-driven peak 不是同一類。</p>
<table>
  <thead>
      <tr>
          <th>維度</th>
          <th>predictable-peak（Disney+ 新片發布）</th>
          <th>flash-sale（拓元售票）</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>時間 lead</td>
          <td>已知日期、提前 1-2 天可預備</td>
          <td>已知時刻、提前 1-5 分鐘有效</td>
      </tr>
      <tr>
          <td>峰值倍數</td>
          <td>metadata 3-5x、持續數小時</td>
          <td>6750x in seconds、t=0 起跳 / t=300 結束</td>
      </tr>
      <tr>
          <td>Scale 方式</td>
          <td>scheduled scaling 預先升 baseline</td>
          <td>scheduled scaling 太慢、必須 pre-provision + composite PK</td>
      </tr>
      <tr>
          <td>Auto-scaling</td>
          <td>跟得上（事件持續時間長）</td>
          <td>完全跟不上（事件時間 &lt; scaling 反應週期）</td>
      </tr>
      <tr>
          <td>後續調回</td>
          <td>事件結束後 scheduled scaling 降回</td>
          <td>結束後立即降回、避免燒錢</td>
      </tr>
  </tbody>
</table>
<p><code>9.C27 Disney+</code>（Marvel / Star Wars 首日 metadata 流量 3-5 倍、持續時段較長）可以提前 1-2 天 pre-scale、scheduled scaling 合適。<code>9.C15 Tixcraft</code> 6750x in seconds，scheduled scaling 太慢、必須事前 pre-provision baseline 拉到極高、或用 on-demand + composite partition key 雙保險。</p>
<p>兩者都不是「peak/avg &gt; 5x → on-demand」單軸決策能解。</p>
<blockquote>
<p><strong>Scope warning</strong>：「scheduled scaling 30-60 分鐘前升 capacity」這個具體 lead time 是經驗值、case 未揭露具體時間。pre-scale 的 lead time 依事件性質決定、不是固定 30-60 分鐘。</p></blockquote>
<h3 id="軸-5dba--sre-工時釋放">軸 5：DBA / SRE 工時釋放</h3>
<p><code>9.C19 Capcom</code> 跟 <code>9.C29 Lemino</code> 揭露的成本軸：DynamoDB 真實成本不只看 monthly bill。</p>
<ul>
<li><code>9.C19 Capcom</code>：30% 成本下降的本質是「工程資源從 DB 運維轉到遊戲品質」、Capcom 是遊戲公司不是 IT 公司、把 DBA 時間從 Postgres patching / replication 設定 / backup 排程釋放到遊戲機制設計</li>
<li><code>9.C29 Lemino</code>：90% 工程工時下降（DBA + connection management + capacity planning 統包）</li>
</ul>
<p><strong>評估公式</strong>：</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">總成本 = direct cost (monthly bill)
</span></span><span class="line"><span class="ln">2</span><span class="cl">       + 工程工時機會成本 (DBA 從 patch/replication/backup 釋放出來做的事)</span></span></code></pre></div><p>on-demand 的 6-7x base rate 在 DBA 工時釋放下、實質 ROI 可能仍正向（特別在小團隊 / 非 IT 主業公司）。但要算總成本、不是只看 bill。</p>
<h3 id="軸-6dynamodb-vs-自管-cluster-cost-crossover">軸 6：DynamoDB vs 自管 cluster cost crossover</h3>
<p><code>9.C20 Zomato</code> 警惕段揭露的最上層決策軸：mode 選擇之上還有 vendor 選擇。</p>
<ul>
<li><code>9.C20 Zomato</code>：「成本降 50% 是 <em>當下流量</em> 的對照」、未來流量繼續成長、DynamoDB cost-per-request 成長率比 TiDB 自管 cluster 高、某流量規模後 crossover、自管 cluster 反而便宜</li>
<li>不是只在 on-demand vs provisioned 之間挑、是要算「未來 12-24 個月在預期流量下、DynamoDB（不論 mode）vs 自管 cluster 的成本曲線」</li>
</ul>
<p>判讀分層：</p>
<ul>
<li><strong>小 / 中流量 startup</strong>：DynamoDB on-demand 簡單划算、不用糾結</li>
<li><strong>大流量 + 流量可預測 + DBA 團隊已存在</strong>：自管 cluster crossover 點可能成立、值得算</li>
<li><strong>大流量 + 流量不可預測 + 小團隊</strong>：DynamoDB managed 仍划算（軸 5 加成）</li>
</ul>
<p>本軸是 mode 選擇之上的更上層決策、不是每次都展開、但寫進邊界判讀條件。</p>
<h2 id="操作流程">操作流程</h2>
<p>從 workload profiling 到 mode 切換的 8 步流程。</p>
<h4 id="step-1workload-profiling">Step 1：workload profiling</h4>
<p>用 CloudWatch 過去 30 天 RCU/WCU、算 p50 / p95 / p99 peak、求 peak/avg ratio（軸 1 輸入）+ read/write ratio rolling avg（軸 2 輸入）。</p>
<h4 id="step-2surge-性質判讀">Step 2：surge 性質判讀</h4>
<ul>
<li>是暫時 surge 還是永久 baseline 上移（軸 3）— 看 surge 結束後 4-8 週的 baseline trend</li>
<li>是 predictable-peak 還是 flash-sale（軸 4）— 看事件時間跟 auto-scaling 反應週期的比例</li>
</ul>
<h4 id="step-36-軸合成決策">Step 3：6 軸合成決策</h4>





<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">軸 1（peak/avg）+ 軸 2（讀寫比 trend）+ 軸 3（surge 性質）
</span></span><span class="line"><span class="ln">2</span><span class="cl">+ 軸 4（事件分級）+ 軸 5（工時機會成本）+ 軸 6（vendor crossover）
</span></span><span class="line"><span class="ln">3</span><span class="cl">→ provisioned + auto-scaling / on-demand / scheduled scaling 三選一</span></span></code></pre></div><p>不是任一軸獨自決定、是 6 軸合成；軸間衝突時優先序：軸 6（vendor）&gt; 軸 5（工時）&gt; 軸 3（surge 永久 vs 暫時）&gt; 軸 4（事件分級）&gt; 軸 1（peak/avg）&gt; 軸 2（讀寫比 trend）。</p>
<h4 id="step-4provisioned-配-auto-scaling">Step 4：provisioned 配 auto-scaling</h4>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="nt">BillingMode</span><span class="p">:</span><span class="w"> </span><span class="l">PROVISIONED</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w"></span><span class="nt">ProvisionedThroughput</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">  </span><span class="nt">ReadCapacityUnits</span><span class="p">:</span><span class="w"> </span><span class="m">100</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">  </span><span class="nt">WriteCapacityUnits</span><span class="p">:</span><span class="w"> </span><span class="m">50</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w"></span><span class="nt">AutoScalingSettings</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">  </span><span class="nt">TargetTrackingScalingPolicy</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">    </span><span class="nt">TargetValue</span><span class="p">:</span><span class="w"> </span><span class="m">70.0</span><span class="w">  </span><span class="c"># target utilization</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">    </span><span class="nt">ScaleOutCooldown</span><span class="p">:</span><span class="w"> </span><span class="m">60</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">    </span><span class="nt">ScaleInCooldown</span><span class="p">:</span><span class="w"> </span><span class="m">60</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">  </span><span class="nt">MinCapacity</span><span class="p">:</span><span class="w"> </span><span class="m">50</span><span class="w">      </span><span class="c"># baseline</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">  </span><span class="nt">MaxCapacity</span><span class="p">:</span><span class="w"> </span><span class="m">1000</span><span class="w">    </span><span class="c"># baseline × 預期 surge multiplier</span></span></span></code></pre></div><p>target utilization 70% 留 buffer 給 scale latency；alarm 設 5 分鐘觀察窗。</p>
<h4 id="step-5scheduled-scaling">Step 5：scheduled scaling</h4>
<p>已知大事件（黑五、開票、新片發布）前預先提升 min capacity、事件後回原值：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 黑五前 24 小時把 min capacity 拉到日常 10 倍</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="n">client</span><span class="o">.</span><span class="n">put_scheduled_action</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="n">ResourceId</span><span class="o">=</span><span class="s2">&#34;table/orders&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="n">ScheduledActionName</span><span class="o">=</span><span class="s2">&#34;black-friday-pre-scale&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="n">Schedule</span><span class="o">=</span><span class="s2">&#34;cron(0 0 * * ? *)&#34;</span><span class="p">,</span>  <span class="c1"># 時間 lead 依事件性質決定、非固定 30-60 分鐘</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">    <span class="n">ScalableTargetAction</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;MinCapacity&#34;</span><span class="p">:</span> <span class="mi">5000</span><span class="p">,</span> <span class="s2">&#34;MaxCapacity&#34;</span><span class="p">:</span> <span class="mi">50000</span><span class="p">}</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="p">)</span></span></span></code></pre></div><h4 id="step-6mode-switch">Step 6：mode switch</h4>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">aws dynamodb update-table <span class="se">\
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="se"></span>  --table-name orders <span class="se">\
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="se"></span>  --billing-mode-summary <span class="nv">BillingMode</span><span class="o">=</span>PAY_PER_REQUEST</span></span></code></pre></div><p>每張 table 24 小時內只能切一次、要計畫 maintenance window。</p>
<h4 id="step-7驗證點">Step 7：驗證點</h4>
<p>切換後第一週對比 cost + throttle metric、確認方向正確：</p>
<ul>
<li>cost 變化方向跟預期一致（on-demand 應該變貴 / provisioned 應該變便宜）</li>
<li>throttle rate 沒上升</li>
<li>latency p99 沒退化</li>
</ul>
<h4 id="step-8總成本評估軸-5--軸-6">Step 8：總成本評估（軸 5 + 軸 6）</h4>
<p>直接 cost + 工時機會成本 + 對照自管 cluster 的 cost crossover 曲線。Quarterly review 用這個公式、不是只看 monthly bill。</p>
<p><strong>Rollback boundary</strong>：on-demand → provisioned 隨時可切、但 baseline 要先 sized 好；切錯方向第一個月可逆、長期累積 cost 不可逆。</p>
<h2 id="失敗模式">失敗模式</h2>
<p>production 觀察到的 6 個典型 anti-pattern：</p>
<h4 id="case-1on-demand-後-cost-翻-3-倍">Case 1：on-demand 後 cost 翻 3 倍</h4>
<p>dev team 切 on-demand「不用管 capacity」、但 workload 是 sustained constant、on-demand 6-7x base rate 全付出來。<code>9.C5 Amazon Ads</code> 明示「sustained workload 用 provisioned + auto-scaling」。修法：穩定 workload 用 provisioned + auto-scaling（軸 1 + 軸 2）。</p>
<h4 id="case-2auto-scaling-跟不上-spike">Case 2：auto-scaling 跟不上 spike</h4>
<p>流量 1 分鐘內 10x、auto-scaling alarm 5 分鐘才觸發、前 4 分鐘全 throttle。修法：peak/avg 高且 spike 突然 → on-demand、或 scheduled scaling 預先升配（軸 1 + 軸 4）；flash-sale 場景 auto-scaling 不夠快、必須 pre-provision。</p>
<h4 id="case-3on-demand-hot-partition-隱藏">Case 3：on-demand hot partition 隱藏</h4>
<p>on-demand 不顯示 throttle、latency 從 5ms 變 50ms、application timeout retry 加劇問題。修法：on-demand 仍要看 partition-level metric（Contributor Insights）、不能假設 mode 解決設計問題（跟 <a href="/blog/backend/01-database/vendors/dynamodb/partition-key-antipatterns/" data-link-title="DynamoDB Partition Key 反模式與 Write Sharding：composite key 修復跟 mode × partition 交叉判讀" data-link-desc="DynamoDB partition 上限 1000 WCU 是 hot partition 的根因；composite key（event_id &#43; shard suffix）跟 calculated shard（hash % N）兩種修法、mode × partition 在 provisioned / on-demand 不同表現，以及 9.C15 Tixcraft 6750x 擴展的工程細節">partition-key-antipatterns</a> cross-link）；mode × partition 交叉判讀。</p>
<h4 id="case-4provisioned-target-utilization-設太高">Case 4：provisioned target utilization 設太高</h4>
<p>target = 90% 看似省、實際每次 spike 都先 throttle 再 scale。修法：70% buffer 給 scale latency、不要為了省 cost 把 utilization 推到極限。</p>
<h4 id="case-5頻繁切-mode-撞-24h-限制">Case 5：頻繁切 mode 撞 24h 限制</h4>
<p>team 想「白天 provisioned 晚上 on-demand」省 cost、但 mode 切換 24h 一次、計畫破產。修法：白天 provisioned + 晚上把 capacity 設低、不切 mode；用 scheduled scaling 處理日週期、不用 mode switch。</p>
<h4 id="case-6surge-後沒重評-mode長期燒錢軸-3-對應">Case 6：surge 後沒重評 mode、長期燒錢（軸 3 對應）</h4>
<p>Zoom 式 30x permanent baseline 上移後、原 on-demand 設計成本爆炸。修法：surge 結束 4-8 週後重評、若 baseline 維持 70%+ 改 provisioned；把「surge 後 mode review」寫進 runbook、不是 ad-hoc 才想到。</p>
<p><strong>Anti-recommendation</strong>：流量 &lt; 100 RPS、cost &lt; $50/月的小 table 不用糾結 mode、on-demand 簡單；workload 穩定且 cost 高才值得做 provisioned + auto-scaling 的工程投入。</p>
<h2 id="容量與觀測">容量與觀測</h2>
<p>CloudWatch metric：</p>
<ul>
<li><code>ConsumedReadCapacityUnits</code> / <code>ConsumedWriteCapacityUnits</code>：基本用量</li>
<li><code>ProvisionedReadCapacityUnits</code> / <code>ProvisionedWriteCapacityUnits</code>：provisioned 預設值</li>
<li><code>ThrottledRequests</code>：provisioned mode 直接訊號、on-demand 為零不代表沒問題</li>
<li><code>SuccessfulRequestLatency</code> p99：on-demand mode 下 hot partition 訊號</li>
</ul>
<p><strong>新增的觀測軸</strong>（軸 2 / 軸 3 對應）：</p>
<ul>
<li>read/write ratio 7-day rolling avg、超過 ±30% 偏移觸發 review</li>
<li>surge baseline 4-week rolling avg、判斷 surge 是暫時還是永久</li>
<li>AWS Cost Explorer 按 table + mode 切 cost trend、月對比</li>
</ul>
<p>Auto-scaling activity log：CloudWatch alarm history + scaling activity，觀察 scaling 是否頻繁但 utilization 仍低（表示 alarm 設太敏感）。</p>
<p><strong>指標口徑紀律</strong>：引用 case 數字時明示口徑 — <code>9.C5</code> 90M reads/sec 是「年度峰值最高一秒、非平均」、<code>9.C20</code> 90% latency 降可能只 p50 不是 p99/p999、<code>9.C18</code> 30x DAU 是「permanent baseline 上移」非單日 peak。讀 vendor case 數字要分「最大瞬時 / 99 百分位 / 常態 / 滾動」四個口徑、不是混用。</p>
<p>Cost gate：每月 finance review 把 DynamoDB cost 對齊 access pattern volume、不只看絕對數字；軸 5 工時釋放跟軸 6 vendor crossover 也納入。</p>
<p>接回 <a href="/blog/backend/09-performance-capacity/capacity-planning/" data-link-title="9.6 容量規劃模型" data-link-desc="peak forecast、headroom budget、growth curve、autoscaling sizing">9.6 容量規劃模型</a>、<a href="/blog/backend/01-database/kv-document-capacity-planning/" data-link-title="1.10 KV / Document DB 容量規劃" data-link-desc="DynamoDB / Cosmos DB / Bigtable / MongoDB 等 KV / Document DB 的容量設計、partition key 取捨、capacity mode 選擇">1.10 KV / Document DB 容量規劃</a>。</p>
<h2 id="邊界與整合">邊界與整合</h2>
<h3 id="frame-8-event-driven-scaling-5-種模式">Frame 8 event-driven scaling 5 種模式</h3>
<p><code>9.C5</code> / <code>9.C15</code> / <code>9.C18</code> / <code>9.C24</code> / <code>9.C27</code> 跨 case 揭露 event-driven scaling 至少 5 種形狀：</p>
<ul>
<li><strong>flash-sale spike</strong>：拓元 6750x in seconds（軸 4 走 pre-provision + composite PK）</li>
<li><strong>predictable peak</strong>：Disney+ 新片首發（軸 4 走 scheduled scaling）</li>
<li><strong>sustained growth</strong>：Amazon Ads / Capcom（軸 1 + 軸 5 → provisioned + auto-scaling）</li>
<li><strong>surge baseline permanent shift</strong>：Zoom 30x DAU 不會回去（軸 3 → 重評 mode）</li>
<li><strong>B2B sustained + 高可用</strong>：Genesys 99.999%（軸 5 + 軸 6 → managed 工時釋放比 cost 重要）</li>
</ul>
<p>不是用「peak/avg &gt; 5x」單一閾值決策、是事件型分類 × 軸合成。</p>
<h3 id="sibling-與-cross-link">Sibling 與 cross-link</h3>
<ul>
<li><a href="/blog/backend/01-database/vendors/dynamodb/partition-key-antipatterns/" data-link-title="DynamoDB Partition Key 反模式與 Write Sharding：composite key 修復跟 mode × partition 交叉判讀" data-link-desc="DynamoDB partition 上限 1000 WCU 是 hot partition 的根因；composite key（event_id &#43; shard suffix）跟 calculated shard（hash % N）兩種修法、mode × partition 在 provisioned / on-demand 不同表現，以及 9.C15 Tixcraft 6750x 擴展的工程細節">partition-key-antipatterns</a> — capacity mode 不解 hot partition、mode × partition 交叉判讀</li>
<li><a href="/blog/backend/01-database/vendors/dynamodb/single-table-design-pattern/" data-link-title="DynamoDB Single-Table Design：從適用度前置判讀到 access pattern 反推 PK/SK" data-link-desc="DynamoDB single-table 設計不是「資料表越少越好」，而是 access pattern 反推 PK/SK 跟 GSI；本文先做 DynamoDB 適用度 4 軸前置判讀（PK 天然均勻 / control plane vs data plane / consistency / access pattern 穩定），再展開設計流程、failure modes 與 durable queue 正向用例">single-table-design-pattern</a> — access pattern 影響 peak/avg ratio 跟 read/write ratio</li>
<li><a href="/blog/backend/01-database/vendors/dynamodb/gsi-lsi-design/" data-link-title="DynamoDB GSI 與 LSI 設計：access pattern 補位、projection、consistency 跟 DAX 補位" data-link-desc="GSI / LSI 是 single-table 沒覆蓋的 access pattern 補位、不是萬靈丹；本文涵蓋 projection 三型選擇、sparse index、GSI 自己會 hot partition、DAX 讀峰值補位的觸發條件（含 Capcom 是 derive vs Lemino 是 case fact 的分層）">gsi-lsi-design</a> — GSI 多時 cost 跟 mode 互動</li>
<li><a href="/blog/backend/01-database/vendors/dynamodb/global-tables-conflict/" data-link-title="DynamoDB Global Tables：multi-region active-active、LWW conflict 與 cross-device sync 正向用例" data-link-desc="Global Tables 不只是 conflict 痛點、也是 cross-device sync / global read / DR failover 的正向工程方案；本文展開 B2B SaaS vs B2C 業務 driver、LWW conflict resolution、reconciliation pipeline，含 Genesys 99.999% 跨 15 region 跟 Disney&#43; 跨裝置同步的對照">global-tables-conflict</a> — 多 region capacity 規劃放大、軸 5 工時釋放在 multi-region 更顯著</li>
<li>Migration playbook：跨 vendor cost optimization（如 <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</a>）對應 type C operational hybrid</li>
<li>替代路由：cost 極度敏感 + 流量穩定 + DBA 團隊已存在 → 自管 PostgreSQL / MySQL 可能更便宜（軸 6 crossover）、回 <a href="/blog/backend/01-database/vendors/postgresql/" data-link-title="PostgreSQL" data-link-desc="多用途 OLTP 主流關聯式資料庫、MVCC、豐富 SQL 特性、是 Aurora / Cosmos DB / Spanner / CockroachDB / Aurora DSQL 的相容目標">PostgreSQL vendor</a></li>
<li>跟 <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 9.C18</a> 互引：30x permanent surge 後的 mode 重評（軸 3 主案例）</li>
<li>跟 <a href="/blog/backend/09-performance-capacity/cases/capcom-gaming-dynamodb-eks/" data-link-title="9.C19 Capcom：Resident Evil / Monster Hunter 在 DynamoDB &#43; EKS 上的遊戲後端" data-link-desc="Capcom 把 Resident Evil、Street Fighter、Monster Hunter 遊戲後端跑在 DynamoDB &#43; EKS、單一秒位數延遲、營運成本降 30%">Capcom 9.C19</a> + <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 9.C29</a> 互引：DBA 工時釋放（軸 5 主案例）</li>
<li>跟 <a href="/blog/backend/01-database/vendors/aurora/read-replica-scaling/" data-link-title="Aurora Read Replica Scaling：15 replica 上限、lag profile、headroom 預留與 fleet 治理" data-link-desc="Aurora 15 replica 上限、共享 storage 為什麼能養大量 replica、事件型容量分級表、DraftKings headroom 預留判讀、FanDuel 雙 SLO 並行、fleet 治理 3 條 driver（business sharding / microservice / 合規）">Aurora read-replica-scaling</a> 共軸 cross-link：本篇從 KV 層 mode 選擇切入、5 模式分類在本篇主寫；Aurora 從 SQL 讀副本視角切入、事件分級表（FanDuel 平日 / playoff / championship / Super Bowl）跟雙 SLO 並行（DraftKings 讀寫雙峰錯位）+ fleet 治理在 Aurora 端主寫、本篇不重複展開</li>
</ul>
]]></content:encoded></item></channel></rss>