メインコンテンツへスキップ
友田 陽大
DynamoDB
AWS
DynamoDB
マルチリージョン
DR
アーキテクチャ設計
Terraform
サーバーレス

DynamoDB Global Tables × マルチリージョン × 災害復旧(DR) 完全ガイド(2026年版):MREC/MRSCの整合性、競合解決、RTO/RPO設計、PITR、コスト

DynamoDB Global Tablesによるマルチアクティブなマルチリージョン分散を、AWS公式仕様に忠実に解説。結果整合(MREC)とマルチリージョン強整合(MRSC)の違いと選び方、last-writer-wins競合解決、RTO/RPOとフェイルオーバー、PITR(35日)とバックアップ、複製書き込みユニットのコストまで、Terraform/TypeScriptの実コードでDR設計を体系化します。

公開日
読了時間
30分
著者
友田 陽大
シェア

「DBを冗長化したい」「リージョン障害でも止めたくない」——この要件に対して、アプリケーション側でレプリケーションキューを組んだり、二重書き込みを手で実装したりするのは、ほぼ常に間違いです。

DynamoDB Global Tablesの核心は、可用性とグローバル性能を「アプリの努力」ではなく「レプリケーションの設計」で買えることにあります。AWSがマルチリージョンの非同期/同期レプリケーションをフルマネージドで提供するので、アプリは自分のリージョンのローカルエンドポイントに読み書きするだけでいい。ただし1つだけ、設計者が必ず理解しておくべき前提があります。整合性モデルです。 ここを誤解したまま導入すると、「更新が静かに消える」「強整合のつもりが古い値を読む」という、再現しにくく深刻な事故を抱え込みます。

本記事は、私がサーバーレス(Lambda + DynamoDB)のマルチテナント決済プラットフォームの信頼性レイヤーを設計・主導し、本番稼働中の二重課金0件を維持してきた経験をベースに、Global TablesとマルチリージョンによるDR(災害復旧)設計だけを体系化したものです。データモデリングや冪等性の設計はシングルテーブル設計&本番信頼性パターンガイドに、キャパシティとコストの基礎はキャパシティ・コスト・性能設計ガイドに譲ります。本記事はそれらと相補的に、**「複数リージョンで、どう止めずに、いくらで動かすか」**に絞ります。

すべての仕様・上限値はAWS公式ドキュメント(2026年6月時点)に照合しています。料金はリージョン・時期で変わるため、金額は必ず公式料金ページで確認してください。


1. Global Tablesの仕組み:マルチアクティブな自動レプリケーション

公式の定義はこうです。

Amazon DynamoDB global tables is a fully managed, multi-Region, and multi-active database feature that provides easy to use data replication and fast local read and write performance for globally scaled applications.(Global Tablesは、フルマネージド・マルチリージョン・マルチアクティブなデータベース機能で、グローバル規模のアプリケーションに、容易なデータレプリケーションと高速なローカル読み書き性能を提供する)

ここから読み取るべき性質を分解します。

  • グローバルテーブル=2つ以上のリージョンにまたがるレプリカテーブルの集合。 1つのリージョンに置けるレプリカは1つだけ。全レプリカは同じテーブル名・同じ主キースキーマ・同じアイテムデータを共有する。
  • マルチアクティブ(active-active)。 どのレプリカも読み取り「と」書き込みを受け付ける。「プライマリ1つ+リードレプリカ」ではない。どのリージョンの視点でも対等
  • 自動レプリケーション。 あるリージョンのレプリカに書き込むと、DynamoDBが他の全レプリカへ自動で複製する。アプリ側のレプリケーション実装は不要。
  • アプリ変更不要。 Global Tablesは既存のDynamoDB APIをそのまま使う。DynamoDBにグローバルエンドポイントは存在せず、すべてのリクエストはリージョナルエンドポイント宛てになる。アプリは「自分のリージョンのローカルエンドポイント」に話しかける。

この最後の点が設計上きわめて重要です。公式のベストプラクティスは明確です。

Calls to DynamoDB should not go across Regions.(DynamoDBへの呼び出しはリージョンをまたぐべきではない)

つまり、東京のアプリは東京のDynamoDBレプリカだけを叩く。リージョンに問題が出たら、エンドユーザーのトラフィックを別リージョンのアプリスタックごと切り替える。Global Tablesは「全リージョンのアプリが同じデータにアクセスできる」状態を保証する土台であって、フェイルオーバーの「判断とルーティング」はアプリ/インフラ側の責務です(4章で詳述)。

可用性:単一リージョン99.99% → マルチリージョン99.999%

公式の数値です。

構成設計上の可用性SLA
単一リージョンテーブル99.99%
マルチリージョン(Global Tables)99.999%

単一リージョンでも、DynamoDBはデータを1リージョン内の3つのアベイラビリティゾーン(AZ)へ自動複製しており、AZ障害には既定で耐えます。Global Tablesが買い足すのは、その上の**「リージョン障害への耐性」**です。


2. 整合性モデル:MREC vs MRSC(ここが設計の心臓部)

Global Tablesを使うなら、最初に1つだけ重い意思決定があります。整合性モード(consistency mode)です。

Global tables support two consistency modes: multi-Region eventual consistency (MREC) and multi-Region strong consistency (MRSC).

重要な制約を先に押さえます。

  • 指定しなければ既定はMREC(結果整合)。
  • 1つのグローバルテーブル内に、異なる整合性モードのレプリカは混在できない。
  • 作成後にモードは変更できない。 後から「やっぱり強整合に」はできない。最初の設計判断が固定される。

2.1 MREC(マルチリージョン結果整合)— 既定・非同期・last-writer-wins

MRECは、アイテムの変更を他の全レプリカへ非同期に複製します。公式いわく**「通常1秒以内(typically within a second or less)」**で伝播します。書き込みはローカルリージョンで完結して即座に返るため、書き込みレイテンシが低いのが利点です。

問題は競合です。同じアイテムが複数リージョンでほぼ同時に更新された場合、どうなるか。

If the same item is modified in multiple Regions simultaneously, DynamoDB will resolve the conflict by using the modification with the latest internal timestamp on a per-item basis, referred to as a "last writer wins" conflict resolution method.

**last-writer-wins(後勝ち)**で解決されます。アイテムごとに内部タイムスタンプを持ち、タイムスタンプが大きい方が勝ち、負けた方の更新は静かに破棄されます。公式の表現がそのまま事故の警告になっています。

The first operation "loses" to the second operation. These conflicts aren't recorded in CloudWatch or AWS CloudTrail.

つまり競合による更新喪失は、CloudWatchにもCloudTrailにも記録されません。気づけないのです。これがMRECで最も深刻な落とし穴で、7章で対策を述べます。

MRECの強整合読み取りには注意点があります。ConsistentRead: true を付けても、

Strongly consistent read operations return the latest version of an item if that item was last updated in the Region where the read occurred, but may return stale data if the item was last updated in a different Region.

「同じリージョンで最後に更新されたなら最新を返すが、別リージョンで更新されたものは古い値を返しうる」。MRECの「強整合」はあくまでローカルリージョン内の話で、グローバルには強整合ではありません。

2.2 MRSC(マルチリージョン強整合)— 2025年6月導入・同期・RPOゼロ

MRSCは比較的新しいモードです(公式の設計ガイドに「introduced in June 2025」と明記)。

Item changes in an MRSC global table replica are synchronously replicated to at least one other Region before the write operation returns a successful response.

書き込みは、成功を返す前に少なくとも1つの他リージョンへ同期複製されます。だからどのレプリカで強整合読み取りしても常に最新を返し、条件付き書き込みも常に最新版に対して評価されます。代償は書き込みと強整合読み取りのレイテンシ増(クロスリージョン通信が入るため)です。

MRSCには固有の制約が多く、ここを知らずに選ぶと詰みます。

  • 正確に3リージョン構成。 「3レプリカ」または「2レプリカ+1 witness」のいずれか。レプリカの追加削除は不可(2レプリカ+witnessのまま、後からレプリカを足せない)。
  • witness(証人) は最新データを保持するがwitnessに対して読み書きはできない。full replicaの代替で可用性のクォーラムを支える。witnessはストレージ・書き込みコストがかからない
  • リージョンセット内限定。 US(バージニア北部/オハイオ/オレゴン)、EU(アイルランド/ロンドン/パリ/フランクフルト)、AP(東京/ソウル/大阪)。セットをまたげない(例:USとEUを混在させたMRSCは作れない)。
  • 空のテーブルからのみ作成可。 既存データを持つ単一リージョンテーブルをMRSCに変換することはできない。
  • TTL非対応・LSI非対応・トランザクション(TransactWriteItems/TransactGetItems)非対応。
  • 競合は後勝ちではなく、同時更新は ReplicatedWriteConflictException で失敗する(リトライ可能)。LWWによる暗黙の更新喪失が起きない代わりに、競合をアプリが明示的にハンドリングする。

2.3 比較表と選び方

観点MREC(既定)MRSC(2025年6月〜)
レプリケーション非同期(通常1秒以内)同期(成功前に他1リージョン以上へ複製)
グローバル強整合読み取り不可(別リージョン更新は古い値もありうる)常に最新を返す
競合解決last-writer-wins(負けは静かに消失)ReplicatedWriteConflictException(明示的失敗・リトライ)
書き込みレイテンシ低い高い(クロスリージョン往復ぶん)
RPO複製遅延ぶん(通常数秒、>0)ゼロ
リージョン構成任意の数・任意のリージョン(パーティション内)正確に3・リージョンセット内・追加削除不可
TTL / LSI / トランザクションTTL可・トランザクションはリージョン内のみ原子すべて非対応
Streams既定で有効(複製に使用)既定無効(複製に未使用・任意で有効化可)
既存テーブルからの変換既存テーブルにレプリカ追加でOK空テーブルからのみ

公式の選び方の基準は明快です。

The key criteria for choosing a multi-Region consistency mode is whether your application prioritizes lower latency writes and strongly consistent reads, or prioritizes global strong consistency.

  • MRECを使うべき: 別リージョン更新が強整合読み取りで一時的に古く見えることを許容できる/書き込みと強整合読み取りのレイテンシを優先したい/RPO > 0 を許容できる
  • MRSCを使うべき: 複数リージョンにまたがるグローバル強整合読み取りが必要/グローバル整合性をレイテンシより優先する/RPOゼロが必須

私の率直な意見を述べます。多くのワークロードでは、まずMRECで十分です。MRSCは「3リージョン固定・リージョンセット限定・TTL/LSI/トランザクション不可・空テーブルから」という制約が重く、これらが要件に刺さらないなら採用コストが見合いません。**「お金や在庫など、グローバルに同時更新されうる単一アイテムを、複数リージョンから強整合で更新する」**という限られたケースでのみMRSCの価値が出ます。それ以外は、MREC+アプリ側のリージョンアフィニティ設計(後述)の方が、安く・速く・柔軟です。

そして、もし**「全部のデータを1リージョンで強整合に読み書きできれば十分」**なら——そもそもGlobal Tablesは要らず、単一リージョン+強整合読み取りが最もシンプルで安い、という選択肢を常に天秤にかけるべきです。


3. ユースケース:低レイテンシ・地理冗長・DR

公式が挙げるGlobal Tables(MREC)の主な価値は3つです。

ユースケース内容
低レイテンシな読み取りデータのコピーをエンドユーザーの近くに置き、読み取りのネットワークレイテンシを下げる
低レイテンシな書き込み近いリージョンに書いて書き込みレイテンシを下げる(ただし競合しないようルーティングを慎重に
シームレスなリージョン移行新リージョンを追加→旧リージョンを削除、でデータ層を無停止で移設できる

そしてMREC・MRSC共通の価値が、本記事の主題です。

Increased resiliency and disaster recovery. If a Region has degraded performance or a full outage, you can evacuate it.

リージョンが劣化/全断したら、そのリージョンを"退避(evacuate)"できる。 MRECならRPO・RTOは秒単位、MRSCならRPOゼロ。これがGlobal TablesによるDRの本質です。「バックアップから復元する」DRと違い、最初から全リージョンに鮮度の高いデータがあるので、復旧とは「復元」ではなく「トラフィックの付け替え」になります。

注:低レイテンシ「書き込み」は諸刃の剣です。複数リージョンから同じアイテムに書くと、MRECではLWW更新喪失、MRSCでは競合例外が起きます。書き込みのルーティング設計(どのアイテムをどのリージョンが書くか)がDR設計と不可分である、という点を7章で深掘りします。


4. DR設計:RTO/RPOと、3つの復旧手段の使い分け

DR設計は、RTO(目標復旧時間)とRPO(目標復旧時点)を要件として先に決め、それを満たす最小コストの手段を選ぶ作業です。DynamoDBには階層の異なる3つの守りがあります。

守りの層障害範囲仕組みRPORTO
マルチAZ(既定・無料AZ障害1リージョン内の3AZへ自動複製。設定不要0透過的(自動フェイルオーバー)
Global Tables(MREC)リージョン障害マルチアクティブ複製。別リージョンへトラフィック退避数秒(複製遅延)秒〜分(ルーティング切替次第)
Global Tables(MRSC)リージョン障害同期複製・強整合0秒〜分(同上)
PITR / バックアップ論理破壊・誤削除・ランサム時点復元・スナップショット。新テーブルへ復元復元時点まで巻き戻る復元時間(分〜時間)

ここで設計者が混同しがちな2つの軸を、はっきり分けます。

  • Global Tables(アクティブ-アクティブ)が守るのは「インフラ障害」。 リージョンやAZが落ちても、別の生きたレプリカへ切り替えて事業を継続する。データはリアルタイムに同期されている
  • PITR/バックアップが守るのは「論理障害」。 バグや誤操作、ランサムウェアでデータそのものが壊れた/消えた場合に、健全だった時点へ巻き戻す。Global Tablesはこれを守れない——壊れた書き込みも、消した削除も、忠実に全レプリカへ複製してしまうからです。

この2つは代替関係ではなく、両方必要です。リージョン障害にはGlobal Tables、データ破壊にはPITR。DR設計でどちらか一方しか持たない構成は、片側のリスクに対して無防備です。

フェイルオーバーとリージョンルーティング

Global Tablesは「データの可用性」は保証しますが、「どのリージョンに繋ぐか」の判断はしてくれません。1章で見たとおりDynamoDBにグローバルエンドポイントはなく、アプリは自分のリージョンのローカルエンドポイントを叩きます。だからDRのRTOを決めるのは、実質的にアプリ/インフラ側のルーティング切替速度です。

典型的な構成は、フロントを Route 53(ヘルスチェック+フェイルオーバールーティング)や AWS Global Accelerator で複数リージョンのアプリスタックに分散し、リージョン障害を検知したらトラフィックを健全リージョンへ寄せる、というものです(公式の推奨リソースにも Route 53 / Global Accelerator / Application Recovery Controller が挙がっています)。アプリ側は、自分が今いるリージョンのDynamoDBエンドポイントだけを使うよう、リージョンを意識したクライアント生成にします。

import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";

/**
 * リージョン対応クライアント。
 * 原則:アプリは「自分が動いているリージョンのローカルエンドポイント」だけを叩く
 *       (公式:DynamoDBへの呼び出しはリージョンをまたぐべきではない)。
 * フェイルオーバーは Lambda/ECS を別リージョンで実行することで実現し、
 * クライアント側でリージョンを跨ぐリトライはしない(クロスリージョン呼び出しを避ける)。
 */
const HOME_REGION = process.env.AWS_REGION ?? "ap-northeast-1";

// SDK のリージョン解決は AWS_REGION に従うので、明示しておくと意図が明確になる
export const ddb = DynamoDBDocumentClient.from(
  new DynamoDBClient({ region: HOME_REGION }),
  { marshallOptions: { removeUndefinedValues: true } },
);

/**
 * 書き込みのリージョンアフィニティ(MRECでの競合回避):
 * 「あるエンティティの書き込みは、常に同じ"ホームリージョン"で行う」よう
 * 上位のルーティング層(Route 53 等)で寄せるのが定石。
 * これにより同一アイテムの同時マルチリージョン更新=LWW更新喪失を構造的に防ぐ。
 */
export function homeRegionFor(/* tenantId: string */): string {
  // 例:テナントIDのハッシュでホームリージョンを決め、書き込みを1リージョンに固定する。
  // 読み取りは任意のローカルリージョンから(低レイテンシ)。
  return HOME_REGION;
}

ポイントは、フェイルオーバーをSDKのリトライで実装しないことです。クロスリージョン呼び出しは公式が避けよと明言する遅延要因であり、リージョン障害時に別リージョンのエンドポイントを叩きにいくクライアントは、健全時にもレイテンシとコストを悪化させます。**「アプリスタックごと別リージョンで動かし、入口のルーティングで切り替える」**のが正しい層分けです。


5. PITRとオンデマンドバックアップの使い分け

論理障害に対する守りが、PITRとオンデマンドバックアップです。両者は役割が違います。

PITR(ポイントインタイムリカバリ)

Point-in-time recovery (PITR) backups are fully managed by DynamoDB and provide up to 35 days of recovery points at a per second granularity.

  • 最大35日の連続バックアップを、1秒単位の粒度で保持。RecoveryPeriodinDays1〜35日で短縮設定でき、短縮してもPITR料金は変わらない(料金はテーブル+LSIのサイズ基準)。
  • 有効化後は、「現在の5分前」から設定した保持期間までの任意時点へ復元できる。
  • 復元は必ず新しいテーブルへ行われる。元テーブルを上書きしない。
  • 性能・APIレイテンシに影響しない。
  • Global Tablesでは各レプリカで個別にPITRを有効化できる。復元するとグローバルテーブルから独立した単独テーブルになる(現行版2019.11.21なら、復元後のテーブルから新しいグローバルテーブルを作り直せる)。
  • クロスリージョン復元も可能(別リージョンに復元先テーブルを作れる)。

オンデマンドバックアップ

You can use the DynamoDB on-demand backup capability to create full backups of your tables for long-term retention, and archiving for regulatory compliance needs.

  • フルバックアップを任意のタイミングで取得。長期保持・規制対応のアーカイブ向け。
  • 本番テーブルの性能・可用性に影響しない。数MB〜数百TBまで対応。
  • すべて自動で暗号化・カタログ化される。明示的に削除するまで保持
  • AWS Backup と統合でき、AWS Backup経由ならバックアップをリージョン間で自動複製してさらにレジリエンスを高められる。

使い分け表

観点PITRオンデマンドバックアップ
種類連続バックアップ(時点復元)スナップショット
保持最大35日(1〜35で設定可)削除するまで無期限
粒度1秒単位の任意時点取得した瞬間のみ
主用途直近の誤操作・破壊からの巻き戻し長期保持・規制アーカイブ・節目の固定
復元先新テーブル(クロスリージョン可)新テーブル

公式のGlobal Tablesベストプラクティスは、現実的な指針を示しています。

Enabling automated backups and Point-in-Time Recovery (PITR) for one replica in a global table may be sufficient to meet your disaster recovery objectives.

グローバルテーブルの「1つのレプリカ」でPITR/バックアップを有効化すれば、DR目標を満たすのに十分なことが多い。全レプリカで重複して取る必要は通常ありません(PITR設定はレプリカ間で同期されない=個別管理なので、どこで取るかを明示的に決める)。私の実務では、直近の論理破壊にはPITR(短い保持で十分なテーブルは RecoveryPeriodinDays を絞る)、規制・監査用の固定点にはオンデマンドバックアップ+AWS Backup、という二段で設計しています。


6. コスト:複製書き込みユニットという考え方

Global Tablesのコストは、単一リージョンと「書き込みの数え方」が変わる点を理解すれば計算できます。読み取りやストレージの基礎はキャパシティ・コスト・性能設計ガイドに譲り、ここではマルチリージョン固有の差分だけを扱います。

公式の billing モデルです。単一リージョンテーブルにレプリカを足してグローバルテーブルにすると、書き込みの課金単位が変わります。

Replicated Write Request Units (rWRUs) for on-demand capacity mode, where one rWRU per replica table is charged for each write up to 1KB

  • 複製書き込みユニット(rWRU=オンデマンド/rWCU=プロビジョンド) で課金される。1KBごとの書き込みに対し、レプリカテーブル1つあたり1単位
  • 単価は単一リージョンの書き込みユニット(WRU/WCU)と同じ。安くなるわけでも高くなるわけでもなく、**「リージョンの数だけ課金される」**という構造。
  • rWRU/rWCUの課金は、レプリカを持つ全リージョンで発生する。
  • これに加えてクロスリージョンのデータ転送料が、リージョン間複製ぶんかかる。
  • ストレージはリージョンごとにかかる(各レプリカが全データを保持するため、実質ストレージ×レプリカ数)。
  • GSIの更新は通常のWRU/WCUで課金される(レプリカテーブル上のGSIでも、rではなく通常単位)。
  • 整合性モードによるrWRU/rWCU単価の差はない(MRECもMRSCも同じ)。MRSCのwitnessは、rWRU/rWCU・ストレージ・複製のデータ転送のいずれも課金されない

公式の課金例(書き込みのみ)

公式が挙げる例を読むと、コスト構造が一目で分かります。

  • Day 1(単一リージョン): us-west-2 に1KBアイテムを100件書く → 100 WRU
  • Day 2(レプリカ追加でグローバル化): us-east-2 にレプリカを追加。us-west-2 に150件書くと → us-west-2 に150 rWRU + us-east-2 に150 rWRU = 合計300 rWRU

**2リージョン構成にした瞬間、同じ150件の書き込みが「300書き込みユニット相当」**になる。これがGlobal Tablesの最大のコスト要因です。書き込みコストはおおむねレプリカのリージョン数に比例し、さらにクロスリージョン転送とリージョン×ストレージが乗ります。

ざっくりした見積もり指針:「3リージョンのグローバルテーブルにすると、書き込みコストは単一リージョンの約3倍+クロスリージョン転送+ストレージ×3」。読み取りは各リージョンのローカル読み取りなので低レイテンシだが、書き込み主体のワークロードほどマルチリージョン化のコスト増が効く

だからこそ、**「全テーブルを無条件にグローバル化しない」**のが鉄則です。リージョン障害で止められない・グローバルに低レイテンシが要る、と説明できるテーブルだけをGlobal Tablesにし、それ以外は単一リージョン+(必要なら)クロスリージョンPITR復元、という線引きがコスト効率に優れます。


7. 落とし穴:LWW更新喪失・冪等性・時計・一意性・複製ラグ

Global Tablesは強力ですが、分散の難しさが消えるわけではなく、AWSの層に移るだけです。設計者が引き受け続けるべき落とし穴を挙げます。

(1) MRECのlast-writer-wins=更新喪失(最重要)

2章のとおり、MRECでは同一アイテムへの同時マルチリージョン更新が後勝ちで片方を静かに消し、しかもCloudWatch/CloudTrailに記録されない。残高・在庫・カウンタのような読んで増減する値を複数リージョンから書くのは、MRECでは危険です。

対策は、公式の設計ガイドが推す**「書き込みのリージョンアフィニティ(home Region pinning)」です。あるエンティティの書き込みは、常に同じ1つのホームリージョンで行うようルーティング層で寄せる。読み取りは任意のローカルリージョンから(低レイテンシ)。こうすれば同一アイテムが2リージョンで同時に書かれる状況そのものが起きないため、LWWの出番がなくなります。「マルチアクティブだから全リージョンから何でも書ける」と素朴に運用しないこと——これがMREC運用の一丁目一番地です。グローバルに同一アイテムを強整合更新せざるを得ないなら、そこはMRSC**の出番です。

(2) 冪等性は依然としてアプリの責務

リージョン障害でのフェイルオーバー中は、リトライと再送が増えます。Global Tablesは冪等性を提供しませんattribute_not_exists による一度きりの作成や、冪等性キー+保存済みレスポンスといったパターンは、マルチリージョンでも変わらず必要です(冪等性パターンの詳細)。フェイルオーバーは冪等性が試される瞬間だと考えてください。

(3) トランザクションはリージョン内でのみ原子的(MREC)

これは見落としやすい重大仕様です。MRECでは、

Transactional writes are not replicated as a unit across Regions, meaning only some of the writes in a transaction may be returned by read operations in other replicas at a given point in time.

TransactWriteItems はそれを実行したリージョン内でのみ原子的で、ユニットとしてはリージョンをまたいで複製されません。あるリージョンでトランザクションした複数アイテムは、他リージョンでは部分適用の状態が一時的に観測されうる。「全リージョンでトランザクションが原子的」と誤解すると、別リージョンの読み取りで中途半端な状態を拾います。MRSCに至ってはトランザクション自体が非対応です。

(4) 時計・タイムスタンプ

MRECのLWWは内部タイムスタンプに基づきます。これはDynamoDBが管理する private system property で、アプリの updatedAt ではありません。とはいえ、アプリ側でバージョン番号や updatedAt を持って条件付き書き込み(楽観ロック)を併用すると、想定外の上書きを早期に検知できます。マルチリージョンでは「ローカルの時計を信用した分散ロジック」を書かないのが安全側です。

(5) グローバルでの一意性

DynamoDBの一意性保証はアイテム単位の条件付き書き込み(attribute_not_existsで成り立ちますが、MRECではこれがリージョンローカルに評価されます。2リージョンで「同じ新規キーを同時に作成」しようとすると、両方がローカルでは成功し、複製時にLWWで片方へ収束します(=一方の作成が実質失われる)。グローバルに厳密な一意性が必要なら、そのキーの作成を単一ホームリージョンに固定するか、MRSCを使います。「ユニークなはずのIDが複製後に1件になっていた」は、MREC+マルチリージョン書き込みの典型事故です。

(6) 複製ラグを前提に設計する

MRECは通常1秒以内に伝播しますが、SLAはなく、リージョン間距離やワークロードで変動します。ReplicationLatency メトリクス(リージョンペアごと)を監視し、増大したらトラフィックを別リージョンへ寄せる運用にします。アプリは「書いた直後に別リージョンで読んで最新を期待する」設計を避け、**書いたリージョンで読む(read-your-writes をローカルで満たす)**よう、読み書きのリージョンを揃えます。


8. Terraform:マルチリージョン・グローバルテーブル(MREC)

ここまでの設計判断を、IaCに落とします。aws_dynamodb_tablereplica ブロックでリージョンを追加すると、そのテーブルはグローバルテーブル(現行版2019.11.21)になります。PITRはレプリカごと、課金はオンデマンドにして「使った分だけ+リージョン数ぶん」を素直にします。

# プロバイダはリージョンごとに alias を分ける(クロスリージョン管理)
provider "aws" {
  alias  = "tokyo"
  region = "ap-northeast-1"
}

# グローバルテーブルの「定義元」リージョン。replica で他リージョンを足す。
# 公式ベストプラクティス:CloudFormation/Terraform では1つの基準リージョンに
# 全レプリカ定義を集約し、リージョン別スタックに分散させない(ドリフト回避)。
resource "aws_dynamodb_table" "app" {
  provider = aws.tokyo

  name         = "AppTable"
  billing_mode = "PAY_PER_REQUEST" # オンデマンド:rWRU で「使った分×リージョン数」課金
  hash_key     = "PK"
  range_key    = "SK"

  # マルチアクティブ複製に Streams が要る(NEW_AND_OLD_IMAGES が定石)
  stream_enabled   = true
  stream_view_type = "NEW_AND_OLD_IMAGES"

  attribute {
    name = "PK"
    type = "S"
  }
  attribute {
    name = "SK"
    type = "S"
  }

  # 大阪・オレゴンへレプリカを追加 → グローバルテーブル化(MREC)
  # PITR と削除保護はレプリカ間で同期されないので、各レプリカで明示する
  replica {
    region_name            = "ap-northeast-3" # 大阪:国内の地理冗長
    point_in_time_recovery = true
  }
  replica {
    region_name            = "us-west-2" # オレゴン:別大陸の地理冗長
    point_in_time_recovery = true
  }

  # 定義元リージョンの PITR
  point_in_time_recovery {
    enabled = true
  }

  # 本番テーブルの誤削除を止める(各レプリカで個別に有効化が必要)
  deletion_protection_enabled = true

  ttl {
    attribute_name = "expiresAt"
    enabled        = true # 注:TTL複製削除はレプリカ側で rWRU/書き込みを消費する
  }

  tags = {
    Environment = "production"
    DR          = "multi-region-mrec"
  }

  # レプリカのキャパシティはグローバルで同期されるため、
  # billing_mode やキー定義の変更は全レプリカに波及する点に注意。
  lifecycle {
    ignore_changes = [replica] # 手動でのレプリカ増減との競合を避けたい場合
  }
}

設計上の注意:MRSC は現状、replica ブロックの素朴な指定では表現できない制約(正確に3リージョン・リージョンセット限定・空テーブル・witness)を持ち、Terraform/コンソールでの扱いが MREC と異なります。MRSC を採用するなら、整合性モードと3リージョン構成の制約をプロビジョニング前に必ず確認してください(本記事のTerraformは MREC 構成です)。TTL の複製削除がレプリカ側で書き込みユニットを消費する点も、プロビジョンドなら容量見積もりに含めます。


FAQ

Q1. Global Tablesの整合性は強いですか、弱いですか? モード次第です。既定のMRECは結果整合で、変更は他リージョンへ非同期に通常1秒以内で伝播します(グローバルには強整合ではない)。MRSC(2025年6月導入)は強整合で、書き込みは成功前に他リージョンへ同期複製され、どのレプリカでも最新を返します。代わりにMRSCは書き込みレイテンシが上がり、3リージョン固定などの制約があります。

Q2. 競合(同時更新)はどう解決されますか? MRECはlast-writer-wins——内部タイムスタンプが新しい方が勝ち、負けた更新は静かに破棄され、CloudWatch/CloudTrailにも記録されません。これによる更新喪失を避けるには、書き込みを単一ホームリージョンに寄せる(リージョンアフィニティ)のが定石です。MRSCは後勝ちではなく、同時更新を ReplicatedWriteConflictException で明示的に失敗させ、リトライで解消します。

Q3. DRのRPO/RTOはどれくらいですか? MRECはRPOが複製遅延ぶん(通常数秒、ゼロではない)、RTOは秒〜分(実際はアプリのリージョンルーティング切替速度で決まる)。MRSCはRPOゼロ。さらに単一リージョンでも3AZ自動複製でAZ障害には透過的に耐えます。論理破壊(誤削除・バグ)に対するRPO/RTOは、Global TablesではなくPITR/バックアップの復元で決まります。

Q4. PITRは何日保持できますか?オンデマンドバックアップとの違いは? PITRは最大35日1秒単位の任意時点へ復元でき、保持は1〜35日で設定可能。現在の5分前から保持期間内まで戻せます。オンデマンドバックアップはスナップショットで、削除するまで無期限保持——長期保持・規制アーカイブ向け。どちらも復元は新テーブルに対して行われ、本番性能に影響しません。直近の事故にはPITR、節目の固定点にはバックアップ、と使い分けます。

Q5. コストは単一リージョンの何倍になりますか? 書き込みは複製書き込みユニット(rWRU/rWCU)で、レプリカのリージョン数ぶん課金されます。単価は単一リージョンと同じなので、3リージョンなら書き込みコストは概ね3倍+クロスリージョン転送料+ストレージ×リージョン数。読み取りは各リージョンのローカル読み取りです。整合性モードでrの単価は変わらず、MRSCのwitnessはrWRU・ストレージ・転送いずれも無課金です。書き込み主体のテーブルほど増分が大きいので、グローバル化は必要なテーブルだけに絞ります。

Q6. リージョン障害のフェイルオーバーは自動ですか? DynamoDBのデータ層は自動で全リージョンに同期されていますが、「どのリージョンに繋ぐか」の切り替えは自動ではありません。DynamoDBにグローバルエンドポイントはなく、アプリは自リージョンのローカルエンドポイントを叩きます。フェイルオーバーはアプリスタックを別リージョンでも動かし、Route 53 / Global Accelerator 等で入口を切り替えることで実現します。SDKのクロスリージョンリトライで実装しないのが鉄則です。

Q7. すべてのテーブルをGlobal Tablesにすべきですか? いいえ。書き込みがリージョン数ぶん課金され、ストレージもリージョン数ぶんかかるため、コストが構造的に増えます。「リージョン障害で止められない」「グローバルに低レイテンシが要る」と説明できるテーブルだけをグローバル化し、それ以外は単一リージョン+必要に応じたクロスリージョンPITR復元、という線引きがコスト効率に優れます。


おわりに:可用性は「設計」で買い、整合性は「理解」で守る

DynamoDBのマルチリージョン/DRは、アプリにレプリケーションを書くのではなく、Global Tablesという設計の選択で実現します。要点を凝縮します。

  • 可用性とグローバル性能はレプリケーション設計で買う:単一リージョンの3AZ自動複製(SLA 99.99%)の上に、Global Tablesでリージョン耐性(99.999%)を足す。
  • 整合性モデルを最初に決める:既定のMREC(結果整合・低レイテンシ・RPO数秒・LWW)か、MRSC(強整合・RPOゼロ・3リージョン固定・制約多数)。作成後に変更不可
  • インフラ障害はGlobal Tables、論理障害はPITR/バックアップ:両方必要。Global Tablesは壊れた書き込みも忠実に複製する。
  • フェイルオーバーはアプリ層の責務:ルーティング切替がRTOを決める。クロスリージョン呼び出しはしない。
  • MRECの更新喪失をリージョンアフィニティで封じる:同一アイテムの書き込みは単一ホームリージョンへ寄せる。グローバル強整合更新が要る箇所だけMRSC。
  • コストはリージォン数に比例:書き込みは複製ユニットでリージョン数ぶん、ストレージもリージョン数ぶん。グローバル化は必要なテーブルに絞る。

私は、一人 × 生成AI(Claude Code)という体制で、設計判断は人間の検証ゲートを通す進め方を徹底し、本番二重課金0件のサーバーレス決済基盤を実装・運用してきました。整合性モデルの選定、リージョンルーティングとフェイルオーバー、RTO/RPOに基づくPITR/バックアップ設計、複製コストの見積もりまで——DynamoDBのマルチリージョン/DR設計を、要件に合わせて一緒に詰めます。

マルチリージョン化・DR設計でお困りの方は、お問い合わせからご相談ください。 まずは守るべきRTO/RPOと、本当にグローバル化すべきテーブルの選別から、ご一緒します。

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・ 実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

この記事で解説した技術の適用事例

環境分野のサーバーレス決済プラットフォーム(フルスタック開発・決済信頼性レイヤーを主導)

ケーススタディを見る