DynamoDB キャパシティモード完全ガイド:プロビジョニング vs オンデマンド、本番運用で失敗しない選択基準

新しいサービスを立ち上げるとき、DynamoDBのキャパシティモード選択で迷うのはよくある話だ。トラフィックパターンが読めない段階でプロビジョニングモードを選ぶと、スロットリングで障害を起こすか、過剰なコストを払うかのどちらかになる。この記事では、DynamoDBキャパシティモードの仕組みと、実際の運用判断基準を具体的に解説する。

TL;DR:DynamoDBキャパシティモード選択早見表

判断軸オンデマンドプロビジョニング
トラフィック予測可能性不明・不規則安定・予測可能
スロットリングリスク低い(自動スケール)設定次第で高い
コスト特性リクエスト単価が高い安定負荷なら割安
Auto Scaling併用不要(組み込み)推奨(必須に近い)
切り替え頻度制限24時間に1回まで同左
向いているフェーズ開発・ローンチ初期・突発トラフィック成熟サービス・高スループット安定期

DynamoDBキャパシティモードの仕組みを理解する

DynamoDBのスループットは、読み込みキャパシティユニット(RCU)と書き込みキャパシティユニット(WCU)という単位で管理される。1 RCUは最大4KBのアイテムに対する強整合性読み込み1回、1 WCUは最大1KBのアイテムへの書き込み1回に対応する。この前提を押さえた上で、2つのモードの動作を見ていく。

graph LR Client["クライアント"] --> Request["リクエスト"] Request --> ModeCheck{"キャパシティモード?"} ModeCheck -->|"オンデマンド"| OnDemand["自動キャパシティ割り当て
(PAY_PER_REQUEST)"] ModeCheck -->|"プロビジョニング"| Provisioned["事前設定RCU/WCU"] OnDemand --> AutoScale1["内部自動スケール
(前回ピークの2倍まで即時)"] Provisioned --> Check{"キャパシティ内?"} Check -->|"Yes"| Success["リクエスト成功"] Check -->|"No"| Throttle["スロットリング
ProvisionedThroughputExceededException"] AutoScale1 --> Success
  1. オンデマンドモード:リクエストが来るたびにDynamoDBが自動でキャパシティを割り当てる。事前設定不要。ピーク時も自動で対応するが、直前のトラフィック量に基づいて内部的に上限が設定されている。
  2. プロビジョニングモード:RCU/WCUを事前に指定する。指定値を超えるリクエストはスロットリング(ProvisionedThroughputExceededException)される。Auto Scalingと組み合わせることで動的に調整できる。
  3. モード切り替え:テーブルごとに24時間に1回まで切り替え可能。切り替え中もテーブルはオンラインのまま。

オンデマンドモードの実際の挙動と注意点

オンデマンドモードは「無制限にスケールする」と思われがちだが、正確ではない。AWS公式ドキュメントによると、オンデマンドテーブルには前回のピーク時のトラフィックの2倍まで即座にスケールできるという特性がある。新規テーブルや長期間アイドル状態のテーブルでは、初期の上限が低く設定されているため、突然の大量リクエストでスロットリングが発生することがある。

オンデマンドモードは「スロットリングゼロ保証」ではなく、「事前キャパシティ設定不要」という意味だ。新規テーブルに対して初日から大量リクエストを流すと、内部上限に当たることがある。

これはローンチ直後のキャンペーンや、移行直後のテーブルで実際に問題になるパターンだ。対策としては、事前にプロビジョニングモードで高いRCU/WCUを設定してウォームアップしてからオンデマンドに切り替えるか、段階的にトラフィックを流す設計にする。

プロビジョニングモード+Auto Scalingの設定

トラフィックパターンが読めてきた段階でプロビジョニングモードに移行するなら、Auto Scalingは必須と考えていい。手動設定のみでは、予期しないスパイクへの対応が遅れる。Auto Scalingはターゲット使用率(デフォルト70%)に基づいてRCU/WCUを自動調整するが、スケールアップには数分のラグがある点を理解しておく必要がある。

sequenceDiagram participant App as アプリケーション participant DDB as DynamoDB participant CW as CloudWatch participant AS as Application Auto Scaling App->>DDB: 書き込みリクエスト増加 DDB->>CW: WCU使用率メトリクス送信 CW-->>AS: 使用率がターゲット(70%)超過を検知 AS->>DDB: WCU増加リクエスト Note over AS,DDB: スケールアップに数分のラグあり DDB-->>App: 増加後のキャパシティで処理 App->>DDB: リクエスト減少 CW-->>AS: 使用率低下を検知 AS->>DDB: WCU削減リクエスト

Auto Scaling設定のCLI例

以下は、プロビジョニングモードのテーブルに対してAuto Scalingを設定する手順だ。まずApplication Auto Scalingにスケーラブルターゲットを登録し、次にスケーリングポリシーを適用する。

🔽 Auto Scaling設定CLIコマンド(クリックで展開)
# 1. スケーラブルターゲットの登録(書き込みキャパシティ)
aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id 'table/MyTable' \
  --scalable-dimension 'dynamodb:table:WriteCapacityUnits' \
  --min-capacity 5 \
  --max-capacity 500 \
  --region us-east-1

# 2. スケーリングポリシーの適用(書き込みキャパシティ、ターゲット使用率70%)
aws application-autoscaling put-scaling-policy \
  --service-namespace dynamodb \
  --resource-id 'table/MyTable' \
  --scalable-dimension 'dynamodb:table:WriteCapacityUnits' \
  --policy-name 'MyTableWriteScalingPolicy' \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration '{
    "TargetValue": 70.0,
    "PredefinedMetricSpecification": {
      "PredefinedMetricType": "DynamoDBWriteCapacityUtilization"
    }
  }' \
  --region us-east-1

# 3. スケーラブルターゲットの登録(読み込みキャパシティ)
aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id 'table/MyTable' \
  --scalable-dimension 'dynamodb:table:ReadCapacityUnits' \
  --min-capacity 5 \
  --max-capacity 500 \
  --region us-east-1

# 4. スケーリングポリシーの適用(読み込みキャパシティ)
aws application-autoscaling put-scaling-policy \
  --service-namespace dynamodb \
  --resource-id 'table/MyTable' \
  --scalable-dimension 'dynamodb:table:ReadCapacityUnits' \
  --policy-name 'MyTableReadScalingPolicy' \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration '{
    "TargetValue": 70.0,
    "PredefinedMetricSpecification": {
      "PredefinedMetricType": "DynamoDBReadCapacityUtilization"
    }
  }' \
  --region us-east-1

キャパシティモードの切り替えCLI

既存テーブルのモード切り替えはupdate-tableコマンドで実行できる。切り替えはテーブルがACTIVE状態のときのみ可能で、24時間に1回の制限がある。

# プロビジョニング → オンデマンドへの切り替え
aws dynamodb update-table \
  --table-name MyTable \
  --billing-mode PAY_PER_REQUEST \
  --region us-east-1

# オンデマンド → プロビジョニングへの切り替え
aws dynamodb update-table \
  --table-name MyTable \
  --billing-mode PROVISIONED \
  --provisioned-throughput ReadCapacityUnits=100,WriteCapacityUnits=50 \
  --region us-east-1

# 現在のテーブル設定確認
aws dynamodb describe-table \
  --table-name MyTable \
  --region us-east-1 \
  --query 'Table.{BillingMode:BillingModeSummary.BillingMode,RCU:ProvisionedThroughput.ReadCapacityUnits,WCU:ProvisionedThroughput.WriteCapacityUnits,Status:TableStatus}'

スロットリングの診断:実際の障害パターンと対処

本番でスロットリングが発生したとき、最初に疑うのは「テーブル全体のキャパシティ不足」だが、実際にはパーティションキーの偏り(ホットパーティション)が原因のことが多い。テーブルレベルのメトリクスでは問題が見えないのに、特定のキーへのリクエストが集中してスロットリングが発生するケースだ。

あるECサービスで、セール開始直後に特定の商品IDへのアクセスが集中してスロットリングが発生した。CloudWatchのメトリクスを見るとテーブル全体のWCU使用率は40%程度。「キャパシティは余っているのになぜ?」と混乱したが、原因はホットパーティションだった。DynamoDBはデータをパーティションキーに基づいて内部的に分散するが、特定のキーに集中するとそのパーティションのスループット上限に当たる。

graph TD Throttle["スロットリング発生"] --> Check1{"テーブル全体の
キャパシティ使用率は?"} Check1 -->|"高い(80%以上)"| CapShortage["キャパシティ不足
→ RCU/WCU増加またはオンデマンド切替"] Check1 -->|"低い(50%以下)"| HotPartition["ホットパーティション疑い"] HotPartition --> KeyDesign["パーティションキー設計の見直し
ランダムサフィックス・書き込みシャーディング"] HotPartition --> DAX["DAX導入でキャッシュ層追加"] CapShortage --> AutoScaling["Auto Scaling設定確認
min/max/ターゲット使用率"] AutoScaling --> ModeSwitch["オンデマンドへの切り替え検討"]

スロットリング診断のCLIコマンド

# テーブルレベルのスロットリングメトリクス確認(過去1時間)
aws cloudwatch get-metric-statistics \
  --namespace AWS/DynamoDB \
  --metric-name WriteThrottleEvents \
  --dimensions Name=TableName,Value=MyTable \
  --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
  --period 300 \
  --statistics Sum \
  --region us-east-1

# 読み込みスロットリングの確認
aws cloudwatch get-metric-statistics \
  --namespace AWS/DynamoDB \
  --metric-name ReadThrottleEvents \
  --dimensions Name=TableName,Value=MyTable \
  --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
  --period 300 \
  --statistics Sum \
  --region us-east-1

ホットパーティション問題への対処は、キャパシティ増加では根本解決にならない。パーティションキーの設計見直し(ランダムサフィックスの付与、書き込みシャーディング)や、DAX(DynamoDB Accelerator)によるキャッシュ層の導入が実質的な解決策になる。

IAMポリシー:最小権限でのDynamoDB操作

キャパシティモードの変更やAuto Scaling設定には、複数のサービスにまたがる権限が必要になる。以下は最小権限の原則に基づいたポリシー例だ。

🔽 DynamoDB管理用IAMポリシー(クリックで展開)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DynamoDBTableManagement",
      "Effect": "Allow",
      "Action": [
        "dynamodb:UpdateTable",
        "dynamodb:DescribeTable"
      ],
      "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable"
    },
    {
      "Sid": "AutoScalingManagement",
      "Effect": "Allow",
      "Action": [
        "application-autoscaling:RegisterScalableTarget",
        "application-autoscaling:PutScalingPolicy",
        "application-autoscaling:DescribeScalableTargets",
        "application-autoscaling:DescribeScalingPolicies"
      ],
      "Resource": "*"
    },
    {
      "Sid": "CloudWatchMetrics",
      "Effect": "Allow",
      "Action": [
        "cloudwatch:GetMetricStatistics",
        "cloudwatch:DescribeAlarms"
      ],
      "Resource": "*"
    },
    {
      "Sid": "IAMPassRole",
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::123456789012:role/DynamoDBAutoScalingRole"
    }
  ]
}

application-autoscalingcloudwatchのアクションはリソースレベルの制限をサポートしていないため、"Resource": "*"が必要になる。AWSサービス認可リファレンスで各アクションのリソースレベルサポートを確認することを推奨する。

コスト最適化:モード選択の経済的判断基準

コスト面での判断は、ワークロードの特性によって大きく変わる。一般的な傾向として、オンデマンドモードはリクエスト単価がプロビジョニングモードより高い。安定した高スループットが続くワークロードでは、プロビジョニングモード+Auto Scalingの方がコスト効率が良くなることが多い。ただし、具体的な価格はリージョンや時期によって変動するため、AWS公式の料金ページで最新情報を確認してほしい。

判断の実用的な目安として:

  • オンデマンドが有利なケース:1日のトラフィック変動が10倍以上ある、月間のリクエスト数が少ない、開発・テスト環境
  • プロビジョニングが有利なケース:トラフィックが安定していて予測可能、常時高スループットが必要、Reserved Capacityを購入できる規模

DynamoDBキャパシティモード選択フローチャート

graph TD Start(["DynamoDBテーブル作成"]) --> Q1{"トラフィックパターンは
予測可能?"} Q1 -->|"No / 不明"| OnDemand["オンデマンドモード
PAY_PER_REQUEST"] Q1 -->|"Yes / 安定"| Q2{"常時高スループット
(1000 WCU以上)?"} Q2 -->|"Yes"| Provisioned["プロビジョニングモード
+ Auto Scaling"] Q2 -->|"No / 低〜中"| CostCompare["コスト比較実施
(実測RCU/WCUで試算)"] CostCompare -->|"プロビジョニングが安い"| Provisioned CostCompare -->|"オンデマンドが安い"| OnDemand OnDemand --> Monitor["CloudWatchで使用量監視"] Provisioned --> AutoScalingSetup["Auto Scaling設定
min/max/ターゲット70%"] Monitor --> Review{"3ヶ月後に
パターン確認"} Review -->|"安定化"| CostCompare AutoScalingSetup --> HotCheck["ホットパーティション監視"]
  1. まずトラフィックパターンの予測可能性を判断する。不明な場合はオンデマンドから始める。
  2. 安定したトラフィックが確認できたら、CloudWatchメトリクスで実際のRCU/WCU消費量を計測する。
  3. コスト比較の上でプロビジョニングへの移行を検討する。その際は必ずAuto Scalingを設定する。
  4. ホットパーティションの兆候(テーブル全体のキャパシティに余裕があるのにスロットリングが発生)が見られたら、キー設計の見直しを優先する。

まとめとNext Steps:DynamoDBキャパシティモードの運用指針

トラフィックパターンが不明な段階では、DynamoDBキャパシティモードはオンデマンドから始めるのが実用的な選択だ。ただし「スロットリングゼロ」ではないことを理解した上で、新規テーブルへの急激なトラフィック投入には注意が必要だ。

運用が安定してトラフィックパターンが見えてきたら、CloudWatchのメトリクスを元にコスト比較を行い、プロビジョニングモード+Auto Scalingへの移行を検討する。どちらのモードを選んでも、ホットパーティション問題はキャパシティ増加では解決できない点を覚えておいてほしい。

次のステップとして確認すべきドキュメント:

用語集

用語説明
RCU(Read Capacity Unit)最大4KBのアイテムに対する強整合性読み込み1回、または最大8KBのアイテムに対する結果整合性読み込み1回に相当するキャパシティ単位
WCU(Write Capacity Unit)最大1KBのアイテムへの書き込み1回に相当するキャパシティ単位
スロットリングプロビジョニングされたキャパシティを超えるリクエストがDynamoDBによって拒否されること。ProvisionedThroughputExceededExceptionが返される
ホットパーティション特定のパーティションキーへのリクエストが集中し、そのパーティションのスループット上限に達する状態
Auto ScalingApplication Auto Scalingを使用して、実際のトラフィックに基づいてRCU/WCUを自動調整する機能

Related Posts

コメント

このブログの人気の投稿

EC2 SSH接続タイムアウトの原因と修正方法 — セキュリティグループのインバウンドルール完全ガイド

S3パブリックアクセス拒否の原因と解決策:バケットレベルの「Block Public Access」が優先される仕組み

EC2インスタンスIDをメタデータから取得する方法 — IMDSv2が安全な理由