DEV Community

Tejas Shinkar
Tejas Shinkar

Posted on

AWS CloudFront — Complete Understanding, Production Patterns & Practice

AWS CloudFront — Complete Understanding, Production Patterns & Practice

  • [ ] What problem a CDN solves
  • [ ] CloudFront distribution
  • [ ] Origin
  • [ ] Edge location / PoP
  • [ ] Regional edge cache
  • [ ] Cache
  • [ ] Cache HIT
  • [ ] Cache MISS
  • [ ] Cache key
  • [ ] Cache Policy
  • [ ] Origin Request Policy
  • [ ] Query strings
  • [ ] Headers
  • [ ] Cookies
  • [ ] Personalization
  • [ ] TTL
  • [ ] Minimum/default/maximum TTL
  • [ ] Cache-Control
  • [ ] Cache invalidation
  • [ ] Versioned assets
  • [ ] Cache behaviors
  • [ ] Static vs dynamic caching
  • [ ] Request collapsing
  • [ ] Cache hit ratio
  • [ ] CloudFront + S3
  • [ ] CloudFront + ALB + EC2
  • [ ] OAC
  • [ ] WAF
  • [ ] Production cache-key design

1. What CloudFront actually is

Amazon CloudFront is AWS's Content Delivery Network (CDN).

The simplest mental model is:

CloudFront keeps reusable copies of content closer to users so that the origin does not have to generate or deliver the same response repeatedly.

Without CloudFront:

User
  |
  v
Origin
(EC2 / ALB / S3 / API Gateway)
  |
  v
Response
Enter fullscreen mode Exit fullscreen mode

With CloudFront:

User
  |
  v
CloudFront Edge Location
  |
  +---- Cache HIT ----> Response to User
  |
  +---- Cache MISS ---> Origin
                           |
                           v
                        Response
                           |
                           v
                    CloudFront caches it
                           |
                           v
                        User
Enter fullscreen mode Exit fullscreen mode

The origin remains the source of truth. CloudFront is a delivery and caching layer in front of it.

CloudFront can use origins such as:

  • Amazon S3
  • Application Load Balancer
  • EC2/custom HTTP servers
  • API Gateway
  • Other HTTP origins

2. Why do we need a CDN?

Imagine an application hosted in Mumbai.

A nearby user may reach it with relatively low network latency. A user in Europe has a much longer network path:

Europe User
     |
     | long network distance
     v
Mumbai Origin
     |
     v
Response
Enter fullscreen mode Exit fullscreen mode

With CloudFront:

Europe User
     |
     v
Nearby CloudFront edge
     |
     v
Cached response
Enter fullscreen mode Exit fullscreen mode

If the response is already cached at that edge, the origin does not need to be contacted for that request.

CloudFront can therefore:

  1. Reduce viewer latency.
  2. Reduce origin load.
  3. Improve scalability.
  4. Reduce repeated origin data transfer.
  5. Provide globally distributed delivery.
  6. Integrate with security services such as AWS WAF and Origin Access Control.

3. Important CloudFront terminology

Distribution

A CloudFront distribution is the overall configuration that tells CloudFront how to deliver an application.

It contains configuration for things such as:

  • Origins
  • Cache behaviors
  • Cache policies
  • Origin request policies
  • Allowed HTTP methods
  • Viewer protocol settings
  • TLS/custom domains
  • Security
  • Logging

Mental model:

Distribution = the overall CloudFront delivery configuration.


Origin

The origin is where CloudFront obtains the original content.

Examples:

CloudFront -> S3
CloudFront -> ALB -> EC2
CloudFront -> EC2
CloudFront -> API Gateway
Enter fullscreen mode Exit fullscreen mode

For example:

CloudFront
    |
    v
ALB
    |
    +--> EC2
    +--> EC2
    +--> EC2
Enter fullscreen mode Exit fullscreen mode

Here, the ALB is the CloudFront origin.


Edge Location / Point of Presence (PoP)

An edge location is a CloudFront location close to viewers where CloudFront can serve cached content.

Conceptually:

                  CloudFront
                     |
       +-------------+-------------+
       |             |             |
     India         Europe         USA
       |             |             |
     Users         Users         Users
Enter fullscreen mode Exit fullscreen mode

Different edge locations can have their own cached copies.

Important:

The origin stores the original content; edge locations store temporary cached copies.

CloudFront also has regional edge caches between POPs and origins. These provide another caching layer and can retain less-popular objects longer than individual POP caches.


4. Complete request flow

Suppose the origin contains:

logo.png
Enter fullscreen mode Exit fullscreen mode

A user requests:

GET /logo.png
Enter fullscreen mode Exit fullscreen mode

The conceptual flow is:

1. User requests /logo.png
              |
              v
2. DNS routes the viewer to an appropriate CloudFront edge
              |
              v
3. CloudFront determines the cache key
              |
              v
4. Cache lookup
          /             \
        HIT              MISS
         |                |
         v                v
 Return object        Request origin
                           |
                           v
                     Origin response
                           |
                           v
                    CloudFront caches
                           |
                           v
                         User
Enter fullscreen mode Exit fullscreen mode

This is the foundation of CloudFront.


5. Cache HIT

A cache hit means:

CloudFront found a valid cached object matching the viewer's request.

Example:

User
 |
 v
CloudFront
 |
 v
Cache HIT
 |
 v
Cached object
Enter fullscreen mode Exit fullscreen mode

The origin does not need to generate the object for that request.

Benefits:

  • Lower latency
  • Lower origin load
  • Better scalability
  • Better cache hit ratio

6. Cache MISS

A cache miss means:

CloudFront cannot find a valid cached object matching the request at that edge.

Example:

User
 |
 v
CloudFront
 |
 | MISS
 v
Origin
 |
 | response
 v
CloudFront
 |
 +--> cache response
 |
 +--> User
Enter fullscreen mode Exit fullscreen mode

A later matching request can then become a cache hit while the object remains valid.


7. Each edge can have its own cache

Suppose a user in Delhi requests:

/logo.png
Enter fullscreen mode Exit fullscreen mode

One edge location may cache it.

A user elsewhere may reach another edge location, where that object is not yet cached.

Therefore:

                Origin
                  |
        +---------+---------+
        |         |         |
      Edge A    Edge B    Edge C
      logo      logo       logo
Enter fullscreen mode Exit fullscreen mode

The same object can exist in multiple edge caches.

A cache miss at one edge does not mean the entire CloudFront distribution has no copy anywhere.


8. Cache key — the most important concept

The cache key determines which viewer requests are considered equivalent for caching.

Think of it as:

CloudFront's identity/checklist for deciding whether this request can reuse an existing cached object.

For:

GET /products?id=10
Enter fullscreen mode Exit fullscreen mode

the cache identity could contain:

Path: /products
Query string: id=10
Enter fullscreen mode Exit fullscreen mode

If another user sends the same relevant request, it can map to the same cached object.


9. Why cache-key design matters

Suppose:

User A -> /products?id=10
User B -> /products?id=10
User C -> /products?id=10
Enter fullscreen mode Exit fullscreen mode

If all receive the same product information, we want:

                    /products?id=10
                          |
                          v
                    ONE cache object
                   /      |       \
                User A  User B   User C
Enter fullscreen mode Exit fullscreen mode

This produces good cache reuse.

But suppose the cache key unnecessarily includes a unique cookie:

User A:
Cookie: user=A

User B:
Cookie: user=B
Enter fullscreen mode Exit fullscreen mode

Then:

/products?id=10 + user=A -> Cache A
/products?id=10 + user=B -> Cache B
Enter fullscreen mode Exit fullscreen mode

The content may be identical, but CloudFront now has separate cache variants.

That reduces cache reuse and can increase origin traffic.


10. The golden cache-key rule

Ask:

Can this request value change the response?

If yes, it may need to participate in the cache key.

If no, including it may unnecessarily fragment the cache.

For example:

GET /products?id=10
Cookie: analytics_id=abc
Enter fullscreen mode Exit fullscreen mode

If analytics_id is only used for analytics and does not change the response, it usually should not become a cache-key dimension.

But:

GET /profile
Cookie: session_id=userA
Enter fullscreen mode Exit fullscreen mode

may return:

Hello Alice
Enter fullscreen mode Exit fullscreen mode

while:

GET /profile
Cookie: session_id=userB
Enter fullscreen mode Exit fullscreen mode

returns:

Hello Bob
Enter fullscreen mode Exit fullscreen mode

That is a personalized response and must not be accidentally shared.


11. Personalization and caching

This is a major production concern.

Suppose:

User A -> GET /profile
Cookie: session=A
Enter fullscreen mode Exit fullscreen mode

Origin returns:

Hello Alice
Enter fullscreen mode Exit fullscreen mode

Another user:

User B -> GET /profile
Cookie: session=B
Enter fullscreen mode Exit fullscreen mode

Origin returns:

Hello Bob
Enter fullscreen mode Exit fullscreen mode

If CloudFront creates one shared cache object using only:

/profile
Enter fullscreen mode Exit fullscreen mode

the response could be incorrectly reused.

That is not merely a performance problem. It can become a data-isolation/security problem.

Common strategies:

Strategy 1 — Don't shared-cache private responses

For highly dynamic/private endpoints:

User
 |
 v
CloudFront
 |
 v
Origin
Enter fullscreen mode Exit fullscreen mode

Strategy 2 — Vary the cache identity when appropriate

For some architectures:

/profile + user=A -> Cache A
/profile + user=B -> Cache B
Enter fullscreen mode Exit fullscreen mode

But this can become extremely expensive and fragmented when there are millions of users.

Strategy 3 — Separate static and dynamic content

A common production architecture:

/static/*  -> highly cacheable
/api/*     -> dynamic/private
Enter fullscreen mode Exit fullscreen mode

12. Cache Policy

A Cache Policy controls important caching decisions.

It determines:

  1. Which request values participate in the cache key.
  2. TTL settings.
  3. Compression-related cache behavior.

The cache key can be influenced by:

  • Path
  • Query strings
  • Headers
  • Cookies

The key idea:

Cache Policy answers: "What makes this request a different cache object, and how long should the object remain cached?"


13. Query strings

Consider:

/products?id=10
/products?id=20
Enter fullscreen mode Exit fullscreen mode

If id changes the response, it must be represented in the cache identity.

Correct conceptual result:

/products?id=10 -> Cache Object 1
/products?id=20 -> Cache Object 2
Enter fullscreen mode Exit fullscreen mode

If you ignored the relevant query string when the response depends on it, different products could map to the wrong cached response.


14. Cookies

Suppose:

GET /products?id=10
Cookie: user=A
Enter fullscreen mode Exit fullscreen mode

and:

GET /products?id=10
Cookie: user=B
Enter fullscreen mode Exit fullscreen mode

If the response is identical, do not automatically include the cookie in the cache key.

If the response differs because of the cookie, you need a design that prevents incorrect sharing.

The answer is not always "include every cookie."

That can create millions of cache variants.


15. Headers

Headers can also affect responses.

Example:

Accept-Language: en
Enter fullscreen mode Exit fullscreen mode

might produce:

Welcome
Enter fullscreen mode Exit fullscreen mode

while:

Accept-Language: fr
Enter fullscreen mode Exit fullscreen mode

might produce:

Bienvenue
Enter fullscreen mode Exit fullscreen mode

If language changes the response, language may need to influence the cache identity.

Again:

Vary the cache only on dimensions that genuinely affect the response.


16. Cache Policy vs Origin Request Policy

This is one of the most important CloudFront interview concepts.

Think of two separate questions:

Cache Policy

What makes this request different for caching?

Origin Request Policy

What information should CloudFront send to the origin?

They are related, but not the same.


17. Example: origin needs information but cache doesn't

Request:

GET /products?id=10
Cookie: analytics_id=ABC123
Enter fullscreen mode Exit fullscreen mode

Suppose:

  • id=10 determines the product.
  • analytics_id is needed by the origin for analytics.
  • analytics_id does not change the product response.

We want:

CACHE KEY
    /products?id=10
Enter fullscreen mode Exit fullscreen mode

but:

ORIGIN REQUEST
    /products?id=10
    Cookie: analytics_id=ABC123
Enter fullscreen mode Exit fullscreen mode

Therefore:

Cache Policy
    -> does NOT include analytics_id in cache key

Origin Request Policy
    -> forwards analytics_id to origin
Enter fullscreen mode Exit fullscreen mode

This allows cache reuse while still giving the origin required information.

AWS documents this separation explicitly: values included in the cache key are also sent to the origin, while an Origin Request Policy can add additional headers, cookies, and query strings to origin requests without putting them into the cache key.


18. Important warning with Authorization

Suppose:

GET /product?id=10
Authorization: Bearer token123
Enter fullscreen mode Exit fullscreen mode

If the authorization changes what response the user receives, you cannot simply forward the token and assume shared caching is safe.

Always ask:

Does this request information change the response?

If yes, either make the relevant dimension part of the cache design or avoid shared caching for that response.


19. TTL — Time To Live

TTL means:

How long a cached object remains fresh according to the CloudFront caching configuration.

Suppose:

TTL = 3600 seconds
Enter fullscreen mode Exit fullscreen mode

That is one hour.

Conceptually:

12:00 -> object cached
12:30 -> HIT
12:59 -> HIT
13:00 -> TTL expires
13:05 -> CloudFront needs fresh/validated origin content
Enter fullscreen mode Exit fullscreen mode

TTL is one of the biggest CDN design trade-offs.


20. Long TTL vs short TTL

Long TTL

Example:

app.js -> long TTL
Enter fullscreen mode Exit fullscreen mode

Advantages:

  • High cache reuse
  • Low origin traffic
  • Low latency
  • Better scalability

Disadvantage:

  • Changes may remain stale longer unless you use versioned assets or invalidation.

Short TTL

Example:

price.json -> short TTL
Enter fullscreen mode Exit fullscreen mode

Advantages:

  • Changes become visible sooner

Disadvantages:

  • More origin requests
  • Lower cache hit ratio
  • More origin load
  • Potentially higher latency

21. Minimum, default and maximum TTL

CloudFront cache policies have:

  • Minimum TTL
  • Default TTL
  • Maximum TTL

They work with origin caching headers such as:

Cache-Control: max-age=3600
Enter fullscreen mode Exit fullscreen mode

Default TTL

Used when the origin does not provide appropriate caching information.

Minimum TTL

Sets a lower bound on how long CloudFront caches.

Important production warning:

If Minimum TTL is greater than zero, CloudFront can cache for at least that duration even if origin headers contain directives such as no-cache, no-store, or private.

Therefore, be careful when using positive Minimum TTLs with private/dynamic content.

Maximum TTL

Places an upper bound on how long an object can remain fresh based on the relevant origin caching headers.


22. Cache-Control

The origin can send:

Cache-Control: max-age=3600
Enter fullscreen mode Exit fullscreen mode

or:

Cache-Control: no-store
Enter fullscreen mode Exit fullscreen mode

or:

Cache-Control: private
Enter fullscreen mode Exit fullscreen mode

These communicate caching requirements.

CloudFront's cache policy and TTL configuration determine how those origin instructions interact with CloudFront caching.


23. Cache invalidation

Suppose:

Origin:
logo.png = OLD
Enter fullscreen mode Exit fullscreen mode

CloudFront has:

logo.png = OLD
TTL = 24 hours
Enter fullscreen mode Exit fullscreen mode

You update the origin:

Origin:
logo.png = NEW
Enter fullscreen mode Exit fullscreen mode

CloudFront can still have the old object until it becomes invalid according to the caching configuration.

If you need the cached object removed sooner, use CloudFront invalidation.

Flow:

Origin = NEW

CloudFront Cache = OLD
        |
        v
   Invalidation
        |
        v
Cached object invalidated
        |
        v
Next request -> MISS
        |
        v
Origin -> NEW
        |
        v
CloudFront caches NEW
Enter fullscreen mode Exit fullscreen mode

24. TTL vs invalidation

Use TTL when:

"This content can safely remain cached for this long."

Use invalidation when:

"I changed the content and need the cached version invalidated before its normal lifetime."

Production systems commonly use both.


25. Versioned assets — a major production technique

Instead of constantly replacing:

/app.js
Enter fullscreen mode Exit fullscreen mode

use:

/app.a82f91.js
Enter fullscreen mode Exit fullscreen mode

When the application changes:

/app.b73c21.js
Enter fullscreen mode Exit fullscreen mode

is generated.

CloudFront sees a different cache key.

This makes long TTLs practical for build artifacts.

A common pattern:

HTML
    -> shorter TTL / controlled invalidation

JS/CSS/images
    -> long TTL + content-hashed filenames
Enter fullscreen mode Exit fullscreen mode

This reduces the need for broad invalidations.


26. Cache Behavior

A Cache Behavior is a set of CloudFront rules applied to requests matching a URL path pattern.

Example:

/static/*
/images/*
/api/*
Enter fullscreen mode Exit fullscreen mode

Different behaviors can use:

  • Different origins
  • Different cache policies
  • Different origin request policies
  • Different allowed methods
  • Different TTL/caching behavior
  • Different viewer/security settings

Example:

                  CloudFront
                      |
          +-----------+-----------+
          |                       |
       /static/*                /api/*
          |                       |
          v                       v
         S3                      ALB
                                  |
                               EC2/ECS
Enter fullscreen mode Exit fullscreen mode

27. Default behavior vs specific behaviors

A distribution has a default behavior.

You can add specific behaviors.

For example:

Default: /*
Specific: /api/*
Specific: /images/*
Enter fullscreen mode Exit fullscreen mode

Then:

/images/logo.png
Enter fullscreen mode Exit fullscreen mode

can use the /images/* behavior.

And:

/api/products
Enter fullscreen mode Exit fullscreen mode

can use the /api/* behavior.

The more specific matching behavior is used according to CloudFront's path matching rules.


28. Production e-commerce architecture

A strong example:

                         Internet
                            |
                            v
                       CloudFront
                            |
              +-------------+-------------+
              |                           |
          /static/*                    /api/*
              |                           |
              v                           v
              S3                         ALB
                                          |
                                    +-----+-----+
                                    |           |
                                   EC2         EC2
Enter fullscreen mode Exit fullscreen mode

Possible configuration:

/static/*
    S3 origin
    Long TTL
    Versioned assets

/images/*
    S3 origin
    Long TTL

/products/*
    ALB origin
    Cache by product identifier when response is public/reusable

/api/cart/*
    ALB origin
    No/shared-cache disabled

/api/profile/*
    ALB origin
    No/shared-cache disabled
Enter fullscreen mode Exit fullscreen mode

The important idea is:

Don't use one caching strategy for the entire application.


29. Scenario: public product catalogue

Request:

GET /products?id=10
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "name": "Phone",
  "price": 79999
}
Enter fullscreen mode Exit fullscreen mode

If all users get the same response:

User A -> MISS -> Origin -> Cache
User B -> HIT
User C -> HIT
User D -> HIT
Enter fullscreen mode Exit fullscreen mode

Excellent cache reuse.


30. Scenario: personalized profile

Request:

GET /profile
Cookie: session=A
Enter fullscreen mode Exit fullscreen mode

Response:

Hello Alice
Enter fullscreen mode Exit fullscreen mode

Another:

GET /profile
Cookie: session=B
Enter fullscreen mode Exit fullscreen mode

Response:

Hello Bob
Enter fullscreen mode Exit fullscreen mode

Do not accidentally make these a shared cache object.

Possible architecture:

/static/*  -> CloudFront cache
/profile    -> dynamic/private origin
Enter fullscreen mode Exit fullscreen mode

31. Scenario: analytics cookie

Requests:

GET /products?id=10
Cookie: analytics_id=A123
Enter fullscreen mode Exit fullscreen mode

and:

GET /products?id=10
Cookie: analytics_id=B456
Enter fullscreen mode Exit fullscreen mode

If the response is identical, analytics IDs should not unnecessarily create separate cache objects.

If the origin needs the analytics value, use the origin request configuration to forward it without unnecessarily making it part of the cache key.


32. Scenario: language-specific content

GET /home
Accept-Language: en
Enter fullscreen mode Exit fullscreen mode

returns:

Welcome
Enter fullscreen mode Exit fullscreen mode

while:

GET /home
Accept-Language: fr
Enter fullscreen mode Exit fullscreen mode

returns:

Bienvenue
Enter fullscreen mode Exit fullscreen mode

Language affects the response, so the caching design must distinguish the language variants.


33. Scenario: rapidly changing stock price

Suppose:

GET /stock/AAPL
Enter fullscreen mode Exit fullscreen mode

changes every second.

A long TTL would be inappropriate.

Possible approaches:

  • Very short TTL
  • No caching
  • Application-specific architecture
  • Streaming/WebSocket mechanisms for genuinely real-time requirements

CloudFront is not a "cache everything" service.

Caching is a business and correctness decision.


34. Scenario: news website

Possible design:

/articles/*
    Longer TTL

/home
    Shorter TTL

/api/personalized/*
    Dynamic/private
Enter fullscreen mode Exit fullscreen mode

Different content has different freshness requirements.


35. Scenario: deployment

Version 1:

app.js
Enter fullscreen mode Exit fullscreen mode

Version 2 changes the JavaScript.

If the same filename is used and the cached object is still valid, some users may continue receiving the old version.

Better:

app.v1.js
app.v2.js
Enter fullscreen mode Exit fullscreen mode

or content hashes:

app.abc123.js
app.72fd91.js
Enter fullscreen mode Exit fullscreen mode

This is one of the most common production CDN techniques.


36. Request collapsing

CloudFront can reduce duplicate origin requests when simultaneous requests for the same object and same cache key arrive at an edge while the object is not available.

Conceptually:

1,000 simultaneous requests
            |
            v
       CloudFront
            |
            +---- one origin fetch
            |
            v
     response shared with
     waiting requests
Enter fullscreen mode Exit fullscreen mode

This is called request collapsing.

It only helps when requests share the same cache key.

If you unnecessarily fragment the cache key:

user=A -> key A
user=B -> key B
user=C -> key C
Enter fullscreen mode Exit fullscreen mode

the requests are no longer equivalent for this purpose.


37. Cache hit ratio

A useful metric:

Cache Hit Ratio =
Cache Hits / Total Cacheable Requests
Enter fullscreen mode Exit fullscreen mode

Example:

1,000 requests
800 hits
200 misses
Enter fullscreen mode Exit fullscreen mode

Then:

Hit ratio = 80%
Enter fullscreen mode Exit fullscreen mode

Higher hit ratio generally means more requests are served from edge cache and fewer reach the origin.

But:

Do not optimize hit ratio at the expense of correctness or security.

A 99.9% hit ratio with users receiving incorrect/private data is a terrible architecture.


38. Production cache hierarchy

A useful mental model is:

Viewer
   |
   v
CloudFront POP / Edge
   |
   v
Regional Edge Cache
   |
   v
Origin
Enter fullscreen mode Exit fullscreen mode

The exact internal routing is managed by AWS, but conceptually CloudFront provides geographically distributed caching layers between viewers and the origin.

The key point is that your application does not need to manually manage these edge caches.


39. CloudFront + S3

Classic architecture:

User
 |
 v
CloudFront
 |
 v
S3
 |
 +--> index.html
 +--> app.js
 +--> styles.css
 +--> images/
Enter fullscreen mode Exit fullscreen mode

For production, keep the S3 bucket private and allow CloudFront to access it using Origin Access Control (OAC).

Conceptually:

Internet
   |
   v
CloudFront
   |
   | OAC
   v
Private S3
Enter fullscreen mode Exit fullscreen mode

This avoids making the S3 bucket itself the public application entry point.


40. CloudFront + ALB + EC2

Common architecture:

Internet
   |
   v
CloudFront
   |
   v
ALB
   |
   +--> EC2-1
   +--> EC2-2
   +--> EC2-3
Enter fullscreen mode Exit fullscreen mode

Responsibilities:

CloudFront

  • CDN
  • Edge caching
  • Global delivery
  • Viewer-facing TLS
  • WAF integration
  • Routing by cache behavior

ALB

  • Load balancing
  • Health checks
  • Distribution across instances

EC2

  • Application execution
  • Business logic

Keeping these responsibilities separate is important when designing AWS architectures.


41. CloudFront + WAF

AWS WAF can inspect requests before they reach the application.

Conceptually:

User
 |
 v
CloudFront
 |
 v
WAF rules
 |
 +---- malicious -> BLOCK
 |
 +---- valid ----> cache/origin
Enter fullscreen mode Exit fullscreen mode

Possible protections include:

  • SQL injection rules
  • XSS-related rules
  • Rate limiting
  • IP restrictions
  • AWS managed rule groups
  • Custom rules

WAF does not replace application authentication and authorization.


42. Production techniques checklist

Technique 1 — Version static assets

app.abc123.js
styles.72fd12.css
Enter fullscreen mode Exit fullscreen mode

Use long TTLs where appropriate.

Technique 2 — Separate static and dynamic paths

/static/*
/images/*
/api/*
Enter fullscreen mode Exit fullscreen mode

Give each a suitable behavior.

Technique 3 — Minimize cache-key dimensions

Avoid unnecessary:

  • Cookies
  • Headers
  • Query strings
  • Tracking IDs

Technique 4 — Use Origin Request Policy appropriately

Forward information required by the origin without automatically turning every value into a cache-key dimension.

Technique 5 — Choose TTL by freshness requirements

Stable static -> long
Frequently changing -> short
Private -> usually not shared cached
Enter fullscreen mode Exit fullscreen mode

Technique 6 — Use OAC for private S3 origins

CloudFront -> OAC -> private S3
Enter fullscreen mode Exit fullscreen mode

Technique 7 — Use WAF

Protect public CloudFront endpoints.

Technique 8 — Monitor

Useful signals include:

  • Cache hit ratio
  • Request count
  • Cache misses
  • Origin request volume
  • Origin latency
  • 4xx/5xx errors
  • WAF blocked requests

43. Common mistakes

Mistake 1 — Include every cookie in the cache key

This can create huge cache fragmentation.

Mistake 2 — Ignore personalization

This can cause incorrect or unsafe response reuse.

Mistake 3 — Use huge TTLs everywhere

This creates stale-content problems.

Mistake 4 — Use tiny TTLs everywhere

This destroys much of the CDN benefit and increases origin load.

Mistake 5 — Confuse Cache Policy and Origin Request Policy

Remember:

Cache Policy
    = What affects cache identity?

Origin Request Policy
    = What additional information goes to origin?
Enter fullscreen mode Exit fullscreen mode

Mistake 6 — Rely only on invalidation

Versioned assets are often cleaner for deployments.

Mistake 7 — Make S3 public unnecessarily

Use OAC for a private CloudFront-backed S3 origin.


44. Production mini architecture

A strong production-style architecture:

                         Internet
                            |
                            v
                       CloudFront
                            |
              +-------------+-------------+
              |                           |
          /static/*                    /api/*
              |                           |
              v                           v
             S3                         ALB
                                          |
                                     EC2/ECS
                                          |
                                      Database
Enter fullscreen mode Exit fullscreen mode

Security:

CloudFront
    |
    +--> AWS WAF
    |
    +--> OAC for S3
    |
    +--> HTTPS/TLS
Enter fullscreen mode Exit fullscreen mode

Caching:

/static/*
    Long TTL
    Versioned assets

/api/public/*
    Carefully configured caching

/api/cart/*
    No/shared cache

/api/profile/*
    No/shared cache
Enter fullscreen mode Exit fullscreen mode

45. Practice Lab 1 — Basic CloudFront + S3

Objective

Understand:

  • Distribution
  • S3 origin
  • Edge cache
  • Cache HIT/MISS
  • TTL
  • Invalidation

Tasks

  1. Create an S3 bucket.
  2. Upload index.html.
  3. Put:
CloudFront Version 1
Enter fullscreen mode Exit fullscreen mode

inside it.

  1. Create a CloudFront distribution with S3 as origin.
  2. Access the CloudFront URL.
  3. Change the S3 object to:
CloudFront Version 2
Enter fullscreen mode Exit fullscreen mode
  1. Request through CloudFront again.
  2. Observe whether the old response is still available.
  3. Create an invalidation for the object.
  4. Request again.

Questions

  • Why didn't the origin update necessarily appear immediately?
  • What did invalidation change?
  • What would happen if the TTL were much shorter?

46. Practice Lab 2 — Observe HIT/MISS

Objective

Understand the difference between first request and subsequent requests.

Tasks:

  1. Request a static object through CloudFront.
  2. Request it again.
  3. Inspect relevant response/log information.
  4. Identify HIT/MISS behavior.
  5. Compare the conceptual path of each request.

Expected mental model

First:
Viewer -> CloudFront -> MISS -> Origin -> Cache -> Viewer

Later:
Viewer -> CloudFront -> HIT -> Viewer
Enter fullscreen mode Exit fullscreen mode

47. Practice Lab 3 — Query-string cache key

Create responses for:

/products?id=10
/products?id=20
Enter fullscreen mode Exit fullscreen mode

Configure the relevant query string in the cache policy.

Test:

/products?id=10
/products?id=20
/products?id=10
Enter fullscreen mode Exit fullscreen mode

Expected conceptual result if starting from empty cache:

10 -> MISS
20 -> MISS
10 -> HIT
Enter fullscreen mode Exit fullscreen mode

Then remove the query-string distinction and reason about what could go wrong.


48. Practice Lab 4 — Personalized response safety

Create a simple application that returns:

Cookie: user=A
-> Hello A
Enter fullscreen mode Exit fullscreen mode

and:

Cookie: user=B
-> Hello B
Enter fullscreen mode Exit fullscreen mode

First understand the dangerous design where the cache key does not distinguish the personalized response.

Then redesign it safely.

Goal

Understand:

A high cache hit ratio is worthless if the cache returns the wrong user's response.


49. Practice Lab 5 — Cache Policy vs Origin Request Policy

Build a request such as:

GET /products?id=10
Cookie: analytics_id=ABC
Enter fullscreen mode Exit fullscreen mode

Goal:

CACHE KEY:
    /products?id=10

ORIGIN REQUEST:
    /products?id=10
    Cookie: analytics_id=ABC
Enter fullscreen mode Exit fullscreen mode

Then repeat with:

Cookie: analytics_id=XYZ
Enter fullscreen mode Exit fullscreen mode

Verify conceptually that:

Cache identity remains reusable
Enter fullscreen mode Exit fullscreen mode

while:

Origin still receives the required information
Enter fullscreen mode Exit fullscreen mode

This is one of the highest-value CloudFront labs for interviews.


50. Practice Lab 6 — TTL experiment

Create an object with a short TTL.

Change the origin content.

Observe:

Before expiry
    -> cached content can remain

After expiry
    -> CloudFront needs fresh/validated origin content
Enter fullscreen mode Exit fullscreen mode

Then invalidate it manually.

Compare:

TTL
vs
Invalidation
Enter fullscreen mode Exit fullscreen mode

51. Practice Lab 7 — Cache behaviors

Create:

/static/*
/api/*
Enter fullscreen mode Exit fullscreen mode

Configure:

/static/*
    Aggressive caching

/api/*
    No/shared-cache disabled or carefully configured
Enter fullscreen mode Exit fullscreen mode

If possible:

S3 -> /static/*
ALB/EC2 -> /api/*
Enter fullscreen mode Exit fullscreen mode

This will connect CloudFront with the EC2/ALB work you have already done.


52. Practice Lab 8 — Private S3 + OAC

Architecture:

User
 |
 v
CloudFront
 |
 | OAC
 v
Private S3
Enter fullscreen mode Exit fullscreen mode

Tasks:

  1. Create a private S3 bucket.
  2. Upload an object.
  3. Create CloudFront.
  4. Configure OAC.
  5. Configure the S3 bucket policy.
  6. Verify CloudFront access.
  7. Verify direct public S3 access is not allowed.

53. Practice Lab 9 — CloudFront + ALB + EC2

Use:

User
 |
 v
CloudFront
 |
 v
ALB
 |
 +--> EC2-1
 +--> EC2-2
Enter fullscreen mode Exit fullscreen mode

Create:

/static/*
/api/*
Enter fullscreen mode Exit fullscreen mode

and reason about which traffic should be cached and which should remain dynamic.

This connects CloudFront to:

  • VPC
  • ALB
  • EC2
  • Security Groups
  • Application architecture
  • CDN caching

54. Practice Lab 10 — Production-style mini project

Build:

                         User
                           |
                           v
                      CloudFront
                           |
              +------------+------------+
              |                         |
          /static/*                  /api/*
              |                         |
              v                         v
             S3                       ALB
                                        |
                                   EC2 instances
                                        |
                                      App/API
Enter fullscreen mode Exit fullscreen mode

Add:

  • S3 private access through OAC
  • Cache behavior for static assets
  • Different behavior for API
  • Cache policy
  • Origin request policy
  • TTL
  • Invalidation
  • WAF
  • HTTPS/custom domain if available
  • Logging/monitoring

Test:

1. Static asset HIT
2. Static asset MISS
3. API request
4. Query-string variation
5. Cookie behavior
6. TTL expiry
7. Invalidation
8. Origin failure
9. Security restrictions
Enter fullscreen mode Exit fullscreen mode

55. Interview revision

What is CloudFront?

CloudFront is AWS's CDN. It delivers content from geographically distributed edge locations and caches reusable origin responses closer to users, reducing latency and origin load.

What is a cache hit?

A cache hit occurs when the viewer request maps to a valid cached object, so CloudFront can return it without fetching that object from the origin.

What is a cache miss?

A cache miss occurs when CloudFront cannot find a valid matching cached object, so it obtains the object from the origin and can cache the response.

What is a cache key?

The cache key identifies a cached object. It can include the path and, when configured, selected query strings, headers, and cookies.

Cache Policy vs Origin Request Policy?

Cache Policy controls what contributes to the cache key and TTL behavior. Origin Request Policy controls additional headers, cookies, and query strings that CloudFront sends to the origin without necessarily making them part of the cache key.

Why can including too many cookies be bad?

It creates many cache variants, reduces cache reuse and can lower the cache hit ratio.

Why can excluding a response-changing cookie be dangerous?

Different users can map to the same cache object and potentially receive the wrong personalized response.


56. Final mental model

Memorize this flow:

                VIEWER REQUEST
                       |
                       v
                  CloudFront
                       |
                Build cache key
                       |
                       v
                 Cache lookup
                  /         \
               HIT           MISS
                |              |
                v              v
             Cached         Origin
             object            |
                |              v
                |          Response
                |              |
                |              v
                |          Cache it
                |              |
                +------<--------+
                       |
                       v
                    Viewer
Enter fullscreen mode Exit fullscreen mode

And this distinction:

Cache Policy
    |
    +--> What makes requests different?
    |
    +--> How long can objects be cached?

Origin Request Policy
    |
    +--> What additional information does origin need?
Enter fullscreen mode Exit fullscreen mode

The single most useful rule:

Cache only what can safely be reused, make the cache key vary only on information that changes the response, and choose TTL according to the required freshness.


-

Top comments (0)