Skip to content

Amazon CloudFront - CDN

Chapter 14: Amazon CloudFront - CDN Service

Section titled “Chapter 14: Amazon CloudFront - CDN Service”

Amazon CloudFront is a fast content delivery network (CDN) service that securely delivers data, videos, applications, and APIs to viewers globally with low latency and high transfer speeds.

CloudFront Overview
+------------------------------------------------------------------+
| |
| +------------------------+ |
| | CloudFront | |
| | (CDN) | |
| +------------------------+ |
| | |
| +---------------------+---------------------+ |
| | | | |
| v v v |
| +----------+ +----------+ +----------+ |
| | Edge | | Regional | | Origin | |
| | Locations| | Edge | | Servers | |
| | | | Caches | | | |
| +----------+ +----------+ +----------+ |
| |
| Edge Locations: 400+ locations worldwide |
| Regional Edge Caches: Intermediate caching layer |
| Origins: S3, ALB, API Gateway, Custom HTTP |
| |
+------------------------------------------------------------------+

CloudFront Request Flow
+------------------------------------------------------------------+
| |
| User Request |
| | |
| v |
| +----------+ |
| | Edge | <-- Closest to user |
| | Location | (Low latency) |
| +----------+ |
| | |
| | Cache Check |
| v |
| +----------+ |
| | Cache | |
| | HIT? | |
| +----------+ |
| | |
| +----+----+ |
| | | |
| v v |
| [YES] [NO] |
| | | |
| v v |
| Return +----------+ |
| Cached | Regional | |
| Content | Edge | |
| | Cache | |
| +----------+ |
| | |
| v |
| +----------+ |
| | Origin | <-- S3, ALB, etc. |
| | Server | |
| +----------+ |
| | |
| v |
| Cache & Return |
| |
+------------------------------------------------------------------+
CloudFront Cache Hierarchy
+------------------------------------------------------------------+
| |
| Edge Locations (400+) |
| +----------------------------------------------------------+ |
| | | |
| | - Located in major cities | |
| | - First point of contact for users | |
| | - Serves cached content | |
| | - Forwards requests to Regional Edge if cache miss | |
| | | |
| +----------------------------------------------------------+ |
| | |
| v |
| Regional Edge Caches (13) |
| +----------------------------------------------------------+ |
| | | |
| | - Located in AWS regions | |
| | - Larger cache capacity | |
| | - Reduces origin load | |
| | - Caches content from origins | |
| | | |
| +----------------------------------------------------------+ |
| | |
| v |
| Origins |
| +----------------------------------------------------------+ |
| | | |
| | - S3 buckets | |
| | - Application Load Balancer | |
| | - API Gateway | |
| | - Custom HTTP origins | |
| | - MediaStore, MediaPackage | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

Web Distribution Architecture
+------------------------------------------------------------------+
| |
| Distribution Configuration |
| +----------------------------------------------------------+ |
| | | |
| | Origin Settings: | |
| | +----------------------------------------------------+ | |
| | | Origin Domain Name: example.com | | |
| | | Origin Protocol Policy: | | |
| | | - HTTP Only | | |
| | | - HTTPS Only | | |
| | | - Match Viewer | | |
| | | Origin SSL Protocols: TLS 1.2 | | |
| | +----------------------------------------------------+ | |
| | | |
| | Default Cache Behavior: | |
| | +----------------------------------------------------+ | |
| | | Path Pattern: Default (*) | | |
| | | Viewer Protocol Policy: | | |
| | | - Allow HTTP and HTTPS | | |
| | | - Redirect HTTP to HTTPS | | |
| | | - HTTPS Only | | |
| | | Allowed Methods: GET, HEAD, OPTIONS | | |
| | | Cache Policy ID: CachingOptimized | | |
| | +----------------------------------------------------+ | |
| | | |
| | Additional Behaviors: | |
| | +----------------------------------------------------+ | |
| | | /api/* -> ALB origin (No cache) | | |
| | | /static/* -> S3 origin (Cache optimized) | | |
| | | /images/* -> S3 origin (Cache optimized) | | |
| | +----------------------------------------------------+ | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
RTMP Distribution (Deprecated)
+------------------------------------------------------------------+
| |
| Note: RTMP distributions are deprecated. |
| Use CloudFront with MediaPackage for streaming. |
| |
| Modern Streaming Options: |
| +----------------------------------------------------------+ |
| | | |
| | 1. Live Streaming: | |
| | - AWS Elemental MediaLive | |
| | - AWS Elemental MediaPackage | |
| | - CloudFront | |
| | | |
| | 2. Video on Demand: | |
| | - S3 (video storage) | |
| | - CloudFront (delivery) | |
| | - AWS Elemental MediaConvert | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

Cache Policy Configuration
+------------------------------------------------------------------+
| |
| Managed Cache Policies |
| +----------------------------------------------------------+ |
| | | |
| | Policy Name | Use Case | |
| |--------------------------|-------------------------------| |
| | CachingOptimized | Static content, high cache | |
| | CachingOptimizedFor | Static content, uncompressed | |
| | UncompressedObjects | | |
| | CachingDisabled | Dynamic content, no cache | |
| | Elemental-MediaPackage | Video streaming | |
| | Amplify | AWS Amplify apps | |
| | | |
| +----------------------------------------------------------+ |
| |
| Custom Cache Policy Settings |
| +----------------------------------------------------------+ |
| | | |
| | TTL Settings: | |
| | - Minimum TTL: 0 seconds | |
| | - Maximum TTL: 31536000 seconds (1 year) | |
| | - Default TTL: 86400 seconds (1 day) | |
| | | |
| | Cache Key Settings: | |
| | - Query strings: None, Whitelist, All | |
| | - Headers: None, Whitelist, All | |
| | - Cookies: None, Whitelist, All | |
| | | |
| | Response Headers: | |
| | - Cache-Control | |
| | - Expires | |
| | - Last-Modified | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Origin Request Policy
+------------------------------------------------------------------+
| |
| Purpose: Control what is forwarded to origin |
| |
| Managed Policies |
| +----------------------------------------------------------+ |
| | | |
| | Policy Name | Forwards | |
| |--------------------------|-------------------------------| |
| | AllViewerExceptHostHeader| All viewer headers except | |
| | | Host | |
| | AllViewerAndForward | All viewer + whitelist | |
| | Headers | headers | |
| | AllViewer | All viewer headers | |
| | CORS-CustomOrigin | CORS headers for custom | |
| | | origins | |
| | CORS-S3Origin | CORS headers for S3 | |
| | | |
| +----------------------------------------------------------+ |
| |
| Difference: Cache Policy vs Origin Request Policy |
| +----------------------------------------------------------+ |
| | | |
| | Cache Policy: | |
| | - Determines cache key | |
| | - Affects caching behavior | |
| | - Applied first | |
| | | |
| | Origin Request Policy: | |
| | - Determines what's forwarded to origin | |
| | - Only on cache miss | |
| | - Doesn't affect cache key | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

CloudFront SSL/TLS
+------------------------------------------------------------------+
| |
| Viewer Certificate (Edge to Viewer) |
| +----------------------------------------------------------+ |
| | | |
| | Options: | |
| | 1. CloudFront Default Certificate (*.cloudfront.net) | |
| | 2. Custom Certificate (ACM or IAM) | |
| | | |
| | ACM Certificate Requirements: | |
| | - Must be in us-east-1 region | |
| | - Must be validated (DNS or Email) | |
| | - Supports wildcard (*.example.com) | |
| | | |
| | SSL Protocols: | |
| | - TLS 1.2 (recommended) | |
| | - TLS 1.1 (deprecated) | |
| | - TLS 1.0 (deprecated) | |
| | | |
| +----------------------------------------------------------+ |
| |
| Origin Certificate (CloudFront to Origin) |
| +----------------------------------------------------------+ |
| | | |
| | Options: | |
| | 1. Custom Origin: Use certificate from CA | |
| | 2. S3 Origin: No certificate needed | |
| | | |
| | Protocol Policy: | |
| | - HTTP Only | |
| | - HTTPS Only | |
| | - Match Viewer | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
CloudFront Functions vs Lambda@Edge
+------------------------------------------------------------------+
| |
| CloudFront Functions |
| +----------------------------------------------------------+ |
| | | |
| | Runtime: JavaScript (ECMAScript 5.1 compliant) | |
| | Execution: Edge locations | |
| | Use Cases: | |
| | - URL rewrites/redirects | |
| | - Cache key manipulation | |
| | - Header manipulation | |
| | - Request authentication (simple) | |
| | | |
| | Limits: | |
| | - 1 MB memory | |
| | - 1 ms execution time | |
| | | |
| | Cost: Lower than Lambda@Edge | |
| | | |
| +----------------------------------------------------------+ |
| |
| Lambda@Edge |
| +----------------------------------------------------------+ |
| | | |
| | Runtime: Node.js, Python | |
| | Execution: Regional edge caches | |
| | Use Cases: | |
| | - Complex request/response processing | |
| | - A/B testing | |
| | - Dynamic content generation | |
| | - Access control (complex) | |
| | | |
| | Limits: | |
| | - 128 MB - 3008 MB memory | |
| | - 5-900 seconds execution time | |
| | | |
| | Cost: Higher than CloudFront Functions | |
| | | |
| +----------------------------------------------------------+ |
| |
| Trigger Points: |
| +----------------------------------------------------------+ |
| | | |
| | Viewer Request: After CloudFront receives request | |
| | Viewer Response: Before CloudFront sends response | |
| | Origin Request: Before forwarding to origin | |
| | Origin Response: After receiving from origin | |
| | | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
CloudFront + AWS WAF
+------------------------------------------------------------------+
| |
| Web ACL Configuration |
| +----------------------------------------------------------+ |
| | | |
| | Request Flow: | |
| | | |
| | User Request | |
| | | | |
| | v | |
| | +----------+ | |
| | | CloudFront| | |
| | +----------+ | |
| | | | |
| | v | |
| | +----------+ | |
| | | AWS WAF | <-- Inspect request | |
| | | Web ACL | Apply rules | |
| | +----------+ | |
| | | | |
| | +----+----+ | |
| | | | | |
| | v v | |
| | ALLOW BLOCK | |
| | | | | |
| | v v | |
| | Origin 403 Response | |
| | | |
| +----------------------------------------------------------+ |
| |
| Common Rules: |
| +----------------------------------------------------------+ |
| | - IP address blocking/allowing | |
| | - Geographic restrictions | |
| | - Rate-based limiting (DDoS protection) | |
| | - SQL injection protection | |
| | - XSS protection | |
| | - Bot control | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

Signed URLs and Cookies
+------------------------------------------------------------------+
| |
| Use Case: Restrict access to content |
| |
| Signed URL |
| +----------------------------------------------------------+ |
| | | |
| | Format: | |
| | https://d123.cloudfront.net/video.mp4? | |
| | Expires=1234567890& | |
| | Signature=xxx& | |
| | Key-Pair-Id=APKA... | |
| | | |
| | Components: | |
| | - Expires: Expiration timestamp | |
| | - Signature: Signed policy | |
| | - Key-Pair-Id: CloudFront key pair ID | |
| | | |
| | Use When: | |
| | - Individual file access | |
| | - Download links | |
| | - Temporary access | |
| | | |
| +----------------------------------------------------------+ |
| |
| Signed Cookies |
| +----------------------------------------------------------+ |
| | | |
| | Cookies Set: | |
| | - CloudFront-Expires | |
| | - CloudFront-Signature | |
| | - CloudFront-Key-Pair-Id | |
| | | |
| | Use When: | |
| | - Multiple files | |
| | - Video streaming (HLS) | |
| | - Website access | |
| | | |
| +----------------------------------------------------------+ |
| |
| Trusted Signers: |
| +----------------------------------------------------------+ |
| | - Create CloudFront key pair | |
| | - Add trusted signer to distribution | |
| | - Generate signed URLs/cookies with private key | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+
Origin Access Control (OAC)
+------------------------------------------------------------------+
| |
| Purpose: Secure S3 origin access |
| |
| Architecture |
| +----------------------------------------------------------+ |
| | | |
| | User Request | |
| | | | |
| | v | |
| | +----------+ | |
| | | CloudFront| | |
| | | (OAC) | | |
| | +----------+ | |
| | | | |
| | | Signed request | |
| | v | |
| | +----------+ | |
| | | S3 Bucket| <-- Bucket policy allows CloudFront | |
| | | (Private)| No public access | |
| | +----------+ | |
| | | |
| +----------------------------------------------------------+ |
| |
| S3 Bucket Policy: |
| +----------------------------------------------------------+ |
| | { | |
| | "Version": "2012-10-17", | |
| | "Statement": [{ | |
| | "Sid": "AllowCloudFrontAccess", | |
| | "Effect": "Allow", | |
| | "Principal": { | |
| | "Service": "cloudfront.amazonaws.com" | |
| | }, | |
| | "Action": "s3:GetObject", | |
| | "Resource": "arn:aws:s3:::bucket/*", | |
| | "Condition": { | |
| | "StringEquals": { | |
| | "AWS:SourceArn": "arn:aws:cloudfront::..." | |
| | } | |
| | } | |
| | }] | |
| | } | |
| +----------------------------------------------------------+ |
| |
| OAC vs OAI (Origin Access Identity): |
| +----------------------------------------------------------+ |
| | OAC: Newer, supports all S3 operations | |
| | OAI: Legacy, supports only GET | |
| +----------------------------------------------------------+ |
| |
+------------------------------------------------------------------+

# ============================================================
# CloudFront Distribution
# ============================================================
# S3 Origin (Private)
resource "aws_s3_bucket" "static" {
bucket = "static-content-example"
}
resource "aws_s3_bucket_public_access_block" "static" {
bucket = aws_s3_bucket.static.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# Origin Access Control
resource "aws_cloudfront_origin_access_control" "main" {
name = "oac-main"
description = "OAC for S3 origin"
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
# CloudFront Distribution
resource "aws_cloudfront_distribution" "main" {
enabled = true
is_ipv6_enabled = true
comment = "Main distribution"
default_root_object = "index.html"
# S3 Origin
origin {
domain_name = aws_s3_bucket.static.bucket_regional_domain_name
origin_access_control_id = aws_cloudfront_origin_access_control.main.id
origin_id = "s3-origin"
}
# ALB Origin (for API)
origin {
domain_name = aws_lb.main.dns_name
origin_id = "alb-origin"
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "https-only"
origin_ssl_protocols = ["TLSv1.2"]
}
}
# Default Cache Behavior (S3)
default_cache_behavior {
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "s3-origin"
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "redirect-to-https"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
# API Cache Behavior
ordered_cache_behavior {
path_pattern = "/api/*"
allowed_methods = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "DELETE", "PATCH"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "alb-origin"
forwarded_values {
query_string = true
headers = ["Authorization", "Content-Type"]
cookies {
forward = "all"
}
}
viewer_protocol_policy = "https-only"
min_ttl = 0
default_ttl = 0
max_ttl = 0
}
# Static Content Cache Behavior
ordered_cache_behavior {
path_pattern = "/static/*"
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "s3-origin"
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "redirect-to-https"
min_ttl = 0
default_ttl = 86400
max_ttl = 31536000
}
# Price Class
price_class = "PriceClass_100" # Use only edge locations in US, Europe
# Viewer Certificate
viewer_certificate {
acm_certificate_arn = aws_acm_certificate.main.arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
# Geographic Restrictions (optional)
restrictions {
geo_restriction {
restriction_type = "whitelist"
locations = ["US", "CA", "GB", "DE", "FR"]
}
}
# Custom Error Response
custom_error_response {
error_code = 404
response_code = 200
response_page_path = "/index.html"
}
tags = {
Name = "main-distribution"
}
}
# S3 Bucket Policy for CloudFront
resource "aws_s3_bucket_policy" "cloudfront" {
bucket = aws_s3_bucket.static.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AllowCloudFrontAccess"
Effect = "Allow"
Principal = {
Service = "cloudfront.amazonaws.com"
}
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.static.arn}/*"
Condition = {
StringEquals = {
"AWS:SourceArn" = aws_cloudfront_distribution.main.arn
}
}
}
]
})
}
# ============================================================
# CloudFront Function
# ============================================================
resource "aws_cloudfront_function" "url_rewrite" {
name = "url-rewrite"
runtime = "cloudfront-js-1.0"
comment = "URL rewrite for SPA"
publish = true
code = <<-EOT
function handler(event) {
var request = event.request;
var uri = request.uri;
// Check if URI ends with /
if (uri.endsWith('/')) {
request.uri += 'index.html';
}
// Check if URI doesn't have extension
else if (!uri.includes('.')) {
request.uri += '/index.html';
}
return request;
}
EOT
}
# Associate function with distribution
resource "aws_cloudfront_distribution" "main" {
# ... other config ...
default_cache_behavior {
# ... other config ...
function_association {
event_type = "viewer-request"
function_arn = aws_cloudfront_function.url_rewrite.arn
}
}
}
# ============================================================
# Lambda@Edge
# ============================================================
resource "aws_lambda_function" "edge" {
filename = "edge-function.zip"
function_name = "edge-function"
role = aws_iam_role.edge.arn
handler = "index.handler"
runtime = "nodejs18.x"
publish = true # Required for Lambda@Edge
}
# IAM Role for Lambda@Edge
resource "aws_iam_role" "edge" {
name = "lambda-edge-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = [
"lambda.amazonaws.com",
"edgelambda.amazonaws.com"
]
}
}
]
})
}

CloudFront is your global performance and security layer. SREs use it for caching, DDoS protection (with Shield/WAF), and deploying frontend apps. Cache invalidation during deployments is a critical operational task.


~/bin/cf-deploy.sh
# Cache invalidation during deployment
#!/bin/bash
set -euo pipefail
DIST_ID="$1"
echo "🚀 Invalidating CloudFront cache..."
INVALIDATION_ID=$(aws cloudfront create-invalidation \
--distribution-id "$DIST_ID" \
--paths "/*" \
--query 'Invalidation.Id' --output text)
echo "Invalidation ID: $INVALIDATION_ID"
# Wait for invalidation
aws cloudfront wait invalidation-completed \
--distribution-id "$DIST_ID" \
--id "$INVALIDATION_ID"
echo "✅ Cache invalidated"
# Monitor cache hit ratio
aws cloudwatch get-metric-statistics \
--namespace AWS/CloudFront \
--metric-name CacheHitRate \
--dimensions Name=DistributionId,Value="$DIST_ID" \
--start-time "$(date -d '1 hour ago' -u +%Y-%m-%dT%H:%M:%S)" \
--end-time "$(date -u +%Y-%m-%dT%H:%M:%S)" \
--period 300 --statistics Average \
--query 'Datapoints[*].{Time:Timestamp,HitRate:Average}' --output table

IssueCauseSolution
Stale content after deployCache not invalidatedCreate invalidation for changed paths
High origin loadLow cache hit ratioReview cache policy, increase TTL for static assets
502 Bad GatewayOrigin unreachableCheck origin health, security groups, protocol policy
Custom domain not workingACM cert not in us-east-1ACM certificates for CF must be in us-east-1
CORS errorsOrigin request policy missingAdd CORS headers via origin request policy

  1. Q: How would you deploy a SPA (React/Vue) with CloudFront?

    • A: S3 for static hosting (private, no website endpoint needed), CloudFront with OAC for secure S3 access, custom error response (404→200→/index.html) for client-side routing, ACM cert in us-east-1 for custom domain, CloudFront Function for URL rewriting. Deploy: sync to S3 then invalidate CF cache.
  2. Q: CloudFront Functions vs Lambda@Edge — when to use each?

    • A: CF Functions: lightweight (JS only, 1ms, 1MB), runs at all 400+ edge locations — use for URL rewrites, header manipulation, simple auth. Lambda@Edge: heavier (Node/Python, up to 30s), runs at 13 regional edges — use for A/B testing, complex auth, dynamic content generation.

Exam Tip

  1. Edge Locations: 400+ globally, separate from regions
  2. Regional Edge Caches: Intermediate layer, larger cache
  3. Origins: S3, ALB, API Gateway, Custom HTTP
  4. Cache Behaviors: Path patterns route to different origins
  5. TTL: Min, Max, Default - controlled by cache policy
  6. OAC vs OAI: OAC is newer, supports all S3 operations
  7. Signed URLs/Cookies: Restrict access with expiration
  8. Lambda@Edge: Node.js/Python, runs at regional edge
  9. CloudFront Functions: JavaScript, runs at edge, faster
  10. ACM Certificate: Must be in us-east-1 for CloudFront

Chapter 15: AWS Transit Gateway - Network Hub


Last Updated: March 2026