マルチリージョン運用3年で実感した、Route 53では足りなかった3つの課題
グローバル展開で「Route 53があれば大丈夫」と思ってた僕たちが、直面した予想外の問題。失敗から学んだ実装パターンを図解で解説します。
マルチリージョン運用3年で知った、Route 53だけじゃ足りない理由
うちのチームがグローバル展開を始めたのは3年前。当時は「Route 53で DNS ラウンドロビンすれば大丈夫」と楽観的に考えてました。その甘さを本当に思い知らされました。
シンガポール拠点の立ち上げ直後、東京のユーザーから「なぜかシンガポール経由でアクセスされてる」というクレームが。Route 53 のジオロケーションルーティングを設定していたのに、トラフィックが最適でない地域にルーティングされていたんです。その時初めて気づきました。DNS ルーティングだけではマルチリージョンネットワーク設計は完成しないということを。
3年かけて何度も失敗しながら辿り着いた、2026年時点での実装パターンを共有します。
Route 53の限界と、実装して気づいたこと
Route 53 でできること・できないことを整理してみたんですが、正直に言うと DNS レベルの制御だけだと足りません。
Route 53 でできていることって、見た目より限定的なんですよ。
| 機能 | 説明 | 特徴 |
|---|---|---|
| ジオロケーションルーティング | 国・都道府県ベースで振り分け | 静的な地理情報のみ参照 |
| 加重ルーティング | トラフィック分散比を指定 | 固定比率 |
| フェイルオーバー | ヘルスチェック時に自動切り替え | バイナリ(動く/動かない) |
| レイテンシベースルーティング | ユーザーに最も近いリージョン優先 | リアルタイム情報なし |
一見すごそうですが、これらは静的な設定なんです。うちが直面した問題をざっくりいうと:
問題1:リアルタイムなトラフィック状況が反映されない
Route 53 のレイテンシベースルーティングは「どのリージョンが地理的に近いか」で判定するんですが、実際のネットワークって混雑状況で変わるんです。東京と大阪のように距離は近いけど、その時間帯に大阪経由の方が高速ってことが起きます。うちの場合、ゴールデンウィークに東京リージョンが混雑して、本来ならシンガポール経由の方が速いのに Route 53 は東京を優先していた。ユーザー体験は最悪でした。
問題2:NLB / ALB レベルのコネクション管理が独立している
Route 53 が「シンガポールにアクセスせよ」と指示しても、実際のコネクションが NLB でどう処理されるかは別の話なんです。3年前は「リージョン間でコネクション数が偏ってバックエンドが過負荷になる」という問題を何度も経験しました。
問題3:TLS ハンドシェイクのコスト
DNS が各リージョンに振り分けても、ユーザーは毎回 TLS ハンドシェイクを最初から始める必要があります。これって意外とレイテンシに効いてくるんですよ。特にモバイルでは。
AWS Global Accelerator を本気で検証した6ヶ月
問題に直面してから、我々が導入したのが AWS Global Accelerator です。1年前は「過剰機能では?」と思ってましたが、実装してみて本当に変わりました。
Global Accelerator の何が違うのか:
Route 53(DNS ベース)
ユーザー → DNS 問い合わせ → IP アドレス取得 → リージョンへ接続
(毎回、キャッシュ効かないと往復)
Global Accelerator(エニーキャスト + TCP/UDP)
ユーザー → 最寄りの AnyPoint(固定 IP) → AWS 高速バックボーン → リージョン
(ファイアウォール通しやすい、TLS 再開可能)
実装してみて体感できた変化:
- レイテンシが平均30%改善:単にリージョン選定がスマートになっただけじゃなく、AWS バックボーン経由で高速化したから
- モバイルユーザーで大幅改善:キャリアネットワークの不安定さを Global Accelerator が吸収している
- TLS セッション再開:同じ Global Accelerator の IP 経由なら既存セッション情報を活用できて、ハンドシェイクが省略される場合もある
ただ、導入してから気づいた落とし穴もあります。
Global Accelerator の意外な制約:
導入6ヶ月目で目が覚めたんですが、実は全能ではないんです。
-
リージョン間のコネクション管理は相変わらず統一されていない:Global Accelerator は「どのリージョンに送るか」を判定するだけで、その後のコネクションプールは各リージョンの NLB が独立管理。つまり東京リージョンに大量のコネクションが溜まって、シンガポール側は遊んでる、みたいなことが起きます。
-
コスト:月30万円近く。スケールしたサービスなら OK ですが、小〜中規模だと Route 53 + CloudFront + 自前の最適化の方が安いかもしれない。
-
キャッシュ戦略が複雑化:Global Accelerator が複数リージョンに振り分けると、キャッシュヒット率が下がるんです。うちは CloudFront をさらに前に置く結果になって、層が増えてデバッグが地獄になりました。
マルチリージョン設計で本当に重要な3つのレイヤー
3年の試行錯誤から気づいたんですが、マルチリージョンって実は3層構造で考えるべきなんです。
1. エッジ層:ユーザーに最も近い場所
CloudFront + Global Accelerator の組み合わせですね。
- 静的コンテンツ:CloudFront のエッジロケーション(200以上)でキャッシュしてレスポンス
- 動的コンテンツ&リアルタイム系:Global Accelerator の Anycast IP 経由で AWS バックボーン直結
うちが実装した構成:
ユーザー
↓
[CloudFront エッジロケーション]
├─ キャッシュ可能 → Cache キャッシュしてレスポンス
└─ 動的コンテンツ → Global Accelerator Anycast IP へ
↓
[AWS Global Accelerator]
↓
[各リージョンの NLB/ALB]
2. リージョン層:計算リソースの配置
ここが意外と複雑です。ECS・EKS・Lambda のどれを選ぶかで、マルチリージョン戦略が変わります。
ECS Fargate でやってた時代の失敗
各リージョンで独立した ECS クラスタを立てていたら、リージョン間のコネクションプール管理が破綻しました。東京にタスク 10 個、シンガポールに 5 個いるのに、DNS ラウンドロビンで振ると、東京のリソースが飽和する現象。
EKS に乗り換えてからの改善
EKS にして始めてカスタムコントローラーで「グローバルコネクションプール」を実装できたんです。
# イメージ:EKS のカスタムリソース
apiVersion: networking.mycompany.com/v1
kind: GlobalLoadBalancer
metadata:
name: api-global
spec:
regions:
- name: ap-northeast-1
target: tokyo-nlb
weight: 50 # コネクション数の目安
readiness: true
- name: ap-southeast-1
target: sg-nlb
weight: 30
readiness: true
- name: us-east-1
target: us-nlb
weight: 20
readiness: true
strategy: dynamic-weight-adjustment
healthCheckInterval: 5s
この構成で、実際のバックエンド負荷に基づいてリアルタイムに重みを調整できるようになりました。
3. データレプリケーション層:状態管理
ここがマルチリージョン設計で最も複雑で、ほぼ全ての企業が失敗してます。うちも例外ではありませんでした。
うちが学んだ教訓:
RDS Multi-AZ だけでは足りないってすぐに気づきました。クロスリージョンレプリケーションは RPO / RTO の要件で大きく変わります。
Aurora Global Database でやってた時代は、写入は東京だけで、読み取り専用レプリカが各リージョン。結構安定していました。でも、切り替わり時間が問題で、2年前のある障害で東京リージョン全体がダウンした時、RTO が 5 分かかった。その後は DynamoDB + Global Tables に乗り換えました。
DynamoDB Global Tables の何が良かったのか:
Aurora Global Database(読み取り専用レプリカ)
東京リージョン ─ 書き込み → レプリケーション → シンガポール ─ 読み取りのみ
DynamoDB Global Tables(全リージョン読み書き)
東京 ←→ シンガポール ←→ 米国
(最終的一貫性で自動同期)
DynamoDB にしてから、RTO がほぼ 0 に近くなりました。代わりに「最終的一貫性」の設計を強いられましたが、うちのユースケースでは OK でした。
2026年現在の、うちのマルチリージョン構成
実際に運用してる構成を図にしてみました。
graph TB
subgraph EdgeLayer ["Edge Layer: CloudFront + Global Accelerator"]
CF["CloudFront CDN<br/>200+ Locations"]
GA["AWS Global Accelerator<br/>Anycast IP"]
end
subgraph TokyoRegion ["Tokyo Region (ap-northeast-1)"]
TkyAZ1["AZ 1a"]
TkyAZ2["AZ 1c"]
subgraph TkyNetwork ["VPC: 10.0.0.0/16"]
TkyNLB["NLB<br/>Port 80, 443"]
TkyEKS["EKS Cluster<br/>8x t3.xlarge"]
TkyAurora["Aurora PostgreSQL<br/>Primary"]
end
TkyAZ1 --> TkyNLB
TkyAZ2 --> TkyNLB
TkyNLB --> TkyEKS
TkyEKS --> TkyAurora
end
subgraph SGRegion ["Singapore Region (ap-southeast-1)"]
SgAZ1["AZ 1a"]
SgAZ2["AZ 1b"]
subgraph SgNetwork ["VPC: 10.1.0.0/16"]
SgNLB["NLB<br/>Port 80, 443"]
SgEKS["EKS Cluster<br/>6x t3.large"]
SgDDB["DynamoDB<br/>Global Tables"]
end
SgAZ1 --> SgNLB
SgAZ2 --> SgNLB
SgNLB --> SgEKS
SgEKS --> SgDDB
end
subgraph USRegion ["US East Region (us-east-1)"]
UsAZ1["AZ 1a"]
UsAZ2["AZ 1b"]
subgraph UsNetwork ["VPC: 10.2.0.0/16"]
UsNLB["NLB<br/>Port 80, 443"]
UsEKS["EKS Cluster<br/>4x t3.medium"]
UsS3["S3 Replica<br/>Async"]
end
UsAZ1 --> UsNLB
UsAZ2 --> UsNLB
UsNLB --> UsEKS
UsEKS --> UsS3
end
subgraph CrossRegion ["Cross-Region"]
Transit["Transit Gateway<br/>for Inter-Region"]
AuroraSync["Aurora Replication<br/>Tokyo → Sg/Us<br/>Read-only"]
DDBSync["DynamoDB Global Tables<br/>Bi-directional Sync"]
end
User["User<br/>Global Access"]
User --> CF
User --> GA
CF --> TkyNLB
GA --> TkyNLB
GA --> SgNLB
GA --> UsNLB
TkyNLB --> Transit
SgNLB --> Transit
UsNLB --> Transit
TkyAurora --> AuroraSync
AuroraSync --> SgDDB
AuroraSync --> UsS3
TkyDDB["DynamoDB<br/>Global Tables"] -.-> DDBSync
SgDDB -.-> DDBSync
UsS3 -.-> DDBSync
style EdgeLayer fill:#ff9999
style TokyoRegion fill:#99ccff
style SGRegion fill:#99ff99
style USRegion fill:#ffcc99
style CrossRegion fill:#cc99ff
実装で痛感したコスト最適化のポイント
マルチリージョンはコストがエグいです。うちが3年で学んだ工夫を紹介しますね。
1. リージョン間通信をできるだけ減らす
Transit Gateway は便利ですが、データ転送料がかかります。月平均 200GB のクロスリージョン通信で月 18万円かかってました。正直、目を疑いましたね。
対策は こんな感じ:
- 可能な限りリージョンローカルで完結するようアプリ設計する
- DynamoDB Global Tables は「同期」が多くないユースケースのみ利用
- S3 は非同期レプリケーション + CloudFront キャッシュで対応
これで月8万円まで削減できました。
2. 全リージョンで同じスペックはいらない
東京(写入+読み取り)は大きく、シンガポール(読み取り+軽い計算)は中程度、米国(バックアップ + 非同期処理)は小さく。これって当たり前ですが、実装時には意外と見落とされます。
うちの構成:
- 東京:t3.xlarge × 8 ノード(EKS)
- シンガポール:t3.large × 6 ノード
- 米国:t3.medium × 4 ノード
Spot Instance Mix で月 30% 削減できてます。
3. Global Accelerator は「本当に必要か」検討する
Route 53 + CloudFront で十分な場合も多いんです。うちが Global Accelerator を導入した理由は「ライブストリーミング配信」と「リアルタイムチャット」で低レイテンシが必須だったから。他のサービスだったら不要かもしれません。
運用して分かった、本番環境のモニタリング戦略
マルチリージョンは複雑なので、層別で監視する必要があります。
① DNS 層
- Route 53 Health Checks
- ジオロケーション別レスポンスタイム
② グローバルエッジ層
- Global Accelerator Flow Logs
- 地域別・リージョン別のトラフィック分散率
- TLS ハンドシェイク成功率
③ リージョン層
- CloudWatch メトリクス(各リージョン EKS)
- CPU / メモリ使用率
- NLB コネクション数
- ポッド起動時間
④ クロスリージョン層
- Transit Gateway Flow Logs
- 帯域幅利用率
- パケット損失率
⑤ データレイヤー
- Aurora Global Database レプリケーション遅延
- DynamoDB Global Tables レプリケーション遅延
- S3 クロスリージョンレプリケーション遅延
僕たちはこれら全部を Datadog に集約してダッシュボード化してます。3年前は CloudWatch だけで監視してて、クロスリージョン障害に気づくのが遅かった教訓から。今では問題を早期発見できるようになりました。
まとめ
マルチリージョン設計は「Route 53 で振り分ければ OK」という簡単な話ではありません。3年の経験から気づいたポイント:
-
Route 53 は DNS ルーティングに過ぎない:本当の最適化には Global Accelerator、CloudFront、アプリケーション層での工夫が必要です。
-
リージョン間コネクション管理が複雑:独立した各リージョンのリソースをどう統合するかは、アーキテクチャの工夫次第。EKS にして初めて実装できました。
-
データレプリケーション戦略で大きく変わる:Aurora か DynamoDB か、同期か非同期か、要件でがらりと変わる。最適解は1つではありません。
-
コスト最適化は必須:やみくもにマルチリージョン化するとコストが爆発します。要件に合わせた「段階的」な展開を心がけるべき。
-
監視・アラートが重要:マルチリージョンは複雑なので、問題発生時に気づく仕組みが全てを決めます。
次は「マルチリージョン障害から 30 分で自動復旧する設計」をチームで実装しようとしてます。正直、まだ検証中だけど、早ければ Q1 に導入予定。またハマった話は別の記事で書きますね。