11.1
CloudFront: Caching at the Edge
Edge locations, origins, Origin Access Control, cache keys and TTL, and CloudFront vs S3 replication.
26 min Reading + animations
Tip: tap or hover any dotted-underlined term to see what it means.
By the end of this lesson you will be able to
- Explain what a CDN does and why CloudFront makes a site faster and cheaper to run: lower latency, origin offload, fewer long-distance handshakes.
- Describe CloudFront’s layers (edge locations, Regional Edge Caches, Origin Shield) and follow a request through a cache miss, a hit, a revalidation and an origin outage.
- Choose the right origin (S3 bucket, S3 website endpoint, custom HTTP origin, VPC origin) and keep an S3 origin private with Origin Access Control and a bucket policy.
- Route paths to origins with cache behaviours, and design a cache key and TTLs with cache policies and origin request policies.
- Set up origin failover with an origin group, HTTPS with an ACM certificate in us-east-1, and logging.
- Pick between CloudFront, S3 Cross-Region Replication and S3 Transfer Acceleration from the wording of an exam question.
#Why put a cache near your users
#The distance problem
Light in fibre covers roughly 200 km per millisecond, and real cables never run in a straight line. A packet from Dhaka to a server in North Virginia (us-east-1) and back takes about 230 ms. That is one round trip, and a web page needs many:
- A new HTTPS connection costs one round trip for the TCP handshake and one for TLS 1.3 (two for older TLS) before the first request is even sent, then one more for the request and the answer: about 3 round trips ≈ 700 ms before the first byte arrives.
- A product page loads dozens of photos, scripts and style sheets. Browsers reuse connections, but every request still waits at least one round trip.
- The further away the server, the more packets get lost on the way, and every loss stalls TCP.
The cure is not a faster server; it is a shorter distance. If a copy of the photo sits in a data centre 20–30 ms away, the same three round trips take under 100 ms.
#What CloudFront is
Amazon CloudFront is AWS’s content delivery network (CDN): a worldwide network of caching servers that sits between your users (the viewers) and your servers (the origins). It is a global service: you do not pick a Region for it, and its configuration is pushed to every location.
What you get by putting it in front of a site or an API:
- Lower latency. Viewers connect to a nearby location; TLS is finished there, close to them.
- Origin offload. Popular files are served from caches, so the origin handles a small fraction of the requests. During an Eid sale or an election night, that is the difference between a fast site and a dead one.
- A faster path for what is not cached. Requests that must reach the origin (an API call, a checkout) travel the long distance over the AWS backbone, on connections CloudFront keeps open, instead of over the public internet.
- Protection. Being spread worldwide, CloudFront absorbs network floods; AWS Shield Standard is included at no cost, and AWS WAF can filter requests at the edge. That is lesson 11.2.
- Cheaper delivery. Data transfer from AWS origins (S3, ALB, EC2) to CloudFront is free, and CloudFront’s own transfer prices are lower than S3’s for traffic to the internet.
CloudFront is not only for static files. It also speeds up dynamic content (HTML built per request, API responses) because of the warm connections and the backbone, and it carries WebSocket and gRPC traffic. What it does not do is run your application: compute at the edge is limited to small functions (lesson 11.3).
#How CloudFront is built
#Edge locations and Regional Edge Caches
CloudFront has two tiers of caches in front of your origin, plus an optional third:
- Edge locations, also called points of presence (PoPs): more than 750 of them in over 100 cities and 50 countries, plus more than 1,140 smaller embedded PoPs inside internet providers’ networks. DNS sends each viewer to the PoP that can serve them best, normally the one with the lowest latency. For a viewer in Dhaka that is typically a PoP in a nearby country, such as Kolkata or Singapore. PoPs are small and keep the most popular objects.
- Regional Edge Caches: 15 larger caches in AWS Regions, each shared by many PoPs. When a PoP misses, it asks its Regional Edge Cache before going to the origin. They keep objects longer, which helps the long tail: product photos nobody opened today, last week’s news, a video that suddenly becomes popular again.
- Origin Shield (optional, extra charge): one more cache layer in the Region you choose, closest to your origin, in front of all the Regional Edge Caches. See “Origin Shield: one cache in front of the origin” below.
Three exceptions to the path through the Regional Edge Cache are worth knowing: PUT, POST, PATCH, OPTIONS and DELETE go straight from the PoP to the origin; requests that CloudFront decides at request time are dynamic (not cacheable) also go direct; and when an S3 origin is in the same Region as the Regional Edge Cache, the PoP skips that tier and talks to S3 itself.
Watch one photo go through these tiers, including what happens when its TTL runs out and when the origin is down:
One photo, many viewers: the life of a cached object
Bazaar Bari keeps its product photos in a bucket in North Virginia. Shoppers in Bangladesh reach a nearby CloudFront edge location instead. Watch when the request travels all the way to the origin, and when it does not.
Scenario
Nobody near Dhaka has asked for this photo yet, so no cache has it.
Cache state for /img/saree-42.jpg
| Edge copy | Regional copy | Age / TTL | x-cache |
|---|---|---|---|
| none | none | — | — |
Viewer 1 opens a product page. DNS for shop.example.com has already sent the browser to the CloudFront PoP with the lowest latency, not to Virginia. The browser asks that PoP for the photo.
#The distribution
A distribution is one CloudFront configuration. When you create one, CloudFront gives it a domain name such as d111111abcdef8.cloudfront.net. A distribution holds:
- one or more origins (up to 100) and optional origin groups for failover;
- cache behaviours: which paths go to which origin, and how they are cached;
- general settings: alternate domain names (your own names, such as
shop.example.com, up to 100), the TLS certificate, the default root object, logging, a price class (which parts of the network to use, lesson 11.2), an AWS WAF web ACL, IPv6 and HTTP/2 and HTTP/3 support.
To serve the site at your own name, add the name as an alternate domain name, attach a certificate that covers it, and point DNS at the distribution: in Route 53 an Alias record to the distribution, which also works at the zone apex (example.com) and costs nothing per query (lesson 8.2). Elsewhere, a CNAME to d111111abcdef8.cloudfront.net for a subdomain.
Changes to a distribution are deployed to every location; that takes a few minutes, during which the status is “Deploying”.
#Origins
An origin is where CloudFront fetches what it does not have. The kinds you will meet:
| Origin | What it is | How it is protected | Typical use |
|---|---|---|---|
S3 bucket (REST endpoint, bucket.s3.region.amazonaws.com) | An S3 origin; CloudFront can sign its requests | Origin Access Control + bucket policy; bucket stays private | Static sites, images, video files, downloads; also uploads to S3 through CloudFront |
S3 website endpoint (bucket.s3-website-region.amazonaws.com) | A custom origin that speaks HTTP only | None from CloudFront: the bucket must be public | Sites that need S3’s index documents in every folder and its redirect rules (lesson 10.3) |
| Custom HTTP origin | Any server reachable over HTTP or HTTPS on the internet: a public ALB, EC2 with a public address, API Gateway, a Lambda function URL, a server in your own data centre | Security group with the CloudFront prefix list, a secret header (lesson 11.2) | Dynamic sites, APIs, anything not in S3 |
| VPC origin | A private ALB, NLB or EC2 instance in a private subnet | No public address at all | Applications that must not be reachable from the internet (lesson 11.2) |
| AWS media services | AWS Elemental media services | Service-specific | Live and on-demand video streaming |
For every origin you also set: an optional origin path (fetch from /production inside the bucket), custom headers to add to every origin request, and for custom origins the origin protocol policy (HTTP only, HTTPS only, or match the viewer) and ports. Three timers decide how CloudFront treats a slow or dead origin: connection timeout (default 10 s, 1–10), connection attempts (default 3, 1–3) and response timeout (default 30 s, 1–120). The defaults mean a dead origin can make a viewer wait about 30 seconds before anything happens.
#Cache behaviours: which path goes where
A cache behaviour is a rule that matches a path pattern and says how to handle matching requests. A distribution has a list of them (up to 75), checked in order of precedence; the first match wins. The last one is always the default behaviour, *, which catches everything else and cannot be deleted.
Each behaviour sets:
- the origin (or origin group) to use;
- the viewer protocol policy: allow HTTP and HTTPS, redirect HTTP to HTTPS, or HTTPS only;
- the allowed methods: GET and HEAD; GET, HEAD and OPTIONS; or all seven (adding PUT, POST, PATCH and DELETE); and whether OPTIONS responses are cached;
- the cache policy (cache key and TTLs) and origin request policy (what to forward), explained below, and an optional response headers policy (security headers, CORS headers);
- edge functions, signed URLs or cookies, field-level encryption and compression.
Path patterns are case-sensitive and support * (any characters) and ? (one character): /images/*, /api/*, *.mp4.
Cache behaviours: one domain, several origins
shop.example.com has three cache behaviours, checked in order: /images/* goes to a bucket and is cached for a day, /api/* goes to the ALB and is never cached, and the default (*) behaviour catches everything else.
Scenario
Matched cache behaviour
| Path pattern | Origin | Cache policy | Allowed methods |
|---|---|---|---|
| /images/* | images bucket | CachingOptimized | GET, HEAD |
The browser asks for /images/saree-42.jpg. CloudFront compares the path with the behaviours in precedence order; /images/* is first and matches.
#Keeping an S3 origin private: Origin Access Control
If the bucket behind CloudFront were public, anybody could skip CloudFront and download straight from S3: no WAF, no geo restriction, no signed URLs, no edge logs, and a full S3 bill for every byte. Origin Access Control (OAC) closes that door:
- CloudFront signs every request to the bucket with AWS Signature Version 4, as the CloudFront service, and identifies the distribution making it. With the recommended setting (“Sign requests”) the connection to S3 is always HTTPS.
- The bucket keeps Block Public Access on. Its bucket policy allows the service principal
cloudfront.amazonaws.com, but only for requests made on behalf of your distribution, using theAWS:SourceArncondition.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipalReadOnly",
"Effect": "Allow",
"Principal": { "Service": "cloudfront.amazonaws.com" },
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bazaarbari-images-example/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/EDFDVBD6EXAMPLE"
}
}
}
]
}
Three details that come up in real setups and in exam questions:
- The condition is the security. Without it, any CloudFront distribution in any account, including one an attacker creates, could read the bucket.
- SSE-KMS. If objects are encrypted with a customer managed KMS key, the key policy must also allow
cloudfront.amazonaws.comto usekms:Decrypt(sameAWS:SourceArncondition), otherwise viewers get 403 (lesson 10.8). - Uploads. To accept PUT through CloudFront, the behaviour must allow all methods and the bucket policy must also allow
s3:PutObjectfor the distribution. OAC supports these dynamic requests.
OAC also requires the bucket’s Object Ownership to be “bucket owner enforced” (the default for new buckets), and it cannot be used with a website endpoint origin: there is nothing to sign for an anonymous HTTP endpoint.
#The legacy way: origin access identity
Before 2022 the same job was done by an origin access identity (OAI): a special CloudFront user that the bucket policy names as its principal (arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity …). It still works for reading SSE-S3 buckets in older Regions, but it does not support SSE-KMS, does not support every kind of upload, and does not work in S3 Regions launched after December 2022. AWS now calls OAI legacy and recommends OAC. Older exam questions and the slides of a few years ago say OAI; read either as “CloudFront can read a private bucket, nobody else can”.
To migrate without an outage: add a statement for the distribution (OAC) next to the OAI statement in the bucket policy, switch the origin to OAC, wait for the deployment, then remove the OAI statement.
Origin Access Control: only CloudFront may read the bucket
The photo bucket is private. CloudFront signs every request it sends to S3, and the bucket policy trusts those signatures only when they come from Bazaar Bari’s own distribution.
Scenario
Bucket bazaarbari-images-example
| Block Public Access | Bucket policy allows | Encryption |
|---|---|---|
| On | this distribution only | SSE-S3 |
A shopper asks shop.example.com for a photo. On a miss, the edge must fetch it from the bucket, which has Block Public Access on.
Self-checkQuestion
An S3 bucket serves product photos through CloudFront. The security team requires that the photos can only be downloaded through CloudFront, never directly from S3. What should the architect configure?
#The cache key: what makes two requests the same
#What is in the key
The cache key is the set of values CloudFront uses to decide whether a request matches something already in the cache. By default it is the distribution’s domain name plus the URL path. You can add, through a cache policy:
- query strings: none, all, an allow list or all except a deny list;
- headers: none or a list (for example
CloudFront-Viewer-Country, or a normalisedAccept-Encoding, which CloudFront adds itself when compression is on, so gzip and Brotli copies are cached separately); - cookies: none, all, an allow list or all except a deny list.
The rule that decides everything: put into the cache key exactly the values that change the response, and nothing else.
- Leave out something that changes the response (the
sizequery string of an image resizer), and viewers get the wrong copy: a thumbnail on the zoom page. - Put in something that does not change the response (a
fbclidtracking parameter, the fullUser-Agent, a session cookie on a photo), and every variation is a separate cached copy. The hit ratio collapses, the origin takes the load, and you pay for it.
#Cache policy and origin request policy
Two separate policies are attached to each behaviour, and the difference is a classic question:
Cache policyOrigin request policy
- Decides the cache key: which query strings, headers and cookies make a request different.
- Holds the TTLs (minimum, default, maximum) and the compression settings.
- Everything in the cache key is also forwarded to the origin automatically.
- Managed examples: CachingOptimized (no query strings, headers or cookies; TTL 1 s / 1 day / 365 days), CachingDisabled (all TTLs 0),
UseOriginCacheControlHeaders.
- Decides what else is forwarded to the origin on a miss, without adding it to the cache key.
- Use it when the origin needs a value that does not change the cached answer (a header for its logs, a user’s country for analytics), or when caching is disabled and the origin needs everything.
- Managed examples:
AllViewer,AllViewerExceptHostHeader(for API Gateway and Lambda function URLs, which need their own Host),CORS-S3Origin. - Nothing here can make the cache key bigger.
A dynamic API behind CloudFront is usually CachingDisabled + AllViewer (or AllViewerExceptHostHeader): nothing is cached, and the origin sees every header, cookie and query string. Static files from S3 are usually CachingOptimized with no origin request policy, or CORS-S3Origin when browsers fetch them cross-origin. Older distributions use “legacy cache settings” on the behaviour instead of policies; the policies replaced them.
#TTL: how long a copy lives
#Minimum, default and maximum TTL
The TTL (time to live) is how long CloudFront keeps a copy before it has to check with the origin again. The cache policy holds three numbers, and the origin’s own headers decide where in that range the TTL falls:
| What the origin sends | TTL CloudFront uses |
|---|---|
Cache-Control: max-age=N | N, but never less than the minimum TTL or more than the maximum TTL |
Cache-Control: s-maxage=N (with or without max-age) | N, within the same bounds. s-maxage is for shared caches like CloudFront; browsers use max-age |
Expires: <date> (and no max-age) | Until that date, within the bounds. max-age wins if both are present |
| Nothing | The default TTL (24 hours if you set nothing else), or the minimum TTL if that is larger |
no-cache, no-store or private | Respected if the minimum TTL is 0; cached for the minimum TTL if it is above 0 |
The last row is a trap: the managed CachingOptimized policy has a minimum TTL of 1 second, so an origin’s no-store is overridden and the response is cached for one second. For responses that must never be cached, use a policy with minimum TTL 0, such as CachingDisabled or UseOriginCacheControlHeaders.
Two more facts: a viewer’s own Cache-Control: no-cache in a request is ignored (users cannot force CloudFront to the origin), and a TTL is a maximum, not a promise: an object nobody asks for may be evicted earlier to make room.
#Hit, miss, revalidation, and serving stale
Every response from CloudFront carries headers that show what happened:
x-cache: Hit from cloudfront: served from the edge cache.x-cache: Miss from cloudfront: fetched from the Regional Edge Cache or the origin (also shown for requests that are never cached).x-cache: RefreshHit from cloudfront: the copy had expired; CloudFront asked the origin with a conditional request (If-None-Matchwith the ETag, orIf-Modified-Since), the origin said304 Not Modified, and the cached copy was served and renewed. Cheap: no body crosses the ocean.x-cache: Error from cloudfront: an error, from the origin or CloudFront itself.age: seconds since the copy was fetched.x-amz-cf-pop: which PoP answered (a code likeSIN2-P1).x-amz-cf-id: the request ID for support and logs.
When the origin is unreachable and the copy has expired, CloudFront can serve the stale copy instead of an error if the origin sent Cache-Control: stale-if-error=N (or the minimum TTL is above 0). stale-while-revalidate=N goes further: after expiry CloudFront serves the old copy immediately while it fetches a fresh one in the background. Errors from the origin (4xx and 5xx) are cached too, for 10 seconds by default, so a failing origin is not flooded; you can change this per status code with custom error responses (lesson 11.2).
#What CloudFront does not cache
- Responses to PUT, POST, PATCH and DELETE are never cached; CloudFront just proxies them. GET and HEAD responses are cached; OPTIONS responses only if you choose.
- Anything a TTL of 0 applies to: CachingDisabled, or the origin’s
no-storewith a minimum TTL of 0. - Files larger than 50 GB in a single GET response.
Now try it. Change the cache key and the TTL, and see what happens to the hit ratio and to the origin:
Cache key and TTL lab
Bazaar Bari’s Eid sale: 120,000 photo requests an hour for 400 product photos, from 15,000 shoppers, through 12 PoPs and 3 Regional Edge Caches. Photo URLs look like /img/saree-42.jpg?size=thumb&fbclid=… . Choose what goes into the cache key and how long copies live, then run an hour of traffic.
Query strings in the cache key
Header in the cache key
Cookies in the cache key
TTL
Press “Run one hour of traffic” to see the result.
#When the origin fails: origin groups
#Origin failover
An origin group has two origins: a primary and a secondary. A behaviour that points at the group sends every cache miss to the primary. If the primary returns one of the status codes you chose (any of 400, 403, 404, 416, 429, 500, 502, 503, 504), or cannot be connected to (counted as 503), or times out (counted as 504), CloudFront sends the same request to the secondary and returns its answer.
What to know about it:
- It works per request, with no health check and no memory: the next miss goes to the primary again. Lower the connection timeout and attempts on the primary, or each miss waits up to 30 seconds before failing over.
- It applies only to GET, HEAD and OPTIONS. Uploads and other writes are not failed over.
- A typical pair is a bucket and its Cross-Region Replication copy in another Region (lesson 10.4), or two load balancers in two Regions. Up to 10 origin groups per distribution.
Origin failover: a second origin for the same files
The photo bucket is copied to Mumbai with Cross-Region Replication. An origin group lists Virginia as primary and Mumbai as secondary, and the /images/* behaviour points at the group instead of at one bucket.
Scenario
Origin group “photos”
| Primary | Secondary | Failover on | Connect timeout × tries |
|---|---|---|---|
| bucket, us-east-1 | replica, ap-south-1 | 500, 502, 503, 504 | 10 s × 3 (default) |
On a cache miss, CloudFront always tries the primary origin first.
For a whole application that must move to another Region, origin groups are one piece: DNS failover with Route 53 health checks (lessons 8.3 and 8.4) or Global Accelerator (lesson 11.4) move all traffic, including writes.
#Origin Shield: one cache in front of the origin
Each Regional Edge Cache that misses goes to the origin on its own. With 15 of them, a popular new object can reach the origin many times, and some origins hate that: a live-video packager, an on-the-fly image resizer, a server in your own data centre with a thin link. Origin Shield adds one more cache in the Region you choose, the one closest to your origin. All Regional Edge Caches then go through it, and it collapses simultaneous requests for the same object into one origin request.
- Benefits: a higher overall hit ratio, much less origin load, and the traffic stays on the CloudFront network all the way to your origin.
- Cost: a charge per request that passes through Origin Shield as an extra layer (requests from the Regional Edge Cache in the same Region are not charged).
- It is a setting of the origin, works with origins inside or outside AWS, with origin groups, and in a multi-CDN setup where other CDNs pull from CloudFront.
- It is not worth it for content that is not cacheable or is rarely requested.
#HTTPS with CloudFront
There are two connections to secure: viewer → CloudFront and CloudFront → origin.
- Viewer protocol policy (per behaviour): HTTP and HTTPS, Redirect HTTP to HTTPS (CloudFront answers 301 with the https address, the usual choice for websites) or HTTPS only (HTTP requests get 403, common for APIs).
- Origin protocol policy (custom origins): HTTP only, HTTPS only or Match viewer. With HTTPS the origin’s certificate must be valid and must match the origin domain name, otherwise CloudFront returns 502 Bad Gateway. S3 REST origins with OAC are always HTTPS; website endpoints are always HTTP.
- Your own domain needs a certificate on the distribution. The default
*.cloudfront.netname has one already. Forshop.example.com, request a free public certificate in AWS Certificate Manager (ACM) in us-east-1 (N. Virginia), whatever Region your origin is in. A certificate in another Region does not appear in the CloudFront console. (For an ALB origin, the ALB’s own certificate stays in the ALB’s Region, lesson 6.4.) The certificate must cover every alternate domain name. - SNI or dedicated IP. CloudFront uses SNI (Server Name Indication) by default: the browser says which host name it wants during the TLS handshake, so one set of edge addresses can serve many certificates. It is free and every current browser supports it. For very old clients without SNI there is a dedicated IP option that costs about $600 a month per certificate. You also choose a security policy that sets the minimum TLS version viewers may use.
The certificate lives in us-east-1 for the same reason Lambda@Edge functions are created there (lesson 11.3): CloudFront is global, and its control plane uses that Region.
#Logs and monitoring
CloudFront can record every request. Standard logs (access logs) are delivered in batches, usually within minutes, to S3, CloudWatch Logs or Amazon Data Firehose; the logging itself is free, you pay for where they are stored. Each line has the time, PoP, client IP, URL, status, bytes, time taken and the result type (Hit, Miss, RefreshHit, Error, OriginShieldHit…). Real-time logs go to a Kinesis data stream within seconds, with the fields and sampling rate you choose, at a charge per million log lines; use them for live dashboards and alarms. CloudFront also publishes CloudWatch metrics (requests, bytes, 4xx and 5xx error rates, and, as a paid option, cache hit rate and origin latency), and AWS CloudTrail records configuration changes.
#What it costs
Pay-as-you-go CloudFront charges for data transfer out to viewers (per GB, cheaper per GB as volume grows, different by continent), HTTP and HTTPS requests (per 10,000), and extras: invalidations beyond the free 1,000 paths a month, Origin Shield, real-time logs, edge functions, dedicated IP certificates. The always-free tier covers 1 TB of transfer out and 10 million requests every month. Transfer from AWS origins to CloudFront is free, so a busy site served from S3 through CloudFront is usually cheaper than the same site served straight from S3. Price classes, which leave out the most expensive parts of the world to save money, are in lesson 11.2.
#CloudFront vs S3 Cross-Region Replication
Both are ways of getting data closer to users far from the bucket, and the exam likes to put them side by side. They work in completely different ways.
| CloudFront | S3 Cross-Region Replication (CRR) | |
|---|---|---|
| What it does | Caches copies of what viewers request, at hundreds of edge locations | Copies every new object into a bucket in another Region you choose |
| Where the copies are | The whole global edge network, automatically | Only in the Regions you set up, one rule (destination) each |
| When a copy is made | On the first request at each location, then kept for the TTL (often a day) | Asynchronously after each write, usually within seconds to minutes (99.99% within 15 minutes with Replication Time Control) |
| Freshness | Can be stale until the TTL ends or you invalidate | Near real time |
| Requirements | A distribution in front of the origin | Versioning on both buckets, an IAM role, a replication rule; existing objects need Batch Replication |
| Writes | Passed through to the one origin | The application writes to its local bucket; writes to the replica are not copied back unless you set up two-way replication |
| Best for | Static content that must be fast everywhere: images, video, CSS, JavaScript, downloads, also dynamic pages and APIs | Disaster recovery, compliance (a copy in another country or Region), low-latency access for applications in a few chosen Regions |
CloudFront or Cross-Region Replication?
Both put data closer to far-away users, in very different ways. CloudFront keeps temporary copies of what people read, at the edge. CRR keeps a full, permanent copy of every new object in another Region’s bucket.
Scenario
How the copy behaves
| Copy lives in | Copied when | Freshness | Writes |
|---|---|---|---|
| hundreds of edge caches | on first request | until TTL ends | passed to origin |
Shoppers everywhere open product photos. Each nearby edge fetches a photo the first time someone asks for it.
The notes add one more pairing, and it needs a correction: for “staff far away need low-latency uploads to a bucket”, CRR helps only if each office writes to its own Region’s bucket. When everybody must upload into one bucket, the standard answer is S3 Transfer Acceleration (lesson 10.6), which enters the AWS network at a nearby edge location. Uploading through a CloudFront distribution with PUT uses the same idea and works, but it is not what exam questions about uploads expect.
#What goes wrong
- 403 from an S3 origin. Missing or wrong bucket policy (no
AWS:SourceArn, wrong distribution ID), the key does not exist (S3 says 403, not 404, when CloudFront cannot list the bucket), no default root object for/, or SSE-KMS without a key policy statement. - Users see an old file after an update. The copy is still within its TTL. Invalidate the path or, better, version the file name (lesson 11.2). Check
agein the response. - Low hit ratio. Too much in the cache key: all query strings, all cookies,
User-Agent. Look at the URLs in the standard logs. - One user sees another user’s data. A personal response cached with a key that does not include the session: use CachingDisabled for such paths, or include the right value in the key.
- 502 Bad Gateway. CloudFront could not complete TLS with a custom origin (certificate expired, self-signed, or not matching the origin domain name), or the origin closed the connection.
- 504 Gateway Timeout. The origin did not answer in time: a security group or network ACL blocking CloudFront, an overloaded server, or a response slower than the response timeout.
- The certificate does not appear in the console. It was requested in a Region other than us-east-1.
- The site works at d111111abcdef8.cloudfront.net but not at shop.example.com. The alternate domain name is missing from the distribution, the certificate does not cover it, or DNS does not point at the distribution yet.
- “My change is not live.” The distribution is still deploying, or the old response is still cached.
#CloudFront in system design
- The standard static front end. A private S3 bucket with OAC, a distribution with an ACM certificate and a Route 53 Alias, CachingOptimized, long TTLs and versioned file names. Cheap, fast and safe; most serverless web apps start here.
- One domain for site and API. Path behaviours route
/api/*to an ALB or API Gateway with caching off, and everything else to S3. No CORS, one certificate, one WAF. - Absorbing spikes. Short TTLs (even 1–5 seconds) on hot dynamic pages turn a flood of identical requests into a trickle at the origin. Add Origin Shield for fragile origins.
- Read availability across Regions. CRR keeps a second bucket current; an origin group fails reads over to it.
- Global upload and download in one place. Uploads with PUT through CloudFront or Transfer Acceleration, downloads cached at the edge, and private content with signed URLs (lesson 11.2).
- Know its limits. CloudFront is HTTP-based (HTTP, WebSocket, gRPC). For TCP or UDP applications, static IP addresses as the main requirement, or fast Regional failover of non-HTTP traffic, look at Global Accelerator (lesson 11.4).
#Try it yourself
Create a private bucket, a distribution with OAC, and watch a miss become a hit. Replace the IDs with yours.
# 1. A private bucket with a photo (Block Public Access stays on, the default)
aws s3 mb s3://bazaarbari-images-example --region us-east-1
aws s3 cp saree-42.jpg s3://bazaarbari-images-example/img/saree-42.jpg \
--cache-control "max-age=86400"
# 2. An origin access control that always signs
aws cloudfront create-origin-access-control --origin-access-control-config \
Name=bazaarbari-oac,SigningProtocol=sigv4,SigningBehavior=always,OriginAccessControlOriginType=s3
# 3. The managed cache policies and their IDs
aws cloudfront list-cache-policies --type managed \
--query "CachePolicyList.Items[].CachePolicy.[Id,CachePolicyConfig.Name]" --output table
# 4. Create the distribution from a config file (origin + OAC ID + default behaviour with
# CachingOptimized, ViewerProtocolPolicy redirect-to-https, DefaultRootObject index.html)
aws cloudfront create-distribution --distribution-config file://dist-config.json
aws cloudfront get-distribution --id EDFDVBD6EXAMPLE --query "Distribution.Status" # Deployed?
# 5. Allow only this distribution in the bucket policy (the JSON from the lesson)
aws s3api put-bucket-policy --bucket bazaarbari-images-example --policy file://oac-policy.json
Now look at the headers. Run the same request twice:
curl -sI https://d111111abcdef8.cloudfront.net/img/saree-42.jpg | grep -iE "x-cache|age|x-amz-cf-pop|cache-control"
# x-cache: Miss from cloudfront ← first request
# x-amz-cf-pop: SIN2-P1 ← the PoP that answered (yours will differ)
curl -sI https://d111111abcdef8.cloudfront.net/img/saree-42.jpg | grep -iE "x-cache|age"
# x-cache: Hit from cloudfront
# age: 12 ← seconds since the copy was fetched
# Direct access to the bucket must fail
curl -sI https://bazaarbari-images-example.s3.us-east-1.amazonaws.com/img/saree-42.jpg | head -1
# HTTP/1.1 403 Forbidden
# A different query string is the same object only if the cache policy ignores query strings
curl -sI "https://d111111abcdef8.cloudfront.net/img/saree-42.jpg?fbclid=abc" | grep -i x-cache
Useful extras: aws cloudfront get-distribution-config --id EDFDVBD6EXAMPLE to see every setting (and the ETag you need for update-distribution), aws cloudfront list-distributions --query "DistributionList.Items[].[Id,DomainName,Aliases.Items]", and aws acm request-certificate --domain-name shop.example.com --validation-method DNS --region us-east-1 for the certificate. Delete the distribution when you are done: disable it, wait until it is deployed, then delete-distribution with its ETag.
#Summary
Key takeaways
- CloudFront is AWS’s CDN: a global service that caches content at 750+ edge locations (PoPs) backed by 15 Regional Edge Caches, cutting latency and origin load. It also speeds up dynamic content over the AWS backbone and gives DDoS protection at the edge.
- A request goes viewer → nearest PoP → Regional Edge Cache → (optional Origin Shield) → origin. PUT, POST, PATCH, DELETE and OPTIONS go straight from the PoP to the origin and are never cached.
- A distribution (
d111111abcdef8.cloudfront.net) has origins, origin groups, cache behaviours (path patterns, first match wins, default*last, case-sensitive) and general settings (alternate domain names, certificate, price class, WAF, logs). - Origins: S3 bucket (REST endpoint, secured with OAC), S3 website endpoint (a custom HTTP origin, public, no OAC), any custom HTTP origin (public ALB, EC2, on-premises), VPC origins for private ALB/NLB/EC2.
- OAC: CloudFront signs requests; bucket private; bucket policy allows
cloudfront.amazonaws.comwithAWS:SourceArn= your distribution; KMS key policy for SSE-KMS. OAI is the legacy version (no SSE-KMS, no new Regions). - Cache key = domain + path, plus whatever query strings, headers and cookies the cache policy adds. Include exactly what changes the response. The origin request policy forwards extra values without changing the key.
- TTL: origin’s
max-age/s-maxage/Expires, clamped between the minimum and maximum TTL; default 24 h when the origin says nothing. Expired copies are revalidated (304 →RefreshHit);stale-if-errorserves old copies when the origin is down; errors are cached 10 s by default. - Origin groups: primary and secondary, failover per request on chosen status codes, timeouts or connection failures, GET/HEAD/OPTIONS only. Default 3 × 10 s connection attempts.
- HTTPS: viewer protocol policy (redirect or HTTPS only), origin protocol policy, ACM certificate in us-east-1, SNI (free) vs dedicated IP.
- CloudFront vs CRR: CloudFront = cached copies everywhere for a TTL, for global reads; CRR = full near-real-time copy in chosen Regions, for DR, compliance and Regional low-latency access; faster uploads to one bucket = Transfer Acceleration.
Answer on your own first, then read the explanation, even when you got it right.
Self-checkQuestion
What is Amazon CloudFront?
Self-checkQuestion
Which statement about CloudFront Regional Edge Caches is true?
Self-checkQuestion
Which two of these can be configured directly as a CloudFront origin?
Choose 2
Self-checkQuestion
An online shop in Dhaka keeps its product images in an S3 bucket in us-east-1. Customers across Asia, Europe and North America complain that images load slowly. The bucket must not be publicly accessible. What is the best solution?
Self-checkQuestion
A distribution uses Origin Access Control for its S3 origin. The bucket policy allows Principal Service cloudfront.amazonaws.com the action s3:GetObject on the bucket’s objects, with no Condition. What is the risk?
Self-checkQuestion
After switching an S3 origin to Origin Access Control, objects encrypted with SSE-S3 load, but objects encrypted with SSE-KMS under a customer managed key return 403. What fixes this?
Self-checkQuestion
A team wants to keep using S3 website hosting features (index.html in every folder, routing rules) behind CloudFront, and also wants the bucket to be private with OAC. What should the architect tell them?
Self-checkQuestion
Which two are advantages of Origin Access Control over the legacy origin access identity?
Choose 2
Self-checkQuestion
A distribution has these behaviours in precedence order: /api/* to an ALB, /images/* to an S3 bucket, and the default (*) to a second S3 bucket. A mobile app requests /API/orders. Where does the request go?
Self-checkQuestion
After a new release, customers of a shop occasionally see another customer’s cart. The /api/cart responses come from an ALB through CloudFront. What is the most likely cause and fix?
Self-checkQuestion
The origin needs the CloudFront-Viewer-Country header to write analytics logs, but the response does not depend on the country. How should it be configured?
Self-checkQuestion
A cache behaviour has minimum TTL 0, default TTL 86,400 and maximum TTL 31,536,000 seconds. The origin returns an object with Cache-Control: max-age=600. How long does CloudFront cache it?
Self-checkQuestion
A cache policy has minimum TTL 0, default TTL 300 and maximum TTL 3,600 seconds. The origin sends Cache-Control: max-age=604800 (7 days) on a style sheet. How long is it cached at the edge, and how long in the browser?
Self-checkQuestion
An origin sends no Cache-Control or Expires headers. The behaviour uses a cache policy with minimum TTL 0, default TTL 86,400 and maximum TTL 31,536,000. A price list is changed at the origin one hour after it was first cached. When will all viewers of that PoP see the new list without an invalidation?
Self-checkQuestion
The origin returns Cache-Control: no-store on a personal page, but the behaviour uses the managed CachingOptimized policy. What happens?
Self-checkQuestion
A cached logo expired a minute ago and is requested again. The logo has not changed at the origin. What happens?
Self-checkQuestion
A news site receives 10,000,000 requests a day through CloudFront and has a cache hit ratio of 97% at the edge (assume every miss reaches the origin). How many requests reach the origin per day, and what happens if the hit ratio rises to 99%?
Self-checkQuestion
A viewer in Dhaka has a round-trip time of 240 ms to the origin in us-east-1 and 20 ms to a CloudFront edge location. A new HTTPS connection with TLS 1.3 needs about 3 round trips before the first byte of the response arrives (TCP, TLS, request). Roughly how long until the first byte in each case, if the object is cached at the edge?
Self-checkQuestion
Which two responses does CloudFront never cache?
Choose 2
Self-checkQuestion
An origin group has an S3 bucket as primary and a CRR replica as secondary, with failover status codes 500, 502, 503 and 504. A viewer requests a photo that was deleted from the primary bucket and still exists in the replica. What does the viewer get?
Self-checkQuestion
During a test, the primary origin of an origin group is made unreachable. Users wait about 30 seconds before content arrives from the secondary. Which change shortens this the most?
Self-checkQuestion
An origin group protects a photo-upload application. During an outage of the primary origin, downloads keep working but uploads with PUT fail. Why?
Self-checkQuestion
A live sports stream is packaged just in time by a media origin in eu-west-1. Viewers are worldwide, and the origin is overloaded by many identical requests coming from different Regional Edge Caches. Which CloudFront feature addresses this most directly?
Self-checkQuestion
An engineer requests an ACM certificate for shop.example.com in eu-west-1, where the application runs, and cannot find it when editing the CloudFront distribution. What is wrong?
Self-checkQuestion
Which two statements about HTTPS with CloudFront are true?
Choose 2
Self-checkQuestion
A company stores critical documents in an S3 bucket in us-east-1. A new regulation requires a complete, continuously updated copy in a second Region for disaster recovery. What should the architect use?
Self-checkQuestion
Which statement about S3 Cross-Region Replication, compared with CloudFront, is true?
Self-checkQuestion
Which two statements correct or update the source material for this lesson?
Choose 2
Self-checkQuestion
The shop uploads a new banner, offer.jpg, over the old one in the origin bucket. An hour later many customers still see the old banner. The behaviour uses the default 24-hour TTL. What is the best long-term practice?
Self-checkQuestion
The standard logs of a distribution in front of S3 product photos show a hit ratio of 12%. Most logged URLs look like /img/saree-42.jpg?size=thumb&fbclid=abc123… with a different fbclid each time. The cache policy includes all query strings. What should be changed?