Origin failure is the single most visible CDN failure mode. When an edge cannot fetch from origin, even a 99.9% cache hit ratio collapses into user-facing 5xx errors. A robust origin failover strategy ensures the CDN can automatically reroute requests to a healthy origin without manual intervention, preserving availability and protecting your origin SLA.
This guide compares the two foundational patterns — active-passive and active-active — with architecture tradeoffs, health-check design, and production-ready configuration examples. Implemented correctly, either pattern can deliver 99.99%+ origin availability when combined with sound caching strategies and continuous performance metrics monitoring.
Why Origin Failover Is Non-Negotiable
A CDN decouples edge delivery from origin compute, but it does not eliminate origin dependency. Cache misses, revalidation, purge-and-refetch, and dynamic bypasses all require a successful origin fetch. A single origin in a single region creates a fate-sharing domain: a deployment error, AZ outage, or upstream provider incident becomes a global outage.
Modern origins fail in subtle ways. We see not only hard-down TCP failures, but gray failures: 5-second TTFB spikes, intermittent 502s from overloaded app servers, TLS handshake timeouts after certificate rotation, and saturated NAT gateways. Your failover logic must handle both binary and degraded states.
Key design goals for any failover pattern are:
- Recovery Time Objective (RTO): Time from first failed probe to traffic shifted. Target <30 seconds for active-passive, <5 seconds for active-active with passive detection.
- Recovery Point Objective (RPO): Data loss window for dynamic content. Irrelevant for immutable assets, critical for APIs.
- Blast radius containment: Failover should not cascade. A flapping origin should not cause thundering herd on the secondary.
- Observability: Every failover event must emit metrics, logs, and alerts. Silent failovers hide chronic origin instability.
Active-Passive Failover: Standby Redundancy
In active-passive, the CDN defines a primary origin that serves 100% of origin traffic under normal conditions. A secondary (passive) origin is configured but receives no traffic until the primary is marked unhealthy. This is the simplest high-availability pattern and the default in AWS CloudFront Origin Groups, Akamai Failover, and Fastly Origin Shield with failover.
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
How It Works
The edge maintains a health state machine per origin. Active health checks probe a lightweight endpoint such as /healthz or /cdn-health every 10-20 seconds. After N consecutive failures (typically 3), the primary is marked unhealthy and the edge atomically switches the origin pool to the secondary. When the primary recovers and passes M consecutive successes, traffic fails back — often with a hold-down timer to avoid flapping.
Passive detection complements active checks. If a client request results in a 500, 502, 503, 504, or timeout, the edge can retry idempotent GET/HEAD requests on the secondary immediately, without waiting for the next health probe. This dramatically reduces user-visible errors during brownouts.
Strengths and Limitations
Active-passive excels when the secondary is intentionally different: a cheaper object storage bucket, a static fallback, or a disaster-recovery region that is not provisioned for full load. You pay only for standby capacity. Failback is deterministic and debugging is straightforward because only one origin is live at a time.
The tradeoff is capacity risk. If the secondary has not been load-tested or is cold (autoscaling from zero, empty caches, cold JVMs), the failover itself can cause a secondary outage. You also incur a brief error window while health checks converge. For latency-sensitive workloads, that 20-30 second detection window may breach SLOs. Mitigate this by tuning aggressive passive retry and by keeping the passive origin warm with synthetic traffic or periodic shield fetches.
Use active-passive when: origins are not data-synchronized, workloads are read-heavy and cacheable, budget constraints favor standby over duplicated capacity, or compliance requires a clear primary region. Pair it with proper SSL/TLS configuration on both origins so certificate mismatches do not block failover.
Active-Active Failover: Concurrent Distribution
Active-active treats all origins as equal members of a pool. The CDN load-balances requests across healthy origins on every request, using round-robin, weighted, latency-based, or consistent-hash routing. If one origin fails, it is ejected from the pool and remaining origins absorb its share. There is no concept of primary.
Load Balancing and Health Ejection
Unlike active-passive, active-active requires a load-balancing decision on each cache miss. Most CDNs support weighted origins (e.g., 70/30 split during migration), geographic steering (route EU users to eu-origin, US to us-origin), and consistent hashing for cache efficiency. Health ejection is per-edge or per-shield POP: an origin marked unhealthy in Ashburn may still be healthy in Singapore, preventing global ejection due to localized network issues.
Because traffic is already flowing to multiple origins, failover is near-instant. No detection window is needed for the next request — the load balancer simply skips the unhealthy node. This also keeps all origins warm, caches populated, and autoscaling groups at steady state, eliminating cold-start risk.
When Active-Active Is Worth the Complexity
Active-active shines for high-throughput, low-latency applications where every second of failover matters. E-commerce, media streaming, and API gateways benefit from horizontal scaling and geographic affinity. It also enables zero-downtime deployments via blue-green origin shifts: drain one origin, deploy, then rebalance.
Complexity is the cost. You must solve data consistency. If origins serve dynamic content from separate databases, writes must replicate synchronously or you must route writes to a single primary. For static assets, ensure both origins serve byte-identical content with matching ETags and Cache-Control headers, otherwise you will fragment cache and cause revalidation churn. Cost also doubles if both origins are provisioned for peak load. Evaluate this against cost optimization goals — active-active is justified when the cost of downtime exceeds duplicated origin spend.
Head-to-Head
Choose based on workload characteristics, not habit. The table below summarizes operational differences we observe in production.
| Criterion | Active-Passive | Active-Active |
|---|---|---|
| Traffic Distribution | 100% primary, 0% secondary until failure | Concurrent across N origins (weighted / latency-based) |
| Failover Speed (RTO) | 15–30s (active probe) + passive retry ~1–2s for retried requests | 0–5s; next request skips unhealthy node |
| Origin Warmth | Secondary cold; needs warming strategy | All origins warm; caches and autoscaling steady |
| Consistency Risk | Low; single writer at a time | Higher; requires replication or immutable assets |
| Cost | Standby capacity; lower steady-state cost | 2× provisioned capacity; higher baseline |
| Operational Complexity | Simple health checks and priority switching | Load balancing, ejection, rebalancing, data sync |
| Best For | Static sites, DR regions, budget-sensitive HA | Global APIs, commerce, streaming, low-RTO SLOs |
Health Checks, Retries, and Shielding
Failover is only as reliable as its health signals. A poorly chosen health endpoint is worse than none.
Designing Health Probes
Use a dedicated, unauthenticated endpoint that exercises critical dependencies: app server, cache, database read, and disk. Avoid / as a health check — it may be cached or heavy. Return 200 only when the origin can serve production traffic; return 503 during deployments or when load exceeds a threshold to voluntarily shed load. Keep response bodies under 1KB and set Cache-Control: no-store.
Tune intervals for your SLO. For active-passive, 10-second interval with 3 failures gives 30-second detection. For stricter SLOs, use 5-second interval with 2 failures, but ensure the origin can handle probe QPS: 100 edge POPs × 0.2 RPS = 20 RPS of health traffic. Add jitter and consider shield aggregation — let the shield POP probe origins and edges probe the shield.
Retry and Circuit Breaking
Configure the CDN to retry only safe methods. Retry GET and HEAD on 502/503/504 and timeouts, but never retry POST/PUT blindly. Limit retries to one additional origin to avoid amplifying origin load during partial outages. Implement circuit breaking: if secondary also fails, serve stale from cache via stale-if-error and stale-while-revalidate rather than cascading failures. This pattern pairs well with shield caching and origin keepalive tuning.
Origin shielding further reduces failover thundering herd. With shielding, only the shield POP fetches from origin; edges fetch from shield. On failover, only shield nodes need to converge, not every edge. This cuts origin request burst by 90%+ during failover events.
Configuration Examples
Below are minimal, production-tested patterns for both strategies. Adapt thresholds to your traffic and origin latency.
{
"OriginGroups": {
"Quantity": 1,
"Items": [{
"Id": "primary-failover-group",
"FailoverCriteria": {
"StatusCodes": { "Quantity": 4, "Items": [500,502,503,504] }
},
"Members": {
"Quantity": 2,
"Items": [
{ "OriginId": "primary-origin-us-east-1" },
{ "OriginId": "secondary-origin-eu-west-1" }
]
}
}]
},
"HealthCheck": {
"Path": "/healthz",
"IntervalSeconds": 10,
"FailureThreshold": 3,
"RequestTimeout": 5
}
}backend origin_a {
.host = "origin-a.example.com";
.probe = { .url = "/healthz"; .interval = 5s; .threshold = 2; .window = 3; }
.weight = 50;
}
backend origin_b {
.host = "origin-b.example.com";
.probe = { .url = "/healthz"; .interval = 5s; .threshold = 2; .window = 3; }
.weight = 50;
}
sub vcl_recv {
set req.backend_hint = directors.round_robin.backend();
# geographic steering example
# if (client.geo.continent == "EU") { set req.backend_hint = origin_b; }
}
sub vcl_backend_response {
if (beresp.status >= 500 && bereq.retries == 0) {
return (retry);
}
}
sub vcl_backend_error {
if (bereq.retries == 0) { return (retry); }
}upstream origin_pool {
server primary.example.com:443 max_fails=3 fail_timeout=30s;
server secondary.example.com:443 backup; # active-passive: backup keyword
# For active-active, remove 'backup' and add weight=1 for each
keepalive 32;
}
proxy_next_upstream error timeout http_502 http_503 http_504;
proxy_next_upstream_tries 2;
proxy_connect_timeout 3s;
proxy_read_timeout 5s;
health_check interval=10s fails=3 passes=2 uri=/healthz;Whichever platform you use, validate failover with controlled fault injection. Block the primary origin security group, return 503 from /healthz, and measure time-to-recovery and error rate. Automate this in staging monthly. Also verify TLS: both origins must present valid certificates for the same hostname or use distinct origins with correct SNI, otherwise failover will fail at TLS handshake.
Best Practices and Common Pitfalls
Keep failover origins functionally identical. Drift in headers, compression, or image optimization between origins causes cache poisoning. Version your origin deployments together and run synthetic checks that compare response hashes.
Do not failover on 4xx. 400, 403, and 404 indicate client or content errors, not origin health. Failing over on 404 will amplify origin load and mask content gaps. Restrict failover to 5xx and timeouts.
Serve stale on total failure. Configure Cache-Control: stale-while-revalidate=60, stale-if-error=86400 at origin and enable stale serving at the CDN. When both origins are down, stale content is better than an error page and buys time for recovery.
Monitor failover as a first-class event. Alert on origin health state changes, retry rate, and secondary origin traffic share. Track cache invalidation lag after failover — purging must propagate to both origins’ caches if you use shield or tiered caching.
Test failback. Failover is half the story. Abrupt failback can overload a recovering primary. Use a hold-down timer (e.g., primary must be healthy for 60 seconds) and gradually ramp weight back to primary.
Finally, document your RTO and communicate it. If active-passive gives 30-second RTO and your SLO allows 0.1% error budget, that may be sufficient. Do not over-engineer active-active if standby redundancy meets the business need.
Conclusion
Active-passive and active-active are not competing dogmas but tools for different availability and cost tradeoffs. Active-passive offers simplicity, lower cost, and deterministic behavior — ideal for static and cache-heavy workloads. Active-active delivers near-zero RTO, continuous warmth, and geographic performance at the cost of replication complexity and duplicated capacity.
Start with active-passive if you are building HA for the first time, instrument health checks and passive retries, and warm your secondary. Evolve to active-active when your error budget or global latency requirements demand it, and invest in data synchronization and observability to keep it safe. Either way, failover is not a one-time configuration but a continuous operational practice.
Frequently Asked Questions
What is the difference between active-passive and active-active CDN origin failover?
Active-passive keeps a secondary origin on standby and only routes traffic to it when the primary fails health checks. Active-active distributes traffic across multiple healthy origins simultaneously using load balancing, providing both redundancy and horizontal scaling with near-instant ejection of failed nodes.
How does a CDN detect origin failure?
CDNs use active health checks (HTTP probes to a status endpoint every 5–30 seconds), passive monitoring of 5xx errors and timeouts, and TCP connection failures. After consecutive failures exceed a threshold (typically 2–3), the origin is marked unhealthy and failover is triggered. Passive retries can shift a single request immediately on 502/503/504.
Which failover pattern is better for high-traffic global applications?
Active-active is generally better for high-traffic global apps because it provides lower latency via geographic load balancing, eliminates cold-start issues on failover, and scales throughput. It requires data replication and consistency handling, so it suits stateless or eventually-consistent workloads where duplicated origin cost is justified.
Can active-active failover cause data inconsistency?
Yes, if origins serve dynamic or personalized content without synchronized state. Without replication, cache writes, sessions, or database updates may diverge. Use shared storage, database replication, or stick to serving immutable static assets from both origins to avoid inconsistency. Route writes to a single primary when strong consistency is required.