DynamoDB を導入してしばらく経ったころ、月次の AWS 請求書を見て思わず固まった経験はないだろうか。RDB に慣れたインフラエンジニアが DynamoDB に移行すると、最初は「RDS よりスケーラブルで管理が楽」と感じる。ところが本番トラフィックが乗り始めると、キャパシティ設定の誤りや Scan の多用、古いデータが溜まり続けるテーブルが積み重なり、「気づいたら月数万円」という状況が起きやすい。
この記事では、DynamoDB のコスト構造を正確に把握した上で、キャパシティモードの切り替え判断・DAX による Read コスト削減・TTL を使ったストレージ最適化まで、現場で即実践できる手法を体系的に解説する。
なぜ DynamoDB はコストが予測しにくいのか?
RDS と比べたとき、DynamoDB のコストが把握しにくい理由は「料金の変数が多い」点にある。
RDS はインスタンスサイズ × 時間 + ストレージ GB という比較的シンプルな構造だ。一方 DynamoDB は以下の要素が重なる。
・キャパシティモード: オンデマンドかプロビジョニングか、どちらを選ぶかで単価が大きく変わる
・読み書きの種類: Eventually Consistent Read と Strongly Consistent Read、Transactional Write ではコストが異なる
・GSI(グローバルセカンダリインデックス): テーブルとは別に RCU/WCU が消費される
・ストレージ: 古いデータが溜まると GB 単価がじわじわ積み上がる
・データ転送: 同一リージョン内でも DynamoDB → EC2 は無料だが、リージョン外への転送は課金される
・オプション機能: DynamoDB Streams・DAX・Point-in-Time Recovery(PITR)はそれぞれ追加課金の対象となる
これだけの変数があるにもかかわらず、デフォルトのオンデマンドモードで「とりあえず使い始める」ケースが多く、気づかないうちにコストが膨らむパターンが現場では頻発する。
キャパシティモードの選択(コスト最適化の第一歩)
DynamoDB のコスト構造の中核は「キャパシティモード」にある。ここを間違えると、他の最適化が霞んでしまうくらい差がつく。
1. オンデマンドモード
オンデマンドは、実際に使ったリクエスト数に応じて課金される従量課金型だ。
東京リージョン(ap-northeast-1)の料金は以下のとおり(2026年6月時点)。
| 操作種別 | 単価(USD) | 備考 |
|---|---|---|
| 読み取りリクエスト(RRU) | $0.25 / 100万リクエスト | Strongly Consistent は 2倍消費 |
| 書き込みリクエスト(WRU) | $1.25 / 100万リクエスト | Transactional Write は 2倍消費 |
| ストレージ | $0.25 / GB / 月 | 最初の 25GB は無料枠あり |
オンデマンドの利点は「事前に RCU/WCU を予測しなくてよい」ことだ。スタートアップの初期フェーズや、トラフィックが予測しにくいサービスには適している。ただしトラフィックが安定してくると割高になる傾向があり、プロビジョニングモードへの移行を検討する余地が生まれる。
2. プロビジョニングモード
プロビジョニングモードは、あらかじめ RCU/WCU を確保する方式だ。
| 項目 | 単価(東京リージョン、2026年6月時点) |
|---|---|
| プロビジョニング RCU | $0.00013 / RCU / 時間 |
| プロビジョニング WCU | $0.00065 / WCU / 時間 |
例えば 100 WCU を常時確保すると、月額は 100 × $0.00065 × 720時間 ≒ $46.80 だ。オンデマンドで同じ量の書き込みをさばく場合、1日あたり 100万件を超えるようなワークロードではプロビジョニングのほうが安くなり始める計算になる。
プロビジョニングモードに「Auto Scaling」を組み合わせれば、設定した上限・下限の範囲内で自動的にキャパシティが増減する。ベースラインが読めて、ピーク時のみスパイクするワークロードに有効だ。
3. どちらを選ぶべきか
判断の目安を整理すると次のようになる。
| 状況 | 推奨モード | 理由 |
|---|---|---|
| 開発・テスト環境 / 低トラフィック初期 | オンデマンド | アイドル時間の無駄な予約費用が発生しない |
| トラフィックが安定・予測可能 | プロビジョニング + Auto Scaling | 同じ処理量でオンデマンドより低コストになる |
| バースト性が高く、オフピークが長い | プロビジョニング + Auto Scaling | 低い下限を設定してオフピーク時の無駄を削減できる |
| 突発的な超大規模バーストが想定される | オンデマンド | プロビジョニング上限を突破してスロットリングが起きるリスクを回避できる |
実運用では「6か月分の CloudWatch メトリクスでトラフィックパターンを確認 → プロビジョニングに切り替え → Auto Scaling の上下限をメトリクス実績から設定」という手順が最も確実だ。
読み取り/書き込みコスト削減テクニック
キャパシティモードを最適化したら、次は 1 リクエストあたりの消費コストを下げる方向に目を向ける。
1. DAX(DynamoDB Accelerator)でRead料金を削減
DAX は DynamoDB のインメモリキャッシュだ。キャッシュヒット率が高いワークロードでは、DynamoDB 本体への RCU 消費を大幅に削減できる。
DAX ノードはマイクロサービスアーキテクチャや EC2 / ECS から利用する場合に特に効果が高い。料金はノードのインスタンスタイプ × 時間で課金され、最小構成でも月額数千円~数万円程度かかるため、Read が一定量を超えるワークロードに限定して導入するのが正解だ。
DAX の導入前後でコスト比較をするには、以下の指標を測定する。
・CloudWatch ConsumedReadCapacityUnits: DynamoDB 本体が実際に消費した RCU
・DAX CacheMisses / CacheHits: DAX がどれだけ効いているかの指標
・DAXノード料金 vs RCU削減額: 純粋な削減効果の比較
# AWS CLI: DAXクラスターの作成例(東京リージョン) aws dax create-cluster \ --cluster-name my-dax-cluster \ --node-type dax.r4.large \ --replication-factor 1 \ --iam-role-arn arn:aws:iam::123456789012:role/DAXRole \ --region ap-northeast-1
本番用途では `–replication-factor 3` でマルチAZにするが、コスト検証目的の開発環境ならレプリケーションファクター 1 で動作確認するのも手だ。
2. プロジェクション式で不要データを取得しない
DynamoDB では `GetItem` や `Query` で全属性を取得するとアイテムサイズが丸ごと RCU に計上される。必要な属性だけを `ProjectionExpression` で指定すると、転送量削減の副次効果もある(ただし RCU は 1 キャパシティユニット = 4KB 単位なので小さなアイテムには効果が薄い点も念頭に置く)。
# AWS CLI: 特定属性のみ取得(ProjectionExpression) aws dynamodb get-item \ --table-name Orders \ --key '{"OrderId":{"S":"order-001"}}' \ --projection-expression "Status, TotalAmount" \ --region ap-northeast-1
3. Scanを避け、QueryとGSIを使い分ける
DynamoDB で最もコストを無駄にする操作が `Scan` だ。テーブル全件を舐めるため、データが増えるほどコストが線形に増加する。
対策としてまず確認するのは「そのアクセスパターンに GSI(グローバルセカンダリインデックス)を用意できるか」だ。GSI を使って `Query` に変換できれば、消費 RCU を数分の一に抑えられることがある。
ただし GSI 自体にも WCU(ベーステーブルへの書き込みのたびに GSI も更新される)とストレージコストがかかる。不要な GSI を放置しないことも重要な最適化ポイントだ。
| 操作 | 消費RCU | コスト傾向 |
|---|---|---|
| GetItem(1アイテム取得) | 1 RCU(4KB以内) | 最も効率的 |
| Query(PK + SK範囲指定) | 取得合計サイズに比例 | インデックスを活かせば低コスト |
| Scan(フルテーブル) | テーブル全データサイズに比例 | データ増加とともに急増する |
既存コードに Scan が多用されている場合、アクセスパターンを洗い出して「Query + GSI」に置き換えるリファクタリングがコスト削減の近道だ。
ストレージコスト削減(TTLとアーカイブ戦略)
DynamoDB のストレージ料金は $0.25/GB/月と一見安価に見えるが、ログデータやセッション情報・履歴データが溜まり続けると無視できない金額になる。
1. TTL(Time to Live)の設定
TTL は属性に Unix タイムスタンプ(秒)を設定しておくと、その時刻を過ぎたアイテムを DynamoDB が自動削除してくれる機能だ。削除処理自体は無料で、WCU を消費しない。
# AWS CLI: TTLを有効化(属性名 "ExpiresAt" を使う場合) aws dynamodb update-time-to-live \ --table-name Sessions \ --time-to-live-specification "Enabled=true,AttributeName=ExpiresAt" \ --region ap-northeast-1 # Python (boto3): アイテム書き込み時にTTLを設定する例 import boto3, time dynamodb = boto3.resource('dynamodb', region_name='ap-northeast-1') table = dynamodb.Table('Sessions') table.put_item(Item={ 'SessionId': 'abc123', 'UserId': 'user-001', 'ExpiresAt': int(time.time()) + 86400 # 24時間後に自動削除 })
TTL 削除は即時ではなく、有効期限から最大 48 時間程度の遅延がある。アプリケーション側でも有効期限チェックを入れておくのが現場のベストプラクティスだ。
2. S3へのエクスポートとコールドデータ分離
履歴データや監査ログなど「参照頻度は低いが削除できない」データは、DynamoDB から S3 にエクスポートして保管する方法が有効だ。
DynamoDB の「S3へのエクスポート」機能を使えば、テーブルの特定時点のスナップショットを S3 に JSON 形式で出力できる。出力後、DynamoDB 側のデータを削除することでストレージコストを削減しつつ、S3(Glacier Deep Archive 等)で低コストに長期保管できる。
# AWS CLI: DynamoDBテーブルをS3にエクスポート aws dynamodb export-table-to-point-in-time \ --table-arn arn:aws:dynamodb:ap-northeast-1:123456789012:table/AuditLogs \ --s3-bucket my-archive-bucket \ --s3-prefix dynamodb-exports/ \ --export-format DYNAMODB_JSON \ --region ap-northeast-1
このエクスポート機能は PITR(Point-in-Time Recovery)が有効なテーブルでのみ利用できる点に注意が必要だ。PITR 自体は追加課金となるため、有効/無効のバランスをテーブルごとに判断する。
DynamoDB料金の仕組みとコスト監視のポイント
コスト最適化を継続するには、現状を数値で把握することが不可欠だ。以下のメトリクスを CloudWatch で定常的に監視しておく。
・ConsumedReadCapacityUnits / ConsumedWriteCapacityUnits: 実際に消費されたキャパシティ量。プロビジョニング上限に対してどのくらい消費しているかを確認する
・ThrottledRequests: スロットリングが発生していればプロビジョニングが不足している。ゼロに保つのが理想だが、まれに発生する程度なら Auto Scaling の設定見直しで対処できる
・SuccessfulRequestLatency: DAX 導入後のレイテンシ比較に使う。キャッシュヒット時は 1桁ミリ秒まで下がる
・TableSize / ItemCount: ストレージ肥大化の早期検知に役立てる
AWS Cost Explorer の「サービス別」フィルタで DynamoDB を選び、「使用タイプ別」にブレークダウンすると「WriteCapacityUnit-Hrs」「ReadCapacityUnit-Hrs」「TimedStorage-ByteHrs」のどれがコストの主因かが一目でわかる。費用の大きい項目から順に手を打つのが効率的だ。
よくある無駄遣いパターンと対処法
現場でよく見かける DynamoDB コストの無駄遣いをまとめた。
・使われていない GSI が複数残っている: 書き込みのたびに GSI にも WCU が消費される。CloudWatch で GSI ごとの ConsumedWriteCapacityUnits を確認し、使われていない GSI は削除する
・PITR を全テーブルで有効化している: 開発テーブルや一時テーブルまで PITR を入れている場合は個別に無効化を検討する
・Scan をバッチ処理で多用している: バックオフィスツールやデータ集計で安易に Scan を使っている場合は、S3 エクスポートや Amazon Athena との組み合わせに切り替える
・DynamoDB Streams を使っていないのに有効化している: Streams 自体の料金は読み取りリクエスト数に応じて発生する。使っていなければ無効化する
・オンデマンドモードのまま高トラフィックになっている: 月次の Cost Explorer で WRU/RRU の消費量を確認し、プロビジョニングに切り替えるタイミングを逃さない
・Transactional Write を多用している: TransactWriteItems は通常の書き込みの 2倍の WCU を消費する。本当にトランザクションが必要かどうかを設計レベルで見直す
オンプレの RDBMS に慣れたエンジニアがやりがちなのが「全属性取得」や「集計クエリの多用」だ。DynamoDB ではアクセスパターンをテーブル設計に落とし込む考え方が基本であり、オンプレの感覚でクエリを書くとコストが跳ね上がる。
本記事のまとめ
DynamoDB のコスト最適化は「キャパシティモードの選択」「アクセスパターンの設計」「不要データの削除」という 3 つの柱に集約される。
| 最適化ポイント | やること | 期待削減効果 |
|---|---|---|
| キャパシティモード切替 | トラフィック安定後はプロビジョニング + Auto Scaling へ移行 | 同一処理量で 30~50% 削減 |
| DAX 導入 | Read ヘビーなワークロードでキャッシュを活用 | RCU 消費を 70~90% 削減(キャッシュヒット率次第) |
| Scan 撲滅 | Query + GSI に置き換える | RCU 消費を数分の一に削減 |
| TTL 設定 | 期限付きデータに TTL 属性を付ける | ストレージ料金の継続的な抑制 |
| 不要 GSI の削除 | CloudWatch で GSI 使用状況を確認し削除 | WCU 消費と管理コストの削減 |
| S3 エクスポート | コールドデータを S3 Glacier にアーカイブ | ストレージ単価を大幅に削減 |
まずは Cost Explorer で DynamoDB の使用タイプ別の内訳を確認し、コストの大半を占める項目から着手するのが現実的だ。クラウド上の Linux サーバー構築や EC2 の基礎については、姉妹サイトLinuxMaster.JPでも詳しく解説しているので参照してほしい。
DynamoDB の請求書、毎月ドキッとしていませんか?
キャパシティモードの選び方やアクセスパターン設計は、一度覚えれば長く使えるスキルです。
オンプレの経験を活かしながら、現場で使えるクラウドスキルを体系的に身につけたい方へ、メルマガで実践的なクラウド活用ノウハウをお届けしています。
