I tried optimizing CloudFront VPC origin failover wait time from production logs
This page has been translated by machine translation. View original
Introduction
In the CloudFront VPC origin incident that occurred on July 16, 2026, a timeout wait of approximately 30 seconds occurred before origin failover was triggered, during which no response was returned to users.
This article analyzes response time distributions from CloudFront Standard Logging v2 in a production environment to derive timeout settings that reduce failover wait times. Additionally, we verify failover behavior during connection failures and response delays in a test environment, and examine how failover is recorded in Standard Logging v2 and Real-time Logs.
As a result, we derived settings that failover in approximately 10 seconds during response delays and approximately 2 seconds during connection failures, and confirmed expected behavior in the test environment.
Verification Details
Test Environment
We analyzed logs from the CloudFront distribution of dev.classmethod.jp. The origin is configured with a VPC Origin in ap-northeast-1 (Internal ALB → Lambda). Logs use Standard Logging v2, and the fields used for analysis are time-to-first-byte, origin-fbl, x-edge-result-type, sc-status, and time-taken.
A separate environment with the same configuration as production was built for timeout behavior verification.
| Component | Configuration | Region |
|---|---|---|
| CloudFront | Failover configuration using Origin Group | - |
| Primary origin | VPC Origin → Internal ALB → Lambda | ap-northeast-1 |
| Failover destination | S3 bucket | us-east-1 |
| Real-time Logs destination | Kinesis Data Streams | us-east-1 |
Deriving Appropriate Values from Production Logs
We analyzed 33,670 records spanning 3 hours from 2026-07-21 00:00 to 03:00 UTC from Standard Logging v2. The target is origin requests with x-edge-result-type = Miss and HTML pages (SSR responses).
We limited the scope to Miss and HTML pages because timeout settings only affect requests to the origin. Static resources are served from cache and rarely reach the origin, so they were excluded. The majority of Misses are SSR pages, which represent the group with the largest response times.
We aggregated time_to_first_byte - origin-fbl as a measure of overhead including connection establishment from edge locations to the VPC origin.
| Edge | 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 |
The p99 is at most 0.217 seconds, providing sufficient margin even with ConnectionTimeout set to 1 second. Since VPC origins connect via the AWS backbone, even geographically distant edges such as GRU (São Paulo) and LHR (London) showed stable p99 values below 0.024 seconds.
We aggregated origin-fbl, the time until the origin returns the first byte. This serves as the basis for OriginReadTimeout.
| Metric | p50 | p90 | p95 | p99 | p99.9 | max |
|---|---|---|---|---|---|---|
| origin-fbl | 0.172s | 0.584s | 0.668s | 1.062s | 1.538s | 3.241s |
The maximum value of fetchWithTimeout on the application side is 5 seconds. Since origin-fbl was 1.538 seconds even at p99.9 and 3.241 seconds at the observed maximum, we set OriginReadTimeout to 5 seconds.
The derived configuration values are as follows.
| Parameter | Value | Basis |
|---|---|---|
| ConnectionTimeout | 1s | Connection overhead p99 ≦ 0.22s across all edges |
| ConnectionAttempts | 2 | Safety measure to avoid failover on a single accidental timeout |
| OriginReadTimeout | 5s | App-side fetchWithTimeout max = 5s, origin-fbl p99.9 = 1.538s with sufficient margin |
Failover wait time during response delays: OriginReadTimeout 5s × ConnectionAttempts 2 = 10 seconds. During connection failures: ConnectionTimeout 1s × ConnectionAttempts 2 = 2 seconds.
Demonstrating Timeout Behavior
In the test environment, we intentionally configured the failover destination S3 with AccessDenied, so when failover is triggered, a 403 is returned.
We removed the inbound rule from the ALB Security Group to make TCP connections impossible and verified ConnectionTimeout=5 behavior (set to 5 seconds in testing to make behavior easier to observe).
| CA | Expected | Actual | sc-status |
|---|---|---|---|
| 1 | 5s | 5.54s | 403 |
| 2 | 10s | 10.52s | 403 |
| 3 | 15s | 15.52s | 403 |
We delayed Lambda responses by 10 seconds and verified OriginReadTimeout=5 behavior.
| CA | Expected | Actual | sc-status |
|---|---|---|---|
| 1 | 5s | 5.55s | 403 |
| 2 | 10s | 10.56s | 403 |
| 3 | 15s | 15.55s | 403 |
In both verifications, the time to failover matched the Timeout × ConnectionAttempts formula in the official documentation. The actual measured values include approximately 0.5 seconds of overhead due to the round trip between the measurement client and the edge.
We verified the boundary between normal responses and failover using the derived configuration values. We expected that delays under 5 seconds would result in normal responses, and delays over 5 seconds would trigger failover after two attempts in approximately 10 seconds.
| delay | Expected | Actual | sc-status | Notes |
|---|---|---|---|---|
| 0s | Normal | 0.09s | 200 | VPC Origin Response |
| 2s | Normal | 2.09s | 200 | VPC Origin Response |
| 4s | Normal | 4.07s | 200 | VPC Origin Response |
| 6s | failover | 10.51s | 403 | S3 failover (AccessDenied) |
Responses under 5 seconds were returned normally from the VPC origin, and responses exceeding 5 seconds triggered failover after two attempts in approximately 10 seconds.
Logging Strategy: Detecting Failover Activation
Detection with Standard Logging v2 (Adopted)
In the previous article, origin-fbl, origin-lbl, and timestamp(ms) were already added to the configuration. Extraction of failover candidates and classification by type are as follows.
- Primary extraction:
time-taken≧ 2 seconds andsc-statusis 4xx/5xx - Connection failure candidates:
time-takenaround 2 seconds - Response delay candidates:
time-takenaround 10 seconds
Since origin-fbl for normal requests is approximately 1.5 seconds even at p99.9, and time-taken for HTML pages tends to be close to this, requests with time-taken ≧ 2 seconds and sc-status of 4xx/5xx can be extracted as failover candidates. Note that this condition alone cannot detect failovers in configurations where the failover destination returns 200 normally.
Detection with Real-time Logs (Reference)
We used Real-time Logs to confirm r-host (the origin that actually responded) and sr-reason (the failover reason), which are not available in Standard Logging v2.
| Field | Normal | During Failover |
|---|---|---|
| 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 |
During failover, Failover:504 was recorded in sr-reason, and r-host had switched from the primary origin (ALB) to the failover destination (S3).
While Standard Logging v2 is limited to extracting failover candidates, Real-time Logs allow confirmation of the responding origin and failover reason on the CloudFront side via r-host and sr-reason.
Summary
By determining timeout values based on actual production log data, we were able to derive settings that reduce failover wait time during response delays from the previous approximately 30 seconds to approximately 10 seconds, and trigger failover in approximately 2 seconds during connection failures. The verifications in this article also confirmed that timeout-triggered failovers due to connection failures and response delays activate as configured.
On the other hand, failover during response delays still involves a wait of approximately 10 seconds. While this is a significant reduction from the previous approximately 30 seconds, it is still long compared to a response within a few seconds as a guideline for LCP, and the impact on user experience remains. In cases like the July 16, 2026 incident, where routing around the issue for hours until full recovery is necessary, we would also like to consider approaches such as temporarily treating the failover destination as the primary system or swapping primary and secondary to reach a healthy origin with shorter wait times.


