Choosing a Shield Location for a Multi-Region Origin
Problem Statement
A shield tier has been enabled and origin traffic barely moved. The configuration is correct and the feature is active; the location is wrong. Shield placement is one of the few CDN settings where the intuitive answer — put it close to the users — is the opposite of the correct one.
Prerequisite Concepts
- Origin shielding and request collapsing — what a shield is for and how it differs from collapsing.
- Configuring origin shield on Cloudflare and Fastly — the vendor controls this decision feeds into.
- Understanding HTTP cache hierarchy — the tiering model a shield adds a layer to.
Step-by-Step Resolution
Step 1 — Establish where the origin actually is
This is less obvious than it sounds when the origin sits behind a managed load balancer or an anycast address. Resolve and measure rather than assuming:
# Where does the origin hostname actually terminate?
dig +short origin.example.com
curl -sw '%{time_connect} connect, %{time_starttransfer} ttfb\n' \
-o /dev/null https://origin.example.com/healthz
A connect time of a few milliseconds from a host in one region and two hundred from another tells you where the origin lives regardless of what the DNS record suggests.
Step 2 — Measure candidate locations against the origin
The measurement that matters is round-trip time from each candidate shield location to the origin:
for pop in fra dfw sjc lhr; do
printf '%-4s ' "$pop"
curl -sw '%{time_connect}s\n' -o /dev/null \
--resolve origin.example.com:443:"$(pop_ip $pop)" https://origin.example.com/healthz
done
Choose the lowest. A shield twenty milliseconds from the origin turns each miss into a cheap fetch; one two hundred milliseconds away adds that cost to every miss in the entire footprint.
Step 3 — Pair each origin region with its own shield
For an active-active origin, a single shield is wrong in both directions: it either adds a cross-region hop for one of the backends, or it collapses traffic that geographic routing had deliberately separated.
backend origin_eu { .host = "eu.origin.example.com"; .port = "443"; }
backend origin_us { .host = "us.origin.example.com"; .port = "443"; }
sub vcl_recv {
# Route by region, and let each backend have its own shield
if (client.geo.continent_code == "EU") {
set req.backend_hint = origin_eu;
} else {
set req.backend_hint = origin_us;
}
}
Step 4 — Verify traffic really passes through the shield
The test is that a miss at one location produces a hit at another without touching the origin:
# Warm through one PoP
curl -sI --resolve example.com:443:151.101.1.10 https://example.com/products/9472 \
| grep -iE 'x-cache|^age'
# Request through a different PoP — expect a shield hit, and no origin log entry
curl -sI --resolve example.com:443:199.232.13.10 https://example.com/products/9472 \
| grep -iE 'x-cache|^age'
A chained cache-status value showing a miss at the edge and a hit upstream is the confirmation. Checking the origin’s own access log for the second request is the definitive version of the same test.
Expected Output / Verification
A correctly placed shield produces three observable changes: origin request count falls to roughly the number of distinct objects requested per lifetime, origin request latency falls because the shield is adjacent, and edge hit ratio is largely unchanged — the shield affects misses, not hits.
before: origin 1840 req/min, p50 origin latency 210 ms
after: origin 96 req/min, p50 origin latency 22 ms
If origin request count barely moves, either the shield is not in the path or the two tiers are composing cache keys differently, which prevents the shield from ever matching an edge request.
Edge Cases
- Key mismatch between tiers. If the edge normalises the query string and the shield does not, the shield never holds anything the edge asks for. Apply identical key rules at both tiers.
- A shield that becomes a single point of failure. All misses now depend on one location. Confirm the vendor’s fallback behaviour when a shield is unavailable, and prefer a configuration that fails through to the origin rather than erroring.
- Origin moved without revisiting the shield. Placement is a property of origin topology. A migration to another region silently makes the shield remote and every miss expensive.
- Anycast hiding the origin’s real location. Latency measurement, not DNS, tells you where the origin is. An anycast address can resolve identically everywhere while terminating in one place.
- Failover to a passive region. If traffic fails over to a second origin region, the shield paired with the primary is now remote. Pair shields with backends rather than with the service.
- Very small footprints. With a handful of edge locations the fan-in a shield collapses is small, and the extra hop may cost more than it saves. Measure before adopting it.
Frequently Asked Questions
Why should the shield be near the origin rather than near users?
Because its purpose is to make the origin round trip rare, not fast. Edge locations already provide user proximity. A shield near users adds a hop for everyone while doing nothing about the number of independent caches asking the origin for the same object.
What should I do with an active-active origin in two regions?
Pair each backend with its own shield in the same region. A single shield in front of two regions either adds cross-region latency for one of them or defeats the geographic routing entirely.
Is automatic shield selection good enough?
Often, yes. Where the vendor can infer origin location it will usually pick reasonably. Explicit selection is worth the effort when the origin is behind an anycast address or a load balancer that hides its real location.
Does a shield help if the origin is itself a cache?
Less than you would expect. If the origin is already a caching layer with a high hit ratio, the shield mostly duplicates it. The gain comes from reducing the number of independent requesters, which matters most when the origin does real work.
Related
- Configuring origin shield on Cloudflare and Fastly covers the vendor configuration once the location is chosen.
- Debugging a thundering herd at the origin is the symptom a shield most directly addresses.
- Cache key normalization and query strings explains why key consistency between the tiers is a prerequisite for any of this to work.