CDN
Intermediate 14 min read CDN

Cache Invalidation & TTL

Staleness is a trade, not a bug

TTLs decide how long stale-but-accepted content lives; invalidation is the emergency brake that forces fresh checks. Versioned assets make long TTLs safe; unversioned paths make invalidation a daily ritual.

TTLcache-controlinvalidationpurgeorigin shieldrevalidation
Prerequisites: CDN Basics
Before we start

What you will learn

  • Model how TTL, staleness and revalidation interact
  • Choose between purge/invalidation and cache-busting filenames
  • Compose Cache-Control directives (max-age, s-maxage, must-revalidate, immutable)
In 60 seconds

The edge trusts Cache-Control. max-age sets how long a hit is served without asking; s-maxage overrides it for shared caches (CDNs); must-revalidate forces revalidation before reuse even on stale; immutable lets middle hops skip revalidation for hashed assets. Invalidation purges cached copies so the next fetch is a miss and refreshes from origin.

Introduction

What is this?

Cache-Control directives: public, private, no-store (auth/personal), max-age=<s>, s-maxage=<s>, stale-while-revalidate, immutable, must-revalidate. Edge behavior: fresh (serve), stale + revalidate (ask origin w/ If-None-Match/If-Modified-Since → 304 → serve + refresh TTL), expired hard (miss). Invalidation: CloudFront create-invalidation, Front Door cache purge, Cloud CDN invalidateCache — costs and propagation vary. Cache busting: hash in filename (app-1a2b3c.js) → infinite TTL, never needs purge; no-store for dynamic routes.

Motivation

Why do you need it?

  • Wrong TTLs are the #1 'we changed it but users still see the old version' outage class.
  • Purging entire distributions on every deploy is slow and expensive; versioning avoids it.
  • Revalidation (304s) keeps freshness cheap instead of full origin re-downloads.
  • Stale-while-revalidate hides origin latency behind freshly-aging caches.
Think about it

Mental model

Imagine

Bakery selling bread with a best-before date

Think of

TTL on cached responses

Happy customers take the loaf within the date (max-age); a few minutes past it, staff re-check the kitchen before selling (stale revalidation); truly expired bread is thrown out and re-baked (cache miss → origin).

Mechanics

How it works

  • Origin sets Cache-Control on each response; the edge records freshness age.
  • While age < max-age the edge serves without contacting origin.
  • At expiry, edge revalidates: If-None-Match → 304 (fresh copy, keep bytes) or 200 (new bytes).
  • Invalidation marks the object for immediate purge; the next request is a miss.
  • Versioned assets let you set long TTLs and avoid blocking invalidations entirely.

Edges of staleness.

Origin
Edge
Expiry
304
Purge
Origin
Hands-on

Examples

Production-grade cache headers

Production-grade cache headers
# hashed bundle → cache forever-ish
Cache-Control: public, max-age=31536000, immutable
# index.html → short TTL so deploys propagate quickly
Cache-Control: public, max-age=300, s-maxage=60, must-revalidate
# API user profile → never cache at the edge
Cache-Control: private, no-store

One header per content class: immutable for versioned blobs, short revalidating TTL for the entry HTML, no-store for anything personalized.

Real world

In production

  • Deploy pipeline writes hashed bundles with immutable headers; index.html gets a 5-minute TTL.
  • E-commerce images use max-age=86400 + signed invalidation on price/render updates.
  • News APIs use stale-while-revalidate so spikes read slightly-stale but never queue on origin.
Guidelines

Best practices

  • Set explicit cache metadata at the source (S3 upload, build step) — don't patch it in the CDN.
  • Prefer versioned URLs over mass invalidation; reserve purges for rollbacks and corrections.
  • Use s-maxage to differ edge vs browser caching on the same object.
  • Automate invalidation in the deploy pipeline, gated on the exact changed paths.
  • Test with curl after each release: x-cache and Age reflect the intended freshness.
Watch out

Common mistakes

  • max-age=0 with nothing else → cacheable but revalidates constantly, hammering origin.
  • Forgetting s-maxage/cache key variations so A/B variants serve each other's bytes.
  • Invalidating 100k paths when five hashed filenames changed (slow + hot).
  • Letting <meta http-equiv> or URL hacks (&#38;nocache) do the job of real headers.
When things break

Debugging tips

  • curl -sI: Age grows every second a hit is served; Age: 0 on every call ⇒ always missing.
  • Look for a 304 not cache hit on repeat calls — origin is still being hit, just cheaply.
  • Inspect the actual Cache-Control the origin returns with curl before blaming the edge.
  • Vary / Content-Length mismatches between edge and origin points to corrupted cached bytes.
Interviews

Interview checkpoint

Practice

Hands-on lab

Measure Cache-Control Without an Exploding Cache
30 min · beginner
In progress
Objectives
  • Serve the same object with different Cache-Control values
  • Observe fresh, stale, and revalidated states in real-time
  • Understand what a CDN can and cannot do without proper headers

Measure Cache-Control Without an Exploding Cache

30 min · beginner

0/3 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/2
1

Which header is ignored by CDNs (they use s-maxage instead)?

2

A 304 revalidation response lets the edge reuse its cached copy and only refreshes validity.

Go deeper

Official documentation