Amazon CloudFront is AWS's global content delivery network (CDN). It caches static and dynamic content at 600+ edge locations and regional edge caches, terminates TLS close to users, and can execute lightweight code at the edge — reducing latency and offloading traffic from origin servers.
Cache-Control headers at the origin; CloudFront honors them.Creating a CloudFront distribution in front of an S3 bucket with Origin Access Control via AWS CLI:
# 1) Create an Origin Access Control (OAC) for S3
OAC_ID=$(aws cloudfront create-origin-access-control \
--origin-access-control-config '{
"Name": "site-oac",
"OriginAccessControlOriginType": "s3",
"SigningBehavior": "always",
"SigningProtocol": "sigv4"
}' --query 'OriginAccessControl.Id' --output text)
# 2) Create distribution
aws cloudfront create-distribution --distribution-config '{
"CallerReference": "site-2026-04-25",
"Comment": "Static site",
"DefaultRootObject": "index.html",
"Origins": {"Quantity": 1, "Items": [{
"Id": "s3-site",
"DomainName": "my-site.s3.us-west-2.amazonaws.com",
"OriginAccessControlId": "'"$OAC_ID"'",
"S3OriginConfig": {"OriginAccessIdentity": ""}
}]},
"DefaultCacheBehavior": {
"TargetOriginId": "s3-site",
"ViewerProtocolPolicy": "redirect-to-https",
"Compress": true,
"CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6"
},
"Enabled": true
}'
A simple CloudFront Function that strips tracking query params to improve cache hit ratio:
function handler(event) {
var req = event.request;
var qs = req.querystring;
var stripped = {};
var skip = ['utm_source','utm_medium','utm_campaign','gclid','fbclid'];
for (var key in qs) {
if (skip.indexOf(key) === -1) stripped[key] = qs[key];
}
req.querystring = stripped;
return req;
}
CloudFront Functions run in a lightweight V8 isolate at viewer-request and viewer-response only — sub-millisecond execution, much cheaper, ideal for header rewrites, redirects, A/B routing. Lambda@Edge is full Node.js or Python at four event hooks (viewer request/response, origin request/response), supports network calls and AWS SDK, but adds 30–100 ms latency and costs more. Use CloudFront Functions first; reach for Lambda@Edge when you need its capabilities.
Use Origin Access Control (OAC, the modern replacement for OAI). Configure the bucket policy to allow GetObject only from your distribution ARN, then enable S3 Block Public Access on the bucket. Optionally add SigV4 signed origin requests, restrict viewer access with signed URLs/cookies, and put AWS WAF in front of the distribution.
Invalidation tells CloudFront to discard a cached object across all edges — useful but slow (minutes) and metered beyond 1,000/month. Versioned filenames (app.a8f3d.js) make every release a unique URL with a long Cache-Control: max-age; old versions naturally age out and you never invalidate. Versioning is the production-grade pattern for SPAs and assets; invalidation is the emergency tool.
Restrict to cheaper price classes if your audience is regional, raise cache hit ratio (compress objects, set long max-age on hashed assets, normalize query strings, use Origin Shield), serve large downloads from regions with lower egress pricing, use signed URLs to prevent hotlinking, and avoid Lambda@Edge on every request when a CloudFront Function suffices.
AWS WAF can be attached directly to a CloudFront distribution, applying L7 rules (rate limiting, geo-blocking, managed bot rules, OWASP rule sets) at the edge before traffic reaches your origin. AWS Shield Standard (free) is automatic; Shield Advanced (paid) adds 24/7 DDoS response team support, cost protection during attacks, and additional metrics — typically only needed for high-profile workloads.
Origin Shield is an extra regional cache layer between the edge POPs and your origin. Without it, a cache miss at any of 600+ POPs goes back to origin; with it, misses funnel through one shield region first — dramatically increasing the chance of a cache hit and reducing origin load. Most useful for medium-traffic origins or origins in a single region with global viewers.