Mid-level 11 min · March 06, 2026
AWS CloudFront and Route 53

CloudFront Cache — Why Deploys Never Reach Users

Old app.js served for 24 hours after deploy because cache TTL hadn't expired.

N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Everything here is grounded in real deployments.

Follow
Production
production tested
May 24, 2026
last updated
1,554
articles · all by Naren
 ● Production Incident 🔎 Debug Guide ⚙ Triage Commands
Quick Answer
  • CloudFront caches at 450+ edge locations, serving content from nearest edge. Route 53 provides latency-based, geolocation, and failover DNS routing.
  • Together: Route 53 sends users to closest CloudFront edge; CloudFront serves cached content, falling back to origin only on cache miss.
  • Performance impact: 100ms latency reduction improves conversion by 1% (Amazon internal data). Global CDN cuts load time from 2.5s to 400ms.
  • Production trap: Cache invalidation costs money and takes minutes. Versioned filenames (app.abc123.js) are free and instant.
  • Hidden killer: ACM certificates for CloudFront MUST be in us-east-1. Cert in eu-west-1 = distribution fails to create.
  • Biggest mistake: Forgetting health checks on Route 53 failover records. Without them, primary fails, traffic never switches.
✦ Definition~90s read
What is AWS CloudFront and Route 53?

CloudFront is AWS's content delivery network (CDN) that caches static and dynamic content at 600+ edge locations globally. Route 53 is AWS's DNS service that routes users to the nearest CloudFront distribution via latency-based or geolocation routing.

Imagine your website is a pizza restaurant with one kitchen in New York.

Together, they form the backbone of high-performance web delivery on AWS. The problem they solve is simple: without a CDN, every user request hits your origin server directly, causing high latency, origin load, and single points of failure. CloudFront absorbs traffic at the edge, while Route 53 ensures users reach the optimal edge endpoint.

The catch—and the reason deploys 'never reach users'—is that CloudFront caches aggressively by default. When you deploy new code or assets, users still see the old cached version until the TTL expires or you manually invalidate the cache. This is the single most common production surprise for teams new to AWS.

Alternatives exist: you could skip the CDN and use Route 53 directly with ALB or EC2, but you'd lose global performance and DDoS protection. For low-latency, high-traffic sites, CloudFront + Route 53 is the standard. For internal apps or low-traffic APIs, it's overkill—use CloudFront only when you need edge caching, TLS termination at the edge, or WAF integration.

Real-world numbers: a properly configured CloudFront distribution can achieve 95%+ cache hit ratios, reducing origin load by orders of magnitude and cutting latency from 200ms to under 20ms for distant users. The trade-off is cache invalidation cost—$0.005 per path per month, which adds up if you invalidate aggressively.

Production teams typically set TTLs to 24 hours for stable assets and use versioned filenames (e.g., app.abc123.js) to avoid invalidation entirely.

Plain-English First

Imagine your website is a pizza restaurant with one kitchen in New York. If someone in Tokyo orders a pizza, it takes forever to arrive. CloudFront is like opening pizza pickup counters all over the world — customers grab a hot slice from the nearest counter instead of waiting for New York. Route 53 is the smart GPS that tells every customer exactly which counter is closest to them. Together, they make sure your website loads fast no matter where on Earth your user is sitting.

Developers love the shiny new feature. They hate the 12-second DNS propagation, the SSL mismatch errors, and the fact that their global users see a 5-second load time because CloudFront skipped Route 53’s routing policy. Without a tight CloudFront and Route 53 handshake, your deployment is a gamble—users get routed to the wrong region, cache misses stack up, and origin traffic bleeds cash. This stack isn’t just about speed; it’s the critical bridge between DNS resolution and edge distribution that, when configured wrong, silently kills your user experience and your budget.

Why CloudFront + Route53 Means Your Deploy Never Reaches Users

CloudFront is a content delivery network (CDN) that caches responses at edge locations worldwide. Route53 is AWS's DNS service. Together, they form the front door of most production web applications. The core mechanic: Route53 resolves your domain to a CloudFront distribution, and CloudFront serves cached content from edge caches — meaning requests never hit your origin server unless the cache misses. This is great for latency and origin load, but catastrophic for deployments: after you push new code, users still see the old cached version until the TTL expires or you explicitly invalidate the cache. CloudFront caches based on the URL and query string by default — not on headers like version or ETag unless you configure it. The default TTL is 24 hours. That means a deploy at 10 AM won't be visible to most users until the next day. You must either set shorter TTLs (e.g., 1 minute) for dynamic paths or use cache invalidation (costs money per path) or versioned URLs (e.g., /static/v2/main.js). The practical takeaway: CloudFront is not transparent — it actively hides your changes from users until you tell it to stop.

Default TTL is a trap
CloudFront's default TTL of 24 hours means your deploy is invisible for a full day unless you explicitly invalidate or version your assets.
Production Insight
Team deploys a hotfix for a payment bug at 3 PM, but CloudFront still serves the broken JS bundle until the next day — users see '500' errors for 18 hours.
Symptom: after deploy, some users see old behavior, others see new — depending on which edge location they hit and whether their cache expired.
Rule of thumb: always version static assets (e.g., /static/v123/main.js) and set TTL to 0 for API paths under /api/.
Key Takeaway
CloudFront caches aggressively by default — your deploy is invisible until cache expires or is invalidated.
Use versioned URLs for static assets to bypass cache entirely on each deploy.
For dynamic content, set TTL to 0 or use cache-control headers — never rely on default TTLs.
CloudFront Cache Deploy Flow THECODEFORGE.IO CloudFront Cache Deploy Flow How Route53 and CloudFront delay deployment propagation Route53 DNS Query Latency/geolocation routing to edge CloudFront Edge Cache Cached content served to users Deploy Update New origin content pushed Cache Invalidation Manual or automatic purge needed User Receives Update Only after cache refresh ⚠ Cache invalidation not triggered by deploy Always invalidate CloudFront cache after origin update THECODEFORGE.IO
thecodeforge.io
CloudFront Cache Deploy Flow
Aws Cloudfront Route53

CloudFront + Route 53 Integration — The Global Delivery Stack

CloudFront and Route 53 solve different problems. CloudFront is a CDN — it caches content at edge locations and serves users from the nearest edge. Route 53 is DNS — it translates domain names to IP addresses, but AWS's version goes far beyond basic DNS with latency-based, geolocation, weighted, and failover routing.

Together, they form the global delivery stack: Route 53 directs the user's DNS query to the closest CloudFront edge (latency-based routing). The user's browser then connects to that CloudFront edge. CloudFront serves the content from its cache if available; otherwise, it fetches from the origin (S3, EC2, ALB, or custom HTTP server).

Why this matters: A SaaS company hosted only in us-east-1 with no CloudFront saw 2.5s load times in Australia. After adding CloudFront with a simple cache-all policy, load times dropped to 400ms. That's not theoretical — it's the kind of improvement that directly impacts revenue.

The real value isn't just speed. It's resilience. When your origin goes down in us-east-1, CloudFront can still serve stale content from its cache for hours. That's the difference between a 5-minute outage and a non-event. Route 53's health checks then detect the failure and reroute new requests to a replica in another region.

io/thecodeforge/cloudfront_invalidation.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
# io.thecodeforge/cloudfront_invalidation.sh
# Create CloudFront invalidation for a distribution

DISTRIBUTION_ID="E1ABC123XYZ"

# Invalidate entire distribution (use carefully in production)
echo "Creating invalidation for distribution: ${DISTRIBUTION_ID}"
aws cloudfront create-invalidation \
  --distribution-id "${DISTRIBUTION_ID}" \
  --paths '/*'

# Invalidate specific files or directories
aws cloudfront create-invalidation \
  --distribution-id "${DISTRIBUTION_ID}" \
  --paths '/index.html' '/static/css/*' '/static/js/app.js'

# Check cache hit ratio from CloudWatch
aws cloudwatch get-metric-statistics \
  --namespace AWS/CloudFront \
  --metric-name CacheHitRate \
  --statistics Average \
  --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
  --period 3600 \
  --dimensions Name=DistributionId,Value="${DISTRIBUTION_ID}"

echo "Invalidation created. Use 'aws cloudfront get-invalidation --id <ID>' to track progress."
Output
Invalidation created: I123ABC
Status: InProgress
Cache hit ratio (last hour): 94.2%
Forge Tip: Use Versioned Filenames to Avoid Invalidation
Invalidation takes minutes and costs per path. Versioned filenames (app.abc123.js) create a new URL on each deploy — cache miss is automatic. Set long TTL (1 year) and never invalidate. This is the industry standard for static assets.
Production Insight
A team wasted $500/month on CloudFront invalidations because they invalidated the entire distribution (/*) after every deploy.
100 deploys × $0.005 per path × thousands of files = large bill.
Fix: switched to versioned filenames. New file → new URL → no invalidation needed.
Rule: invalidation is for emergencies and dynamic content only. For static assets, versioning is free and instant.
Key Takeaway
CloudFront = CDN (edge caching). Route 53 = DNS (smart routing).
Together they form the global delivery stack: Route 53 routes to nearest edge, CloudFront serves cached content.
Versioned filenames > invalidation for static assets. Invalidation is for emergencies.
Target >90% cache hit ratio for static content. Low ratio means cache key or TTL problems.
Invalidation vs Versioned Filenames Decision Guide
IfStatic assets (JS, CSS, images) that change with each deploy
UseUse versioned filenames. Generate content hash (e.g., app.abc123.js). Set TTL to 1 year. No invalidation needed.
IfDynamic HTML pages (index.html) that reference versioned assets
UseSet short TTL (60s) on HTML. When HTML changes, CloudFront picks up new version within 60s. No invalidation needed.
IfAPI responses that return 404 after you add a new endpoint
UseInvalidation for specific path ('/api/v2/users'). Only for urgent fixes or new endpoints. Default TTL can be 60s for APIs.
IfEmergency security patch — need to remove cached content immediately
UseUse invalidation with specific paths ('/malicious.js'). Wait for completion (2-15 minutes). Also rotate any security tokens.

Route 53 Routing Policies: Latency, Geolocation, and Failover

Route 53 offers several routing policies that go far beyond simple DNS resolution.

Latency-based routing: Route 53 measures round-trip time between the user's resolver and each AWS region where you have an endpoint. It returns the IP of the region with the lowest latency. Ideal for active-active setups where you want automatic performance optimisation.

Geolocation routing: Routes users based on their geographic origin (continent, country, or state). Useful for compliance (GDPR privacy notice for EU users) or content localization (different pricing per country). Note: geolocation uses requestor's IP, not DNS resolver location.

Weighted routing: Distributes traffic across multiple endpoints based on assigned weights. Great for canary deployments (1% traffic to new version) or A/B testing.

Failover routing: Works with Route 53 health checks. If the primary endpoint fails health check, Route 53 returns the secondary endpoint's IP. Ensure health check intervals are short enough for your desired RTO.

Production nuance: DNS caching at ISPs can override Route 53 decisions. Set TTL low (60s) for latency and failover records to respond quickly to network changes.

Another nuance: latency-based routing works at the resolver level, not the end user. If a user's corporate DNS resolver is in Virginia but the user is in Europe, they get routed based on Virginia's latency. That's why geolocation can be more predictable for compliance use cases.

route53-failover-record.jsonJSON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "api.yourapp.com.",
        "Type": "A",
        "SetIdentifier": "primary-us-east-1",
        "Failover": "PRIMARY",
        "AliasTarget": {
          "HostedZoneId": "Z2FDTNDATAQYW2",
          "DNSName": "d123.cloudfront.net.",
          "EvaluateTargetHealth": true
        }
      }
    },
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "api.yourapp.com.",
        "Type": "A",
        "SetIdentifier": "secondary-eu-west-1",
        "Failover": "SECONDARY",
        "AliasTarget": {
          "HostedZoneId": "Z2FDTNDATAQYW2",
          "DNSName": "d456.cloudfront.net.",
          "EvaluateTargetHealth": true
        }
      }
    }
  ]
}
Output
Created primary failover record pointing to us-east-1 CloudFront distribution.
Created secondary failover record pointing to eu-west-1 CloudFront distribution.
Health checks must be attached to primary record for failover to work.
Mental Model: DNS as Traffic Director
  • Latency routing is reactive: uses actual network measurements to find fastest region.
  • Geolocation is deterministic: based on IP address ranges, not real-time latency.
  • Failover routing requires health checks on EVERY endpoint — without them, failover never triggers.
  • Alias records (pointing to AWS resources) are free and support health evaluation.
  • Weighted routing is perfect for canary deployments: shift 1% traffic, monitor, then ramp up.
Production Insight
A large e-commerce site used geolocation routing for EU users but forgot that some ISPs use DNS forwarders in different countries.
Users in Germany got routed to the US because their corporate DNS resolver was in Virginia.
Rule: latency-based routing is more robust than geolocation for performance. Use geolocation only for legal restrictions.
Another failure: a team set failover routing but 'EvaluateTargetHealth' was set to 'No' on the alias record. The health check worked, but Route 53 ignored it. Always set EvaluateTargetHealth=true for alias records in failover configurations.
Test failover by actually taking the primary endpoint offline — not just in console.
Key Takeaway
Choose routing policy based on your actual failure mode: latency for speed, geolocation for rules, failover for availability.
Rule: always pair failover routing with health checks and EvaluateTargetHealth=true — without them, it's just fancy DNS that never switches.
Set TTL to 60s for routing records to allow quick adjustments.
Test failover in staging: simulate primary outage and measure time to switch.

Custom Domain Setup: SSL Certificates, Regions, and Aliases

To serve your app via CloudFront with a custom domain, you need three pieces that must match exactly.

SSL/TLS certificate must be in ACM (AWS Certificate Manager) in the us-east-1 region — even if your origin is elsewhere. CloudFront operates globally but validates certificates from us-east-1 only. The certificate must include all alternate domain names you plan to use (e.g., example.com and www.example.com).

CloudFront distribution must have the custom domain listed in Alternate Domain Names (CNAMEs). This tells CloudFront which domain names to accept traffic for and which certificate to use.

Route 53 alias record pointing to the CloudFront distribution's DNS name (e.g., d123.cloudfront.net). Alias records are free, work at the zone apex, and support health evaluation.

The trap that catches everyone: ACM certificate in eu-west-1 (where your EC2 is) works for ALB but fails for CloudFront. The error message is cryptic: 'The specified SSL certificate doesn't exist, isn't in us-east-1, or doesn't match the alternate domain names'. Always request CloudFront certificates in us-east-1.

Also: if you change the CloudFront distribution (e.g., add a new origin), edge locations can take 10-20 minutes to propagate the configuration. Plan a maintenance window for changes that affect routing.

cloudfront-custom-domain.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
# Step 1: Request certificate in us-east-1 (NOT your origin region)
aws acm request-certificate \
  --domain-name example.com \
  --subject-alternative-names www.example.com \
  --validation-method DNS \
  --region us-east-1

# Step 2: Create CloudFront distribution with custom domain
aws cloudfront create-distribution \
  --origin-domain-name myapp.s3.amazonaws.com \
  --default-root-object index.html \
  --aliases 'www.example.com,example.com' \
  --viewer-certificate "{\"ACMCertificateArn\":\"arn:aws:acm:us-east-1:123456789:certificate/abc-123\",\"SSLSupportMethod\":\"sni-only\",\"MinimumProtocolVersion\":\"TLSv1.2_2021\"}" \
  --default-cache-behavior '{"TargetOriginId":"myapp","ViewerProtocolPolicy":"redirect-to-https","Compress":true}'

# Step 3: Create Route 53 alias record
# Use the distribution domain name from the create-distribution output
# dXXX.cloudfront.net
aws route53 change-resource-record-sets --hosted-zone-id Z123456 --change-batch file://alias.json
Output
Certificate requested in us-east-1. Validate via DNS before use.
Distribution created: E1ABC123XYZ
Domain name: d1a2b3c4d5e6.cloudfront.net
Alias records created. Propagation may take 60 seconds due to TTL.
Certificate Region Trap — This Catches Everyone
If you request the certificate in any region other than us-east-1, CloudFront will refuse to use it. The error is not obvious: 'The specified SSL certificate doesn't exist, isn't in us-east-1, or doesn't match the alternate domain names'. It's in us-east-1, but your cert is in eu-west-1. Request all CloudFront certificates in us-east-1, regardless of where your origin lives.
Production Insight
Teams often miss that ACM certificates for CloudFront must be in us-east-1. They request the cert in the same region as their EC2 instance (eu-west-1, ap-southeast-2), then spend hours debugging SSL handshake failures.
Rule: always request CloudFront certificates in us-east-1, regardless of where your origin lives. Save the certificate ARN and use it consistently.
Another common mistake: after updating the CloudFront distribution (e.g., adding a new origin), the edge locations can take up to 10 minutes to propagate the configuration. During that window, users may see 502 errors or old origins. Plan a maintenance window for such changes.
When you change the distribution's origin, coordinate with DNS TTL to avoid serving old config.
Key Takeaway
Custom domain setup requires three things: certificate (us-east-1), CloudFront domain alias, and Route 53 alias record.
The most common failure is certificate region mismatch — always use us-east-1.
Alias records are free, support root domains (example.com), and evaluate health.
Test the domain with curl -I https://yourdomain.com before pointing production traffic.

Security: Origin Access Control, WAF, and Signed URLs

CloudFront provides several security layers beyond basic TLS.

Origin Access Control (OAC) — restricts access to your S3 origin so that only CloudFront can fetch objects. OAC replaces the older Origin Access Identity (OAI) and is strongly preferred for new distributions. You attach an OAC to the distribution's origin and update the bucket policy to allow requests signed by that OAC. OAC supports server-side encryption with KMS; OAI does not.

AWS WAF integration — associate a Web ACL with your CloudFront distribution to block malicious traffic (SQL injection, XSS, IP reputation lists, rate limiting) before it reaches your origin. WAF rules are applied at the edge, reducing origin load. WAF costs scale with request volume, so use rate-based rules to limit costs.

Signed URLs and Signed Cookies — for premium content, generate time-limited URLs that CloudFront verifies using a private key. Signed URLs are per-file; Signed Cookies apply to a set of files. Generate short expiration (minutes to hours) and combine with IP restrictions for defense in depth.

Field-Level Encryption — encrypts sensitive data (credit card numbers, PII) before sending to the origin, so even the origin cannot read the raw data. The origin receives only the encrypted value.

Real risk: If you use OAI instead of OAC, you cannot use AWS KMS to encrypt objects at rest in S3. Always choose OAC for new distributions.

cloudfront-oac-setup.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/bin/bash
# Create Origin Access Control (OAC) for S3 origin
# OAC replaces legacy Origin Access Identity (OAI)

# Step 1: Create OAC
OAC_ID=$(aws cloudfront create-origin-access-control \
  --origin-access-control-config "{
    \"Name\": \"MyAppOAC\",
    \"Description\": \"OAC for myapp S3 bucket\",
    \"SigningProtocol\": \"sigv4\",
    \"SigningBehavior\": \"always\",
    \"OriginAccessControlOriginType\": \"s3\"
  }" \
  --query 'OriginAccessControl.Id' \
  --output text)

echo "Created OAC: ${OAC_ID}"

# Step 2: Update bucket policy to allow only CloudFront with this OAC
# The policy condition checks for 'aws:SourceArn' matching your distribution
cat > bucket-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::myapp-bucket/*",
      "Condition": {
        "StringEquals": {
          "aws:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E1ABC123XYZ"
        }
      }
    }
  ]
}
EOF

echo "Apply bucket policy: aws s3api put-bucket-policy --bucket myapp-bucket --policy file://bucket-policy.json"

# Step 3: Attach OAC to distribution origin
# aws cloudfront update-distribution --id E1ABC123XYZ --distribution-config file://dist-config.json
Output
Created OAC: MY-OAC-ID-12345
Bucket policy created. Apply to S3 bucket.
Distribution update required to attach OAC to origin.
Forge Tip: OAC vs OAI — Always Use OAC for New Distributions
OAC is the modern replacement for OAI. It supports KMS-encrypted S3 objects, works with Lambda@Edge, and provides better auditability. OAI still works but is considered legacy. Use OAC for any new CloudFront + S3 setup.
Production Insight
A media company used signed URLs but set the expiration to 10 years — attackers extracted the URL once and had permanent access.
They also forgot to restrict access by IP range in WAF.
Rule: signed URLs should have short expiration (minutes to hours). Combine with IP restriction for defense in depth.
Another real incident: a distribution with OAI was accidentally made public via bucket policy allowing 's3:GetObject' to everyone. OAC with source ARN condition prevents this misconfiguration — the bucket can only be read by the specific CloudFront distribution, not just any IAM principal.
One more: if you use field-level encryption, remember that the origin never sees the encrypted fields — your backend code will receive the raw data only if you decrypt at the edge. Essential for PCI compliance.
Key Takeaway
Security at the edge prevents attacks from reaching your origin.
Use OAC for S3 origins (supports KMS), WAF for common threats (rate limiting, SQLi, XSS).
Signed URLs must have short expiration (minutes to hours) and IP restrictions.
Never rely on security through obscurity — bucket policies and WAF are the bare minimum.

Production Performance: Cache Hit Ratio, Origin Shield, and Cost Optimisation

CloudFront's effectiveness is measured by cache hit ratio — percentage of requests served from edge cache rather than origin. Target >90% for static assets. Low hit ratio means your cache key is too specific (forwarding unique headers or query strings) or TTL is too short.

Origin Shield — an additional caching layer in a single region that sits between edges and origin. It aggregates requests from all edges, reducing connections to your origin. Enable it for origins that are not already behind a CDN and for high-traffic workloads. Origin Shield can dramatically reduce origin load during traffic spikes.

Regional Edge Caches — automatically enabled for all distributions (as of 2024+). They sit between edge locations and origin, caching content not requested frequently enough to stay in edge caches. No extra cost.

Cost optimisation: CloudFront charges per request and per GB transferred. Use compression (gzip/brotli) to reduce bytes. Brotli compresses text 20-25% better than gzip. Set appropriate TTLs to avoid frequent origin fetches. Use cost allocation tags to track spend per distribution.

Monitoring: CloudWatch metrics include Requests, BytesDownloaded, TotalErrorRate, and CacheHitRate. Set alarms for error rate >1% and cache hit rate <80%. Monitor OriginLatency for signs of origin overload.

Pricing nuance: CloudFront has free tier (1TB transfer/month), but costs can spike if you serve large files (video) or have high request rates (many small files). For small files, per-request cost dominates; consider combining files into archives or using HTTP/2 multiplexing.

cloudfront-performance-checks.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash
DISTRIBUTION_ID="E1ABC123XYZ"

echo "=== CloudFront Performance Metrics ==="

# Cache hit ratio (last hour)
aws cloudwatch get-metric-statistics \
  --namespace AWS/CloudFront \
  --metric-name CacheHitRate \
  --statistics Average \
  --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
  --period 3600 \
  --dimensions Name=DistributionId,Value="${DISTRIBUTION_ID}"

# Error rate
aws cloudwatch get-metric-statistics \
  --namespace AWS/CloudFront \
  --metric-name TotalErrorRate \
  --statistics Average \
  --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
  --period 3600 \
  --dimensions Name=DistributionId,Value="${DISTRIBUTION_ID}"

# Origin latency (p95)
aws cloudwatch get-metric-statistics \
  --namespace AWS/CloudFront \
  --metric-name OriginLatency \
  --statistics p95 \
  --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
  --period 3600 \
  --dimensions Name=DistributionId,Value="${DISTRIBUTION_ID}"

echo "=== Cache Hit Ratio Target: >90% for static content ==="
echo "=== Error Rate Target: <1% ==="
Output
CacheHitRate: 94.2% (OK)
TotalErrorRate: 0.3% (OK)
OriginLatency p95: 45ms (OK)
Cost vs Performance Balance
Don't set TTL to 0 for everything 'to be safe' — every request hits origin. Use versioned filenames and long TTLs for static assets. It's the cheapest way to improve performance and reduce origin costs simultaneously.
Production Insight
A startup saw their CloudFront bill triple after a viral post. They had no compression and TTLs set to 0 for all paths.
Every request hit the origin, which also meant high EC2 data transfer costs.
Fix: enabled Brotli compression (25% bandwidth reduction), set minimum TTL of 1 hour for static assets, enabled Origin Shield.
Bill dropped 70%, page load times improved 40%.
Rule: always review CloudFront cost and usage report before and after any launch event.
Another overlooked cost: invalidations cost money (first 1,000 paths per month free, then $0.005 per path). If you invalidate 10,000 paths daily, that's $1,500/month. Use versioned filenames instead.
Set a CloudWatch alarm on Requests to detect unexpected traffic spikes.
Key Takeaway
Target cache hit ratio >90% for static content. Low ratio = cache key or TTL problem.
Origin Shield reduces origin load during traffic spikes. Enable for high-volume workloads.
Compression: Brotli > gzip. Reduces bandwidth 20-25% for text content.
Cost monitoring: set CloudFront budget alerts. Invalidations cost money — use versioned filenames.

What the Hell is Route53 Actually Doing?

Route53 is not magic. It's a DNS service with a global anycast network and a health-check engine strapped to the side. When a client hits your CloudFront distribution, Route53 translates the human-readable domain into an IP — but that's the boring part.

The real power is the latency-based routing. Route53 maintains a latency map between every AWS edge location and your origins. When a user in São Paulo requests your site, Route53 doesn't just serve any old IP. It looks up which CloudFront edge is closest to that user's resolver, returns that IP, and your content travels the shortest possible path. That's why your global users don't hate you.

But here's the trap: Route53's health checks are optional per record. If your CloudFront distribution goes down, Route53 will keep returning the same IP unless you configure failover routing with active health checks. Without them, you're serving dead endpoints. Production incident waiting to happen.

Route53HealthCheck.tsTYPESCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// io.thecodeforge — devops tutorial

// This is the minimum health check config to avoid serving dead origins
export const healthCheckConfig: AWS.Route53.Types.HealthCheckConfig = {
  Type: 'HTTPS',
  FullyQualifiedDomainName: 'api.production.myapp.com',
  Port: 443,
  ResourcePath: '/health',
  RequestInterval: 30, // seconds
  FailureThreshold: 3,
  EnableSNI: true,
  Regions: [
    'us-east-1',
    'eu-west-1',
    'ap-southeast-1'
  ]
};

// Bind this to a failover record set. If health fails for 90s, Route53 flips to secondary.
Output
Health check created. FQDN: api.production.myapp.com, Type: HTTPS, Threshold: 3 failures in 30s intervals.
Production Trap:
Route53 health checks cost $0.75 per month per check. That's cheap. The cost of a multi-region outage because you skipped them? Six figures. Don't be that engineer.
Key Takeaway
Latency-based routing is powerful, but only if you pair it with health checks. Otherwise you're just guessing.

Prerequisites — The Things You'll Hate Yourself For Skipping

Before you touch a single Route53 record, get these sorted. I've seen production deploys stall because some junior didn't have the domain transferred or forgot about DNS TTL propagation. Don't be that person.

You need: an active AWS account (obviously), a registered domain — either through Route53's registrar or a third-party like Namecheap. If it's third-party, make sure the nameservers are pointed to AWS. That means four NS records from your registrar pointing to the Route53 hosted zone's delegation set. Get this wrong and your domain won't resolve. Happens weekly.

DNS concepts aren't optional. You need to understand TTL, A/AAAA records, CNAME, and alias records. Especially alias records — they're Route53's killer feature for CloudFront. Unlike CNAME, alias records work at the zone apex (example.com, not www.example.com) and cost nothing extra. Use them.

Finally, have your SSL/TLS certificate ready — ideally in AWS Certificate Manager in us-east-1. CloudFront only loads certificates from us-east-1. Request it there, not in your app's region. That mistake has cost teams days of debugging.

PrerequisitesCheck.shBASH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
# io.thecodeforge — devops tutorial

# Verify your domain's nameservers point to AWS Route53
dig NS example.com +short

# Expected output:
# ns-1234.awsdns-56.org.
# ns-5678.awsdns-78.co.uk.
# ns-9012.awsdns-34.com.
# ns-3456.awsdns-12.net.

# If you see anything else, fix your registrar config before proceeding.

# Check that your ACM certificate is in us-east-1
aws acm list-certificates --region us-east-1 --query "CertificateSummaryList[?DomainName=='example.com']"
Output
[
{
"CertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/abc123",
"DomainName": "example.com",
"Status": "ISSUED"
}
]
Senior Shortcut:
Use the AWS console's 'Test Record Set' feature before pointing production traffic at a new CloudFront distribution. It validates aliases and health checks without cutting over.
Key Takeaway
Get your domain, certificate, and DNS concepts right first. Everything else is just configuration.

Gradual Cutover Strategy: DNS Weighting and Dual-Origin Migration

Changing DNS records for a production CloudFront distribution is risky: TTLs are cached globally, and a single misconfigured origin can take down all users before you notice. A gradual cutover avoids this. The why is simple: Route53 lets you attach multiple weighted records to the same alias, splitting traffic between your old origin and the new CloudFront distribution. Start with a 99/1 split, incrementally shift the weight over hours or days while monitoring error rates, cache hit ratios, and latency. This exposes problems in the new origin — wrong S3 bucket policies, stale SSL, or missing CORS headers — before they affect everyone. Route53 health checks can also automatically fail back to the old origin if the new target returns 5xx. Once 100% traffic is stable on CloudFront, delete the old record. This strategy is mandatory for any migration that cannot tolerate downtime or a full rollback.

route53-weighted-migration.ymlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// io.thecodeforge — devops tutorial
// Gradual cutover: 10% new CloudFront, 90% old origin
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  OldOriginRecord:
    Type: AWS::Route53::RecordSet
    Properties:
      Name: www.example.com
      Type: A
      AliasTarget:
        DNSName: old-alb-123.us-east-1.elb.amazonaws.com
      Weight: 90
  NewCloudFrontRecord:
    Type: AWS::Route53::RecordSet
    Properties:
      Name: www.example.com
      Type: A
      AliasTarget:
        DNSName: d123.cloudfront.net
      Weight: 10
      SetIdentifier: CloudFront
Output
Traffic splits: 10% to CloudFront, 90% to old ALB.
Production Trap:
Route53 weighted records do not propagate instantly — clients cache DNS for the full TTL. Set TTL to 60 seconds during migration, not the default 300.
Key Takeaway
Never cut over DNS in one shot. Use weighted records to shift traffic incrementally and monitor each step.

CloudFormation Infrastructure: Declarative CloudFront + Route53 Pipelines

Manually clicking through the AWS console to set up CloudFront and Route53 is fragile and unrepeatable. CloudFormation turns your entire global delivery stack into version-controlled infrastructure. The why is obvious: one template defines the origin, distribution, SSL certificate, aliases, and Route53 record in a single deploy. Changes are reviewed via pull requests, rolled back via change sets, and auditable in CloudTrail. The key pattern is the CloudFront distribution's DomainName output passed as an alias target to a Route53 RecordSet — both in the same stack. Include a Lambda@Edge associaton for signed URLs or header rewriting without leaving the template. Use nested stacks to separate the WAF, the origin bucket, and the distribution, so you can update security policies independently. This eliminates the most common production errors: mismatched SSL regions, forgotten Origin Access Control, and misconfigured CNAMEs.

cloudfront-route53-stack.ymlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// io.thecodeforge — devops tutorial
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Aliases: [www.example.com]
        ViewerCertificate:
          AcmCertificateArn: arn:aws:acm:us-east-1:123456:certificate/abc
          SslSupportMethod: sni-only
        Origins:
          - DomainName: my-bucket.s3.amazonaws.com
            Id: S3Origin
            S3OriginConfig:
              OriginAccessIdentity: origin-access-identity/cloudfront/E1A2B3C4D5
        Enabled: true
  DnsRecord:
    Type: AWS::Route53::RecordSet
    Properties:
      Name: www.example.com
      Type: A
      AliasTarget:
        DNSName: !GetAtt CloudFrontDistribution.DomainName
        HostedZoneId: Z2FDTNDATAQYW2
Output
Creates CloudFront distribution and Route53 A alias in one deploy.
Production Trap:
CloudFront SSL certificates must be in us-east-1 (N. Virginia) regardless of where your application runs. Forgetting this causes stack creation failures.
Key Takeaway
Infrastructure as code with CloudFormation makes CloudFront + Route53 changes predictable, reviewable, and rollback-able.

Overview: Why CloudFront and Route53 Belong Together

Before you wire a CDN to a DNS provider, ask why they should be coupled at all. CloudFront gives you edge caching and DDoS protection. Route53 gives you global traffic routing. Alone, each solves a different problem. Together, they solve the hardest one: ensuring your users hit the nearest healthy endpoint without manual failover or stale caches. The real value isn't feature stacking—it's eliminating the gap between DNS resolution and content delivery. When Route53 routes a user to a CloudFront edge location, the distance between request and response drops from 200ms to 20ms. More importantly, Route53's health checks can tell CloudFront which origin is alive, so your CDN doesn't serve 502s from a dead server. This isn't about convenience; it's about preventing the scenario where your deployment works but users still see broken pages because DNS cached an old IP. Choose this stack when uptime and speed are non-negotiable, and you need one console to manage both.

overview-minimal.ymlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// io.thecodeforge — devops tutorial
// Overview: minimal Route53 + CloudFront alias
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  DomainName:
    Type: String
    Default: 'example.io'
Resources:
  Distribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Aliases: [!Ref DomainName]
        DefaultCacheBehavior:
          TargetOriginId: myOrigin
          ViewerProtocolPolicy: redirect-to-https
        Origins:
          - DomainName: myorigin.com
            Id: myOrigin
  DNS:
    Type: AWS::Route53::RecordSetGroup
    Properties:
      HostedZoneName: !Sub '${DomainName}.'
      RecordSets:
        - Name: !Ref DomainName
          Type: A
          AliasTarget:
            DNSName: !GetAtt Distribution.DomainName
            HostedZoneId: Z2FDTNDATAQYW2
Output
Creates alias record pointing to CloudFront distribution
Production Trap:
If you skip the Alias record and use a CNAME instead, CloudFront will not resolve correctly for the naked domain—breaking apex traffic silently.
Key Takeaway
Route53 health checks must inform CloudFront origin selection, not just DNS routing

Architecture: How the Pieces Actually Fit Together

Stop thinking of CloudFront and Route53 as separate services. In production, they form a single traffic pipeline with three layers. First, Route53 receives a DNS query and applies a routing policy—latency-based, geolocation, or weighted. It resolves to the nearest CloudFront edge location. Second, that edge checks its cache. On a miss, it forwards to the origin through an Origin Access Control (OAC) or custom header. Third, Route53's health probes continuously monitor your origin endpoints and feed their status back to CloudFront via origin failover groups. The architectural trap most engineers fall into: they configure DNS routing to multiple origins but forget CloudFront can only talk to one origin per behavior. The fix is a CloudFront origin group with primary and secondary origins tied to Route53 health checks. This means if your primary origin in us-east-1 fails, the edge fetches from eu-west-1 without any DNS propagation delay. The result: sub-second failover instead of the 60-second TTL hell most teams accept. Always model the pipeline as DNS → edge cache → origin group → health feedback loop.

architecture-group.ymlYAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// io.thecodeforge — devops tutorial
// Architecture: CloudFront origin group with failover
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  Distribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
          - DomainName: primary.example.io
            Id: primaryOrigin
            CustomOriginConfig:
              OriginProtocolPolicy: https-only
          - DomainName: secondary.example.io
            Id: secondaryOrigin
            CustomOriginConfig:
              OriginProtocolPolicy: https-only
        OriginGroups:
          Items:
            - Id: failoverGroup
              FailoverCriteria:
                StatusCodes: [503, 504]
              Members:
                - OriginId: primaryOrigin
                - OriginId: secondaryOrigin
        DefaultCacheBehavior:
          TargetOriginId: failoverGroup
          ViewerProtocolPolicy: redirect-to-https
Output
Distributes traffic to primary; fails over to secondary on 503/504
Architecture Insight:
Always place Route53 health checks inside the same CloudFormation stack as the CloudFront distribution to prevent race conditions during stack updates.
Key Takeaway
CloudFront origin groups + Route53 health checks = DNS-level failover without TTL tradeoffs
● Production incidentPOST-MORTEMseverity: high

The Deploy That Never Reached Users — Cache Invalidation Missed

Symptom
Users reporting that the new button/layout isn't visible. curl -I shows x-cache: Hit from cloudfront. Origin S3 bucket has the updated files. TTL is 24 hours.
Assumption
Engineers assumed CloudFront would automatically pick up new files because the S3 object keys remained the same (overwritten). They didn't know CloudFront ignores changes to existing keys.
Root cause
CloudFront caches objects by URL (including query strings and headers). When object content changes but the URL stays the same (e.g., overwriting app.js), the old cache persists until TTL expires. Default TTL is 24 hours. Invalidating /app.js would have fixed it, but the team didn't include the invalidation step in their deployment pipeline. The cache didn't expire until the next day's deploy, which happened to include a different filename anyway.
Fix
1. Added invalidation to deployment pipeline: aws cloudfront create-invalidation --distribution-id XYZ --paths /app.js /styles.css 2. Switched to versioned filenames: app.abc123.js generated from content hash. New file → new URL → cache miss automatically. 3. Set short TTL (60s) for HTML files that reference versioned assets. 4. Added monitoring: alert if x-cache header shows 'Hit' for updated file patterns after deploy. 5. For emergency fixes: create invalidation for exact path, wait for completion, verify via curl.
Key lesson
  • Never rely on TTL expiry for urgent content updates. Invalidation is required.
  • Versioned filenames (app.abc123.js) are free, instant, and the industry standard.
  • Include cache invalidation as a mandatory step in your deployment pipeline.
  • Use curl -I to check x-cache header: 'Miss' means origin fetch, 'Hit' means from edge.
  • For static sites, set short TTL (60s) on HTML, long TTL (1 year) on versioned assets.
Production debug guideSymptom → Action grid for the three most common production issues5 entries
Symptom · 01
CloudFront returns HTTP 403 Forbidden for S3 origin
Fix
Check Origin Access Control (OAC) settings. Ensure CloudFront has permission to read from the S3 bucket. Update bucket policy to allow aws:SourceArn = distribution ARN. OAC replaces legacy OAI.
Symptom · 02
DNS resolution fails after updating Route 53 record
Fix
Check TTL on the old record (default 300s). Use dig +trace yourdomain.com to see propagation. For planned changes, lower TTL to 60s 24 hours before the change.
Symptom · 03
High origin load despite CloudFront being enabled
Fix
Review CloudFront cache hit ratio in CloudWatch (target >90% for static). Check cache key: are you forwarding query strings, cookies, or headers unnecessarily? Each unique combination creates new cache entry.
Symptom · 04
Custom domain SSL not working — ERR_CERT_COMMON_NAME_INVALID
Fix
Verify ACM certificate is in us-east-1 region. Check Alternate Domain Name in CloudFront exactly matches certificate domain. Ensure Route 53 alias record points to CloudFront DNS name, not an IP.
Symptom · 05
Route 53 failover not triggering — primary down but traffic keeps going
Fix
Check that health check is attached to primary record ('Evaluate Target Health' = 'Yes' for aliases). Verify health check URL returns 200 within 2 seconds. Check if EvaluateTargetHealth is enabled.
★ CloudFront & Route 53 Quick Debug Cheat SheetCommands and actions for the most common production issues
User sees old content after deployment — check cache headers
Immediate action
Invalidate the CloudFront cache or use versioned filenames
Commands
curl -I https://yourdomain.com/app.js | grep -i x-cache
aws cloudfront create-invalidation --distribution-id YOUR_DIST_ID --paths '/*'
Fix now
Run invalidation for changed paths; for static assets, implement versioned filenames in build process.
Route 53 failover not triggering — check health check and record config+
Immediate action
Verify health check status and record evaluation
Commands
aws route53 test-dns-answer --hosted-zone-id ZONE_ID --record-name yourdomain.com --record-type A
aws route53 get-health-check-status --health-check-id HC_ID
Fix now
Attach health check to primary record, set EvaluateTargetHealth=true for alias records, ensure health check URL returns 200.
DNS not resolving to CloudFront — check alias record+
Immediate action
Verify Route 53 alias points to correct distribution DNS name
Commands
dig +short yourdomain.com
aws route53 list-resource-record-sets --hosted-zone-id ZONE_ID --query "ResourceRecordSets[?Name=='yourdomain.com.']"
Fix now
Update alias target to correct distribution DNS name (dXXX.cloudfront.net). Wait for TTL expiry.
Certificate error — check region and domain match+
Immediate action
Verify ACM certificate is in us-east-1 and covers Alternate Domain Names
Commands
aws acm list-certificates --region us-east-1 --query "CertificateSummaryList[?DomainName=='example.com']"
aws cloudfront get-distribution --id DIST_ID --query "Distribution.DistributionConfig.Aliases"
Fix now
Request certificate in us-east-1. Add all alternate domain names to certificate and CloudFront alias list.
WAF blocking legitimate traffic — check sampled requests+
Immediate action
Examine WAF logs in CloudWatch, identify blocking rule
Commands
aws wafv2 get-sampled-requests --web-acl-arn YOUR_ACL_ARN --rule-metric-name YOUR_RULE --scope CLOUDFRONT --time-window Start=...,End=...
aws wafv2 update-rule-group --name YOUR_GROUP --scope CLOUDFRONT --lock-token TOKEN --rules file://updated-rules.json
Fix now
Switch blocking rule to COUNT mode temporarily, adjust rate limit or scope, then re-enable BLOCK.
CloudFront vs Route 53 — Complementary Roles
AspectCloudFrontRoute 53
Primary roleContent delivery (CDN) — cache and serve at edgeDNS resolution — route users to best endpoint
Latency reductionServes cached content from nearest edge locationRoutes to region with lowest network latency via latency-based routing
CachingYes — TTL-based, configurable cache keys (URL, query string, headers)No caching — only DNS response caching (TTL on records)
Failover capabilityOnly via integration with Route 53 or origin failover groupsNative failover routing with health checks and EvaluateTargetHealth
Security featuresWAF, OAC (Origin Access Control), signed URLs, field-level encryptionDNSSEC, traffic flow policies, resolver-level filtering
Cost modelPer request + per GB data transfer. Caching reduces cost. Free tier: 1TB/month.Per hosted zone ($0.50/month) + per million queries ($0.40/million). Alias records free.
Deployment timeDistribution creation: 10-20 minutes. Invalidation: 2-15 minutes.DNS record changes: seconds, but propagation depends on TTL (default 300s)

Key takeaways

1
CloudFront and Route 53 are complementary
CloudFront caches content, Route 53 routes users. Use both for global applications.
2
Versioned filenames > invalidation for static assets. Set TTL to 1 year, never invalidate. Invalidation is for emergencies only.
3
Route 53 failover requires health checks and EvaluateTargetHealth=true. Without them, failover never triggers.
4
ACM certificates for CloudFront MUST be in us-east-1. Cert in any other region = distribution creation fails.
5
Alias records are free, support root domains, and evaluate health. CNAME records cannot be used at zone apex.
6
Target cache hit ratio >90% for static content. Low ratio = cache key too specific (forwarding unique query strings).
7
Enable Brotli compression. Reduces bandwidth 20-25% for text content. Both gzip and Brotli supported.
8
Use OAC (Origin Access Control) for S3 origins. OAC supports KMS encryption; legacy OAI does not.
9
Set CloudFront cost budget alarms. Invalidations cost money. Request counts scale with your traffic.
10
Test failover by actually taking the primary endpoint offline. Simulate real failures, not just console checks.
11
Use wildcard invalidation paths (/static/*) for batch updates. Individual paths cost more and take longer.

Common mistakes to avoid

7 patterns
×

Setting TTLs too low or using invalidation for every deploy

Symptom
High origin load, increased latency, higher CloudFront bill (more origin fetches). Invalidations cost money and take minutes.
Fix
Use versioned filenames for static assets (app.abc123.js). Set TTL to 1 year. For HTML files referencing versioned assets, set short TTL (60s). Reserve invalidation for emergencies.
×

Forgetting to attach health checks to Route 53 failover records

Symptom
Primary endpoint fails, but Route 53 continues returning its IP. Users get errors, failover never triggers.
Fix
Attach health check to primary record. For alias records, set EvaluateTargetHealth=true. Verify health check URL returns 200 within 2 seconds. Test failover by taking primary offline.
×

Requesting ACM certificate outside us-east-1 for CloudFront

Symptom
CloudFront distribution creation fails with 'The specified SSL certificate doesn't exist, isn't in us-east-1, or doesn't match the alternate domain names'.
Fix
Always request CloudFront certificates in us-east-1. Save the ARN. Use the same region for certificate, regardless of origin region. The error message is correct — the certificate technically doesn't exist in us-east-1.
×

Using CNAME instead of Alias record for root domain (example.com)

Symptom
DNS resolution fails for root domain — DNS protocol forbids CNAME at zone apex. Browser shows 'domain not found'.
Fix
Use Route 53 alias record for root domain. Alias records are free, work at apex, and support health evaluation. For subdomains (www), alias records are also preferred but CNAME works.
×

Not enabling compression on CloudFront distributions

Symptom
High data transfer costs, slow loading for text-based content (HTML, CSS, JS, JSON). Brotli can reduce size 20-25%.
Fix
Enable compression in cache behavior. Set 'CompressObjects' to true. Both gzip and Brotli are supported for appropriate content types.
×

Forwarding all query strings in cache key

Symptom
Cache hit ratio below 20%. Each unique query string (e.g., ?session=abc) creates new cache entry, preventing cache reuse.
Fix
Configure cache policy to forward only necessary query strings (e.g., ?lang=en). For A/B testing, forward only the A/B parameter. For versioning, use URL path, not query string.
×

Using OAI (Origin Access Identity) instead of OAC for KMS-encrypted buckets

Symptom
CloudFront can't read objects from S3 bucket encrypted with KMS. OAI does not support KMS.
Fix
Use OAC (Origin Access Control) instead. OAC supports KMS encryption and provides better auditability through source ARN conditions. Migrate existing OAI distributions to OAC.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
Explain the difference between CloudFront cache invalidation and object ...
Q02SENIOR
How would you design a global application that serves both static conten...
Q03JUNIOR
What happens when you create a CloudFront distribution with a custom dom...
Q04SENIOR
Describe a real situation where a weighted Route 53 routing policy cause...
Q05SENIOR
How do you handle cache invalidation for a large deployment with thousan...
Q06SENIOR
When would you use geolocation routing over latency-based routing in Rou...
Q01 of 06SENIOR

Explain the difference between CloudFront cache invalidation and object versioning. Which would you use and why?

ANSWER
Invalidation removes cached objects by path from all edge locations, which takes 2-15 minutes and costs $0.005 per path after the first 1,000 paths per month. Versioning appends a unique hash to the filename (e.g., app.abc123.js), so a new URL is created each deployment — no invalidation needed. I prefer versioning for static assets (JS, CSS, images) because it's instant, free at scale, and avoids stale content during invalidation propagation. For dynamic content that cannot change URL (e.g., index.html), I use short TTL (60s) and optional invalidation for emergency fixes. Real example: a team invalidating 1,000 paths daily pays $150/month. Versioned filenames cost $0 and provide better performance.
FAQ · 11 QUESTIONS

Frequently Asked Questions

01
What is the difference between CloudFront cache invalidation and object versioning?
02
Why does my CloudFront distribution fail to create with 'The specified SSL certificate doesn't exist, isn't in us-east-1, or doesn't match the alternate domain names'?
03
Can I use CloudFront without Route 53?
04
What is the difference between Origin Shield and Regional Edge Caches?
05
How long does CloudFront cache invalidation take?
06
What health check does Route 53 use for failover?
07
Why is my CloudFront distribution showing 502 errors after updating the origin?
08
Can I use CloudFront with a non-AWS origin?
09
How do I set up a custom error response in CloudFront?
10
What is the difference between 'CNAME' and 'Alias' records in Route 53?
11
How do I reduce CloudFront costs for a high-traffic website?
N
Naren Founder & Principal Engineer

20+ years shipping production infrastructure and CI/CD at scale. Everything here is grounded in real deployments.

Follow
Verified
production tested
May 24, 2026
last updated
1,554
articles · all by Naren
🔥

That's Cloud. Mark it forged?

11 min read · try the examples if you haven't

Previous
AWS IAM — Identity and Access
9 / 23 · Cloud
Next
Introduction to Google Cloud Platform