CloudFront Cache Simulator: a request in three layers.
A request goes through the edge POP, the regional edge cache, the optional Origin Shield and finally the origin. On a miss it goes one layer deeper, and on the way back every layer it passed fills its own cache. A CDN is that chain plus TTL arithmetic and invalidation. Send a request below to see the cascade.
The stacked lanes are the four layers a request passes through: Edge POP, Regional Edge Cache, the optional Origin Shield, and the Origin that always holds the object. Send request lights each lane in turn as the request checks it for a HIT, then moves deeper on a MISS. Once the object is found, the response flows back and every layer it passed stores its own copy with the TTL you set. The stat strip tracks where hits landed, the running hit ratio and bytes saved, and the log lists each hop with its latency.
Send the same URL twice in a row. The first request misses at every layer down to the origin and is the slowest, around 180ms plus each hop. The second is an edge HIT at roughly 8ms, because the response on the way back warmed every layer. Press Fast-forward 30s a couple of times to expire the TTLs, and the next request goes to the origin again. With Origin Shield off there is one layer fewer to warm, but every region now sends its misses straight to the origin.
What CloudFront is
A CDN with three caching layers, plus a few protection and routing services bolted on. AWS publishes roughly 600+ points of presence: about 450 edge locations plus 13 regional edge caches. The edge locations terminate TLS and are where a request first lands. Regional caches sit one tier deeper, one per AWS region. Origin Shield is an optional single regional cache placed in front of your origin, so all CloudFront traffic converges through it before reaching you.
On top of caching, CloudFront does DDoS mitigation and WAF rule evaluation, and lets you run code at the edge, either short JavaScript via CloudFront Functions or full Node/Python via Lambda@Edge. The cache hierarchy is the part you tune for cost and hit rate; the rest is configuration.
The cache hierarchy
From client to origin, in order: Edge POP (closest to the user, terminates TLS, fastest answer) → Regional Edge Cache (one per region, larger, longer-lived) → Origin Shield (optional, a single regional cache that consolidates traffic before it leaves CloudFront) → Origin (S3, ALB, EC2, MediaPackage, custom). Each layer caches independently and answers with a HIT or a MISS. On a MISS, the request moves deeper; on a HIT, the response flows back, populating every layer it passed.
The default-without-Origin-Shield path is three layers (edge, regional, origin). With Origin Shield enabled, it's four. The shield adds roughly 5–15ms of latency on a cold miss, but it cuts origin-facing request rates a lot for deployments spread over many regions.
Cache keys and what makes two requests the same
CloudFront hashes the URL plus whichever headers, query strings, and cookies you've told it to include via a cache policy. Anything not in the cache policy is invisible to caching. Two requests with the same cache key share a response even if their other headers differ, and two requests that differ on a field in the key are two cache entries.
Origin request policies are separate. They control what gets forwarded to the origin on a MISS, independent of what's in the cache key. A common mistake is putting Accept-Language in the origin request policy but not the cache policy. The origin returns different content per language, but CloudFront caches whichever one arrived first and serves it to everybody.
TTL: minimum, default, maximum
A cache policy declares three TTLs: minimum, default, maximum. The TTL CloudFront uses for a given response is the clamp of Cache-Control: max-age (or s-maxage, which wins for CDNs) into [min, max]. If the origin sends no Cache-Control at all, CloudFront uses the default.
TTLs tend to sit at two extremes. Static assets with a content hash in the URL (JS, CSS, images) get max-age=31536000, immutable, a year. HTML and API responses get short TTLs (30s–5min) so changes show up quickly. Anything in between is usually a misconfiguration.
Cache hit ratios in production
Static-asset buckets routinely reach 95%+ at the edge. API caching, where it applies, lands at 30–70% depending on how much of the surface is cacheable. Video streaming sits at 90%+, which is much of the reason CDNs exist. Below 80% on a content-heavy site usually points to a cache-key bug (something is in the key that shouldn't be) rather than a real limit.
The metric to watch is edge hit ratio from CloudFront's reports. AWS also reports regional and origin hit rates separately so you can see where the misses are landing.
Origin Shield and when the extra hop pays off
Origin Shield designates one regional cache that all CloudFront traffic passes through before reaching your origin. Two things follow. Your origin sees a small fraction of the requests it would otherwise see, because identical requests from all regions are deduplicated, and you pay for extra GB-out on the shield-to-origin traffic.
It pays off when many viewer regions request the same content (global software downloads, popular video). It doesn't when the footprint is small, when the hit ratio is low (the shield adds latency with little dedup benefit), or when the origin already sits behind a fast cache (such as a second CDN in front).
Invalidation and versioned URLs
CloudFront invalidation marks paths as stale across all edges. Propagation takes about 60 seconds. The first 1,000 paths per month are free, then $0.005 each, and a wildcard counts as one path.
The usual advice is to avoid invalidating. Version assets in the URL instead: /app.v347.js, /photo-abc123hash.jpg. Each release ships new URLs; old ones expire naturally. Keep invalidation for purging something that is already cached, like a bad image or a leaked URL.
Lambda@Edge vs CloudFront Functions
| CloudFront Functions | Lambda@Edge | |
|---|---|---|
| Runtime | JavaScript (subset) | Node.js, Python |
| p99 latency | ~1 ms | ~50 ms |
| Runs at | Every edge POP | Regional edges only |
| Triggers | Viewer request, viewer response | Viewer request/response + origin request/response |
| Memory | 2 MB | Up to 10 GB |
| Best for | Header rewrites, URL normalisation, A/B routing, simple auth | Image resizing on the fly, full JWT validation, server-side rendering at the edge |
Functions are 80× cheaper per million invocations than Lambda@Edge. If a job fits in Functions, use Functions, and use Lambda@Edge only for the heavier transformations.
Origin protection with OAC, signed URLs and signed cookies
Keep your S3 origin from being reachable directly. Use Origin Access Control (OAC, the modern replacement for OAI). CloudFront signs requests to S3 with SigV4 using a service principal; S3 only allows access from CloudFront's principal via its bucket policy. The bucket stays private.
For paid content, sign URLs or cookies with a CloudFront key pair. Signed URLs are good for one-off downloads; signed cookies are good for sessions where the user authenticates once and then loads many resources (HLS / DASH video).
Real deployments
Disney+ launch (Nov 2019). Architected entirely on CloudFront, with 250+ Tbps of peak edge capacity reported in the months after launch. The team has publicly discussed how Origin Shield protected the encoders when millions of viewers tuned in to the same premiere.
Netflix Open Connect. Netflix runs its own embedded ISP-located cache appliances, but the source-of-truth content sits in S3 and CloudFront fronts the rest of the surface (web, metadata APIs, image art). The same pattern shows up in BBC iPlayer, Hulu, and most large video platforms.
Static-site hosting. S3 + CloudFront + ACM is the default modern hosting stack for documentation sites, marketing pages, and SPAs. Vercel, Netlify, and Cloudflare Pages all sit on similar primitives elsewhere.
Five things that commonly break
- Forgetting headers in the cache key. Origin returns different content per
Accept-Language; CloudFront caches the first response and serves it to everyone. Include every header the origin varies on. - Aggressive TTL on dynamic content. Caching API responses for an hour to keep them fast means a status page can show stale order counts for 60 minutes after a deploy.
- Misconfigured Vary header. Origins that send
Vary: *orVary: User-Agentkill the hit rate. CloudFront treats every Vary'd field as a cache-key dimension implicitly via the policy; mixing the two leads to surprises. - CORS preflight not cached. If
OPTIONSisn't in the cache policy, every preflight goes to origin. Front-ends that issue many CORS requests get slower. - SigV4 origin-auth headers stripped. If your origin request policy doesn't forward
Authorizationand the SigV4 date / token headers, your private S3 origin returns 403 to CloudFront. OAC handles this correctly; legacy OAI configurations sometimes don't.
Settings worth tuning
- Cache policy. This setting moves your hit ratio the most. Pick from the AWS-managed presets first (CachingOptimized, CachingDisabled), then customise only what you need.
- Origin request policy. What gets forwarded to origin on MISS. Forward only what the origin needs.
- TTL clamp. Default TTL when origin sends no Cache-Control. Set this deliberately instead of accepting whatever CloudFront ships by default.
- Compression. Enable both gzip and Brotli at the edge. Brotli at level 6 beats gzip at level 9 on text payloads.
- HTTP/2 and HTTP/3. Enable both. HTTP/3 (QUIC) helps mobile and high-latency clients.
- Price class. If your audience is purely US/EU, restrict to the cheaper price class and save on edge serving from Asia/South America POPs.
Further reading
- CloudFront developer guide. The main reference. The performance and caching pages matter most here.
- Origin Shield announcement post. AWS's own framing of when and why to enable it.
- CloudFront in the AWS Codex. A longer reference that goes with this simulator.
- DNS resolution simulator. The other layer of CDN routing: how the client finds the right edge POP in the first place.
- Load balancer simulator. Origin-side traffic distribution after CloudFront has done its job.