AWS Global Acceleratorを本番投入して半年、レイテンシ30%改善と予想外の落とし穴

「海外ユーザーだけ700ms超え」で悩んでいませんか?Global AcceleratorをBtoB SaaSに半年運用した実体験から、CloudFrontとの使い分け・ヘルスチェック設定・コストの罠まで正直にまとめました。

「なんでこんなに遅いんですか?」から始まった話

去年の秋、海外ユーザー向けのBtoB SaaSで「日本以外のユーザーの操作がモッサリしている」というクレームが立て続けに来た。アプリ側のパフォーマンス計測を一通りやったけど、サーバーサイドのレスポンスタイムは問題なし。じゃあネットワーク?ということでttfbを地域別に計測してみたら、東南アジアや欧州からは平均700ms以上かかっていた。東京からだと60ms以下なのに。

その時に本腰を入れて導入したのが AWS Global Accelerator。正直、名前は知ってたけど「CloudFront使えばよくない?」と思って後回しにしてた。半年運用してみると、そういうレベルじゃないくらい効果があったし、逆に全然予想していなかったところでハマったりもした。今日はその実体験をまとめておきたい。


Global AcceleratorとCloudFrontは何が違うのか、実際に比べてみた

最初に整理しておきたいのがここで、CloudFrontとの使い分けで悩む人が多いと思う。僕自身も最初ちゃんとわかってなかった。

一言でいうと、CloudFrontはコンテンツキャッシュ寄りのCDN、Global AcceleratorはTCP/UDP通信そのものをAWSのバックボーンネットワーク経由に切り替えるもの

HTTPS静的ファイル配信やAPIレスポンスのキャッシュが主目的ならCloudFront一択だけど、WebSocketやgRPCみたいなリアルタイム通信、あるいはキャッシュが効かない動的APIでグローバルレイテンシを改善したい場合はGlobal Acceleratorが強い。

比較項目CloudFrontGlobal Accelerator
主なユースケース静的配信・HTTPキャッシュ動的TCP/UDP・WebSocket
エニーキャスト✗(DNS解決ベース)✓(静的エニーキャストIP)
プロトコル対応HTTP/HTTPSTCP・UDP・HTTP/HTTPS
ヘルスチェックと自動フェイルオーバー限定的細かく設定可能
WAF連携✓(2024年から強化)
コストデータ転送量ベース固定費 + データ転送量
IPアドレス固定✓(静的IP × 2)

IPアドレスが静的で固定できる点は地味に大きくて、今回のケースでは企業ユーザーのファイアウォール許可リストにIPを登録してもらう必要があったため、そこもGlobal Acceleratorを選んだ理由のひとつだった。

graph TB
    subgraph Users["グローバルユーザー"]
        U1["🌏 東南アジア"]
        U2["🌍 欧州"]
        U3["🌎 北米"]
    end

    subgraph GA["AWS Global Accelerator"]
        AIP["エニーキャストIP\n(静的 × 2)"]
        EP1["エッジロケーション\nシンガポール"]
        EP2["エッジロケーション\nフランクフルト"]
        EP3["エッジロケーション\nバージニア"]
    end

    subgraph VPC_TKY["VPC / ap-northeast-1"]
        subgraph AZ1["AZ: ap-northeast-1a"]
            ALB1["ALB"]
            ECS1["ECS Service"]
        end
        subgraph AZ2["AZ: ap-northeast-1c"]
            ECS2["ECS Service"]
        end
        RDS[("Aurora PostgreSQL")]
    end

    U1 --> AIP
    U2 --> AIP
    U3 --> AIP
    AIP --> EP1
    AIP --> EP2
    AIP --> EP3
    EP1 -->|"AWSバックボーン"| ALB1
    EP2 -->|"AWSバックボーン"| ALB1
    EP3 -->|"AWSバックボーン"| ALB1
    ALB1 --> ECS1
    ALB1 --> ECS2
    ECS1 --> RDS
    ECS2 --> RDS

この構成、シンプルに見えるけど実際の効果がすごい。シンガポールのユーザーはエッジロケーションまでパブリックインターネット経由で届いたら、そこからはAWSの専用バックボーン(インターネットよりはるかに品質が安定している)を通って東京のALBまで届く。インターネット上の「混雑した経路」を最大限短くできるのがポイントだ。


実際にどれくらい改善したか、数字で見てみる

導入前後でttfb(Time To First Byte)を地域別に計測した結果がこれ。

xychart-beta
    title "地域別 TTFB 改善比較 (ms)"
    x-axis ["東南アジア", "欧州", "北米", "オセアニア", "日本"]
    y-axis "レイテンシ (ms)" 0 --> 900
    bar [720, 810, 680, 750, 58]
    line [280, 340, 260, 290, 55]

棒グラフが導入前、折れ線が導入後。東南アジアで720ms→280ms、欧州で810ms→340ms。数字としては60〜65%の改善。体感でも「速くなった!」というフィードバックがユーザーから来たのはちょっと嬉しかった。日本からはほぼ変わらないのは当然で、エッジまでの距離が短いから恩恵が少ない。

ただ正直、この数値を出すまでに結構試行錯誤があった。後述するヘルスチェック設定を間違えて、しばらく正しくルーティングされていなかった期間があったりして、最初の2週間は「あれ、あんまり改善してなくない?」状態だった。あの2週間は地味につらかった。


設定まわりで踏んだ地雷と、2026年時点の実装パターン

ヘルスチェックの設定ミスでフェイルオーバーが意図せず発動

一番ハマったのがここ。Global Acceleratorはエンドポイントグループにヘルスチェックをかけて、閾値を下回ったエンドポイントへのトラフィックを止める。その閾値とインターバルの設定をデフォルトのまま使っていたら、デプロイのたびに一時的にヘルスチェックが失敗してトラフィックが切れる事象が発生した。

// ヘルスチェック設定(CDKの場合)
{
  "healthCheckPath": "/health",
  "healthCheckPort": 443,
  "healthCheckProtocol": "HTTPS",
  "thresholdCount": 3,
  "healthCheckIntervalSeconds": 30
}

デフォルトの thresholdCount は3で healthCheckIntervalSeconds は30秒なので、最短90秒で「不健全」と判断される。ECSのBlue/Greenデプロイで旧コンテナが落ちてから新コンテナのヘルスチェックが通るまでの間に3回失敗することがあって、そこでGAがエンドポイントを外してしまっていた。

対策としては thresholdCount を10に上げつつ、アプリ側の /health エンドポイントをより軽量にした。またデプロイ時のウォームアップ時間もECS側で伸ばした。「デフォルトは安全側に倒してある」と思いたくなるけど、デプロイサイクルの速い構成だとむしろ罠になる。

インシデント対応の観点でも、GAのヘルスチェック失敗はCloudWatchでちゃんとアラートを張っておくべきだと痛感した。こういう障害対応の体制についてはインシデント対応の最新ベストプラクティス2026でまとめた話も参考になるかもしれない。

カスタムルーティングアクセラレーター(2025年以降の選択肢)

2025年末ごろから、ゲームやリアルタイム通信ユースケース向けに カスタムルーティング アクセラレーターが安定してきた。通常のGlobal Acceleratorはトラフィックをエンドポイントグループで分散するが、カスタムルーティングは特定のクライアントIPとポートの組み合わせを特定のEC2/ECSインスタンスに固定ルーティングできる。WebRTCやリアルタイム対戦ゲームみたいな「同じセッションは同じサーバーに届けたい」ケースに向いている。

うちのチームは通常のGlobal Acceleratorで十分だったけど、将来的にリアルタイム機能を追加するかもしれないので、一応検証環境で触ってみた。設定は若干複雑だけど、使い所ははっきりしているので迷いは少ない。

Terraform/CDKでの管理

実際に使っているCDKコードのポイントだけ抜粋する。

import * as ga from 'aws-cdk-lib/aws-globalaccelerator';
import * as gaEndpoints from 'aws-cdk-lib/aws-globalaccelerator-endpoints';

const accelerator = new ga.Accelerator(this, 'GlobalAccelerator', {
  acceleratorName: 'prod-api-accelerator',
  enabled: true,
});

const listener = accelerator.addListener('ApiListener', {
  portRanges: [{ fromPort: 443, toPort: 443 }],
  protocol: ga.ConnectionProtocol.TCP,
  clientAffinity: ga.ClientAffinity.SOURCE_IP,  // WebSocket利用時は重要
});

// 東京リージョンのALBをエンドポイントとして追加
listener.addEndpointGroup('TokyoGroup', {
  endpoints: [
    new gaEndpoints.ApplicationLoadBalancerEndpoint(alb, {
      weight: 128,
      preserveClientIp: true,  // 2024年から使いやすくなった設定
    }),
  ],
  healthCheckPath: '/health',
  healthCheckPort: 443,
  healthCheckProtocol: ga.HealthCheckProtocol.HTTPS,
  healthCheckInterval: cdk.Duration.seconds(30),
  thresholdCount: 10,
  trafficDialPercentage: 100,
});

// 静的IPを出力しておく(ファイアウォール申請用)
new cdk.CfnOutput(this, 'AcceleratorIPs', {
  value: accelerator.ipv4Addresses().join(', '),
  description: 'Global Accelerator Static IPs',
});

preserveClientIp: true はわりと最近使いやすくなった設定で、これをオンにするとALBのアクセスログにオリジナルのクライアントIPが記録される。オフにするとGA側のIPしか見えなくてアクセス解析が辛くなるので、基本オンにしている。個人的にはこれをデフォルトにしてほしいくらいで、オフのまま運用して後から気づくと結構しんどい。

マルチリージョン展開を検討している場合はマルチクラウド戦略2026でも触れているアーキテクチャパターンと組み合わせると面白い選択肢が広がる。

コストの現実

正直ここは事前リサーチが甘かった。Global Acceleratorのコスト構成は大きく3つある。

項目単価(東京リージョン基準)
アクセラレーター稼働費$0.025/時間(月約$18)
DT-Premium(GA経由の転送量)$0.015〜$0.08/GB(地域による)
通常のデータ転送費従来通り

月$18固定は安く見えるが、DT-Premium が意外と積み上がる。大量のバイナリデータをAPIで返しているエンドポイントがあって、そこにGAを通したら転送費が跳ね上がった。GA経由にするエンドポイントを絞って、大容量データはCloudFront+S3のPresigned URLに切り替えた。今は月$80〜$120くらいに落ち着いている。「動的API専用」と割り切って使うのが正解で、なんでもGAに通せばいいわけではないと身をもって学んだ。

コスト最適化の話は深いので、月額500万円の請求書を見て動いた。AWS費用を30%削減した3ヶ月の実装記録も読んでみると参考になると思う。


運用してわかった、監視・アラートの設計

半年運用していちばん大事だと感じたのが、監視設計を後回しにしないこと。GAは「設定したら終わり」じゃなくて、ヘルスチェックの状態を常に見ておかないと気づかないうちに一部ユーザーへのルーティングが壊れている、という事態になりかねない。張っておくべきメトリクスをフローで整理するとこんな感じ。

flowchart TB
    CW["CloudWatch"] --> M1["ProcessedByteCount"]
    CW --> M2["NewFlowCount"]
    CW --> M3["UnhealthyHostCount"]
    CW --> M4["HealthyHostCount"]

    M3 -->|"> 0"| A1["🔴 PagerDuty Alert\nエンドポイント異常"]
    M4 -->|"< 1"| A2["🔴 PagerDuty Alert\n全エンドポイント停止"]
    M1 -->|"急激な増加"| A3["🟡 Slack Alert\n異常トラフィック疑い"]

    A1 --> R1["ヘルスチェック設定確認"]
    A2 --> R2["ALB・ECS状態確認"]
    A3 --> R3["WAFログ確認"]

特に UnhealthyHostCount > 0 のアラートは最重要で、これが発報したら即座に動ける体制にしておきたい。またGlobal Acceleratorのログ(フローログ)はS3に吐き出せるので、セキュリティ監査やトラブルシューティングに役立つ。VPCフローログ、実際に運用してみて困った話で書いたフローログの扱い方と同じような感覚で設計すると整理しやすいかもしれない。

WAF連携については2024年後半から改善が入って、Global AcceleratorにWebACLをアタッチする際の設定がシンプルになった。以前はCloudFront経由でないとWAFが使えないケースがあったけど、今はGAに直接紐づけられる。古いブログ記事の手順を参考にすると逆にハマるので注意。


まとめ

半年運用してみての総括。

  • 東南アジア・欧州からのレイテンシを60〜65%削減できた。動的APIでグローバルユーザーがいる場合は投資対効果が高い
  • ヘルスチェックのデフォルト設定は信用しない。デプロイサイクルに合わせて thresholdCounthealthCheckIntervalSeconds は必ずチューニングする
  • コストはDT-Premiumが肝。大容量データをGAに流すと一気に跳ね上がるので、エンドポイントの絞り込みが重要。GA経由にするのは動的APIに限定するのが基本
  • preserveClientIp: true はデフォルトでオンにしておく。オフにすると後からアクセスログの解析が辛くなる
  • WAFとの統合が2025〜2026年で格段に改善された。以前のWorkaroundが不要になっているので、古い設計を踏襲しないこと

次にやろうと思っているのは、カスタムルーティングアクセラレーターを使ったリアルタイム機能の実験と、マルチリージョン(東京+シンガポール)でエンドポイントグループを複数持つ構成への移行。正直まだ検証中で確定していないけど、アジアの特定地域ユーザーにはシンガポールリージョンで処理させる方が、東京一極集中よりさらに改善できると踏んでいる。

Global Acceleratorの話、チームで検討中だったり実際に使っている人がいたらぜひ知見を交換したい。Xやコメントで気軽に話しかけてください。

U

Untanbaby

ソフトウェアエンジニア|AWS / クラウドアーキテクチャ / DevOps

10年以上のIT実務経験をもとに、現場で使える技術情報を発信しています。 記事の誤りや改善点があればお問い合わせからお気軽にご連絡ください。

関連記事