Skip to content

CloudFront

First PublishedByAtif Alam

CloudFront is AWS’s Content Delivery Network (CDN). It caches your content at edge locations worldwide, so users get faster responses from a server near them instead of your origin in a single region.

User (Tokyo) ──► Edge Location (Tokyo) ──cache hit──► Response (fast, ~10ms)
cache miss
Origin (us-east-1) ──► Response (cached at edge for next request)
(S3 / ALB / API GW)
  1. User requests https://cdn.example.com/image.jpg.
  2. CloudFront routes to the nearest edge location.
  3. If the content is cached → return immediately (cache hit).
  4. If not cached → fetch from the origin, cache it, and return to the user (cache miss).
  5. Subsequent requests from the same region are served from cache.
ConceptWhat It Is
DistributionA CloudFront configuration — maps a domain to one or more origins with caching rules
OriginThe source of your content (S3 bucket, ALB, API Gateway, custom HTTP server)
Edge locationA data center in the CloudFront network (~450+ worldwide). Caches content.
Regional edge cacheA larger cache between edge locations and your origin. Catches content evicted from edge.
Cache behaviorRules that match URL patterns and define caching, compression, and protocols
TTLTime to Live — how long content stays in the cache before re-checking the origin
Terminal window
# S3 bucket as origin (static website, images, assets)
Origin: my-bucket.s3.us-east-1.amazonaws.com

Use Origin Access Control (OAC) to keep the S3 bucket private — only CloudFront can read from it:

{
"S3OriginConfig": {
"OriginAccessIdentity": ""
},
"OriginAccessControlId": "E1ABC2DEF3GH"
}

S3 bucket policy:

{
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "cloudfront.amazonaws.com"},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E1ABC2DEF3GH"
}
}
}]
}

The bucket stays private (no public access) but CloudFront can serve its content.

CloudFront ──► ALB (application load balancer) ──► EC2 / ECS

For dynamic content, set short TTLs or use cache policies that respect Cache-Control headers from your application.

CloudFront ──► API Gateway ──► Lambda

Adds edge caching and custom domain to your API. Useful for reducing API Gateway costs (cached responses don’t invoke Lambda).

Route different URL patterns to different origins:

/api/* → API Gateway (dynamic)
/images/* → S3 bucket (static)
/* → ALB (web application)

Cache behaviors match URL patterns and define how CloudFront handles requests.

Every distribution has a default behavior (/*) that catches all requests not matched by other behaviors.

Priority Path Pattern Origin TTL Cache Policy
1 /api/* API Gateway 0 No caching (forward all)
2 /static/* S3 bucket 86400 Cache everything (1 day)
3 /images/* S3 bucket 604800 Cache images (7 days)
default /* ALB 300 Cache with headers (5 min)
SettingWhat It Controls
TTLMinimum, maximum, and default TTL (seconds)
Cache keyWhat determines if a request is a cache hit: headers, query strings, cookies
CompressionGzip/Brotli compression for text content

Important: Including headers, query strings, or cookies in the cache key reduces cache hit rates because different combinations create different cache entries. Only include what actually changes the response.

PatternHeaders in KeyQuery StringsCookiesTTL
Static assetsNoneNoneNone1–30 days
Dynamic pagesAccept-LanguageAllSession cookie0–5 min
API responsesAuthorizationAllNone0 (no caching)
ImagesNoneNoneNone7–30 days

CloudFront provides free HTTPS with AWS Certificate Manager (ACM):

Terminal window
# Request a certificate (must be in us-east-1 for CloudFront)
aws acm request-certificate \
--domain-name cdn.example.com \
--validation-method DNS \
--region us-east-1
# Validate via DNS (add the CNAME record ACM provides)
SettingOptions
Viewer protocolHTTP and HTTPS, Redirect HTTP to HTTPS, HTTPS only
Origin protocolHTTP only, HTTPS only, Match viewer
SSL certificateDefault CloudFront cert (*.cloudfront.net), or custom cert from ACM
Security policyTLS version minimum (TLSv1.2 recommended)

Always use Redirect HTTP to HTTPS for the viewer and HTTPS only for the origin when possible.

For certificate lifecycle, rotation, and attaching ACM to other services (ALB, API Gateway), see TLS and Certificates.

cdn.example.com ──Route 53 alias──► CloudFront distribution ──► Origins
  1. Request an ACM certificate for cdn.example.com (in us-east-1).
  2. Add cdn.example.com as an alternate domain name (CNAME) on the distribution.
  3. Create a Route 53 alias record pointing cdn.example.com to the distribution.

When you update content at the origin, cached copies at edge locations still serve the old version until the TTL expires. Invalidation forces CloudFront to re-fetch from the origin.

Terminal window
# Invalidate specific paths
aws cloudfront create-invalidation --distribution-id E1ABC2DEF3GH \
--paths "/index.html" "/css/*"
# Invalidate everything
aws cloudfront create-invalidation --distribution-id E1ABC2DEF3GH \
--paths "/*"
  • First 1,000 invalidation paths per month are free; $0.005 per path after that.
  • Invalidation takes 1–5 minutes to propagate to all edge locations.

Better approach: Use versioned file names (app.v2.js, style.abc123.css) with long TTLs. No invalidation needed — new file name = new cache entry. Most build tools (Webpack, Vite) do this automatically.

Run code at the edge for request/response manipulation:

CloudFront FunctionsLambda@Edge
RuntimeJavaScript (lightweight)Node.js, Python
Execution time< 1msUp to 30 seconds
TriggersViewer request/responseViewer + origin request/response
Network accessNoYes
CostVery lowHigher
Use caseURL rewrites, header manipulation, simple redirectsAuth, A/B testing, dynamic content at edge
function handler(event) {
var request = event.request;
var uri = request.uri;
// Add index.html for directory requests (SPA support)
if (uri.endsWith('/')) {
request.uri += 'index.html';
} else if (!uri.includes('.')) {
request.uri += '/index.html';
}
return request;
}
exports.handler = async (event) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
const token = headers.authorization?.[0]?.value;
if (!token || !isValidToken(token)) {
return {
status: '401',
body: 'Unauthorized',
};
}
return request; // continue to origin
};
User ──► CloudFront (HTTPS) ──► S3 bucket (private, OAC)
└── CloudFront Function: SPA URL rewrite
User ──► CloudFront ──► /api/* ──► ALB ──► ECS
──► /static/* ──► S3
──► /* ──► S3 (SPA index.html)
User (distant region) ──► CloudFront edge ──► API Gateway ──► Lambda

Even without caching, CloudFront reduces latency via optimized AWS backbone routing and persistent connections to the origin.

MetricWhat It Shows
RequestsTotal requests (hit + miss)
BytesDownloadedData transferred to viewers
CacheHitRatePercentage of requests served from cache
4xxErrorRateClient errors (404, 403)
5xxErrorRateOrigin errors

Access logs can be sent to S3 for detailed analysis (client IP, request path, cache status, response time).

  • CloudFront caches content at 450+ edge locations worldwide — reducing latency and origin load.
  • Use Origin Access Control to keep S3 buckets private while serving content through CloudFront.
  • Set long TTLs for static assets and use versioned file names instead of invalidation.
  • Use cache behaviors to route different URL patterns to different origins with different caching rules.
  • CloudFront Functions handle simple edge logic (rewrites, redirects); Lambda@Edge handles complex logic (auth, dynamic content).
  • Always use HTTPS with a free ACM certificate.