CloudFront VPCオリジンのフェイルオーバー待機時間を本番ログから最適化してみた
はじめに
2026年7月16日に発生したCloudFront VPCオリジンの障害では、オリジンフェイルオーバーが発動するまでに約30秒のタイムアウト待機が発生し、その間ユーザーにはレスポンスが返りませんでした。
本記事では、本番環境のCloudFront Standard Logging v2からレスポンスタイム分布を分析し、フェイルオーバー待機時間を短縮するタイムアウト設定を導出します。あわせて、検証環境で接続失敗時と応答遅延時のフェイルオーバー動作を確認し、Standard Logging v2およびReal-time Logsでフェイルオーバーがどのように記録されるかも見ていきます。
結果として、応答遅延時は約10秒、接続失敗時は約2秒でフェイルオーバーする設定を導出し、検証環境で期待どおりの動作を確認できました。
検証内容
検証環境
dev.classmethod.jpのCloudFrontディストリビューションのログを分析対象としました。オリジンはap-northeast-1のVPC Origin(Internal ALB → Lambda)で構成されています。ログはStandard Logging v2で、分析に使用したフィールドはtime-to-first-byte、origin-fbl、x-edge-result-type、sc-status、time-takenです。
タイムアウト動作の検証用に、本番と同じ構成の別環境を構築しました。
| コンポーネント | 構成 | リージョン |
|---|---|---|
| CloudFront | Origin Groupによるフェイルオーバー構成 | - |
| プライマリオリジン | VPC Origin → Internal ALB → Lambda | ap-northeast-1 |
| フェイルオーバー先 | S3バケット | us-east-1 |
| Real-time Logs配信先 | Kinesis Data Streams | us-east-1 |
本番ログからの適正値導出
Standard Logging v2から2026-07-21 00:00〜03:00 UTCの3時間分、33,670レコードを分析しました。対象はx-edge-result-type = MissかつHTMLページ(SSRレスポンス)のオリジンリクエストです。
対象をMissかつHTMLページに限定したのは、タイムアウト設定はオリジンへのリクエストにのみ影響するためです。静的リソースはキャッシュから配信され、オリジンへの到達自体が少ないため対象外としました。Missの大半はSSRページであり、レスポンスタイムが最も大きいリクエスト群です。
time_to_first_byte - origin-fbl を、エッジロケーションからVPCオリジンへの接続確立を含むオーバーヘッドの目安として集計しました。
| エッジ | count | p50 (s) | p90 (s) | p99 (s) | max (s) |
|---|---|---|---|---|---|
| NRT | 10,202 | 0.009 | 0.011 | 0.207 | 0.231 |
| ATL | 4,960 | 0.022 | 0.025 | 0.053 | 0.397 |
| IAD | 4,362 | 0.012 | 0.017 | 0.061 | 0.215 |
| SIN | 2,779 | 0.010 | 0.012 | 0.020 | 0.212 |
| KIX | 2,317 | 0.015 | 0.030 | 0.217 | 0.317 |
| DFW | 2,163 | 0.030 | 0.033 | 0.080 | 0.147 |
| FRA | 193 | 0.009 | 0.015 | 0.214 | 0.217 |
| HEL | 186 | 0.031 | 0.035 | 0.080 | 0.082 |
| GRU | 145 | 0.013 | 0.018 | 0.024 | 0.029 |
| LHR | 109 | 0.010 | 0.012 | 0.017 | 0.018 |
p99は最大でも0.217秒であり、ConnectionTimeoutを1秒にしても十分な余裕があります。VPCオリジンはAWSバックボーン経由で接続するため、GRU(サンパウロ)やLHR(ロンドン)など地理的に離れたエッジでもp99は0.024秒以下で安定していました。
オリジンが最初のバイトを返すまでの時間であるorigin-fblを集計しました。これはOriginReadTimeoutの根拠とします。
| 指標 | p50 | p90 | p95 | p99 | p99.9 | max |
|---|---|---|---|---|---|---|
| origin-fbl | 0.172s | 0.584s | 0.668s | 1.062s | 1.538s | 3.241s |
アプリケーション側のfetchWithTimeoutの最大値は5秒です。origin-fblはp99.9でも1.538秒、観測最大値でも3.241秒だったため、OriginReadTimeoutは5秒としました。
導出した設定値は次のとおりです。
| パラメータ | 設定値 | 根拠 |
|---|---|---|
| ConnectionTimeout | 1s | 全エッジの接続オーバーヘッド p99 ≦ 0.22s |
| ConnectionAttempts | 2 | 1回の偶発タイムアウトでフェイルオーバーしない安全策 |
| OriginReadTimeout | 5s | アプリ側 fetchWithTimeout の最大値=5s、origin-fbl の p99.9=1.538s で十分マージンあり |
応答遅延時のフェイルオーバー待機時間: OriginReadTimeout 5s × ConnectionAttempts 2 = 10秒。接続失敗時は ConnectionTimeout 1s × ConnectionAttempts 2 = 2秒です。
タイムアウト動作の実証
検証環境ではフェイルオーバー先に意図的にAccessDenied設定のS3を使っているため、フェイルオーバー発動時は403が返ります。
ALBのSecurity Groupからインバウンドルールを削除し、TCP接続不可の状態でConnectionTimeout=5の動作を確認しました(挙動を観察しやすくするため検証では5秒に設定)。
| CA | 理論値 | 実測値 | sc-status |
|---|---|---|---|
| 1 | 5s | 5.54s | 403 |
| 2 | 10s | 10.52s | 403 |
| 3 | 15s | 15.52s | 403 |
Lambdaの応答を10秒遅延させ、OriginReadTimeout=5の動作を確認しました。
| CA | 理論値 | 実測値 | sc-status |
|---|---|---|---|
| 1 | 5s | 5.55s | 403 |
| 2 | 10s | 10.56s | 403 |
| 3 | 15s | 15.55s | 403 |
どちらの検証でも、フェイルオーバーまでの時間は公式ドキュメントにあるTimeout × ConnectionAttemptsと一致しました。実測値には計測クライアント〜エッジ間の往復が含まれるため約0.5秒のオーバーヘッドがあります。
導出した設定値で正常応答とフェイルオーバーの境界を確認しました。5秒未満なら正常応答、5秒超なら2回の試行を経て約10秒でフェイルオーバーすることを期待します。
| delay | 期待 | 実測値 | sc-status | 備考 |
|---|---|---|---|---|
| 0s | 正常 | 0.09s | 200 | VPC Origin Response |
| 2s | 正常 | 2.09s | 200 | VPC Origin Response |
| 4s | 正常 | 4.07s | 200 | VPC Origin Response |
| 6s | failover | 10.51s | 403 | S3 failover(AccessDenied) |
5秒未満の応答はVPCオリジンから正常に返り、5秒を超える応答では2回の試行後、約10秒でフェイルオーバーしました。
ログ戦略: フェイルオーバー発動の検知
Standard Logging v2 での検知(採用)
前回記事でorigin-fbl、origin-lbl、timestamp(ms)を追加設定済みです。フェイルオーバー候補の抽出と種別分類は以下のとおりです。
- 一次抽出:
time-taken≧ 2秒 かつsc-statusが4xx/5xx - 接続失敗候補:
time-takenが2秒前後 - 応答遅延候補:
time-takenが10秒前後
正常リクエストのorigin-fblはp99.9でも1.5秒程度であり、HTMLページではtime-takenもこれに近い傾向のため、time-taken ≧ 2秒かつsc-statusが4xx/5xxのリクエストをフェイルオーバー候補として抽出できます。フェイルオーバー先が正常に200を返す構成では、この条件だけでは検出できない点に注意してください。
Real-time Logs での検知(参考)
Standard Logging v2では取得できないr-host(実際に応答したオリジン)とsr-reason(フェイルオーバー理由)を、Real-time Logsで確認しました。
| フィールド | 正常時 | フェイルオーバー時 |
|---|---|---|
| sc-status | 200 | 403 |
| time-taken | 0.048s | 10.495s |
| x-edge-result-type | Miss | Error |
| r-host | internal-cf-vpc-origin-timeout-test-alb-xxxxxxxxx.ap-northeast-1.elb.amazonaws.com | cf-vpc-origin-timeout-test-failover-123456789012.s3.us-east-1.amazonaws.com |
| sr-reason | - | Failover:504 |
フェイルオーバー時はsr-reasonにFailover:504が記録され、r-hostがプライマリオリジン(ALB)からフェイルオーバー先(S3)に切り替わっていました。
Standard Logging v2ではフェイルオーバー候補の抽出にとどまりますが、Real-time Logsではr-hostとsr-reasonにより、応答したオリジンとフェイルオーバー理由をCloudFront側で確認できます。
まとめ
本番ログの実態に基づいてタイムアウト値を決定することで、応答遅延時のフェイルオーバー待機時間を従来の約30秒から約10秒に短縮し、接続失敗時は約2秒でフェイルオーバーする設定を導出できました。本記事の検証でも、接続不能や応答遅延によるタイムアウト起因のフェイルオーバーが、設定値どおりに発動することを確認できました。
一方で、応答遅延時のフェイルオーバーでは約10秒の待機が発生します。従来の約30秒からは大幅に短縮できるものの、LCPの目安である数秒以内の応答と比べるとまだ長く、ユーザー体験への影響は残ります。2026年7月16日の障害のように、完全復旧まで数時間単位での迂回が必要になるケースでは、フェイルオーバー先を一時的に主系として扱う、プライマリとセカンダリを入れ替えるなど、より短い待機時間で健全なオリジンへ到達させることも検討したいと思います。







