HTTP Caching Revalidation & Invalidation Playbook

2026-03-15 · software

HTTP Caching Revalidation & Invalidation Playbook

Date: 2026-03-15
Category: knowledge

Why this matters

Most teams don't fail at HTTP caching because they forgot max-age. They fail because cache behavior is inconsistent across browser, CDN, and origin, and because invalidation strategy is vague until incident day.

Typical symptoms:

This playbook gives a practical, production-first model for cache correctness.


Mental model: split cache policy by asset class

Treat these as different products, not one policy:

  1. Versioned static assets (hashed JS/CSS/images)
  2. HTML/document shells
  3. Personalized or sensitive responses
  4. API responses (public vs user-scoped)

If you apply one blanket policy, you'll either serve stale critical content or give up most cache efficiency.


Recommended baseline policies

1) Versioned static assets (best cache hit ratio)

Use filename/content hash and long TTL.

Example:

Cache-Control: public, max-age=31536000, immutable

Why:

Rule: never mutate content behind the same hashed URL.

2) HTML / app shell (fast updates, still cache-friendly)

Use short freshness + revalidation + stale shields.

Example:

Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=30, stale-if-error=600
ETag: "..."

Interpretation:

3) Personalized/sensitive responses

Use strict no-store for truly sensitive data.

Cache-Control: no-store

For user-scoped but cacheable in browser only:

Cache-Control: private, no-cache

(no-cache means revalidate before reuse, not “do not cache at all”).

4) Public API responses

For stable public data, combine moderate TTL + validators:

Cache-Control: public, max-age=120, s-maxage=300, stale-while-revalidate=30
ETag: "..."
Vary: Accept-Encoding

Avoid overusing Vary; each added dimension multiplies cache key cardinality.


Revalidation correctness checklist

A cache strategy is only as good as validator discipline.

  1. Emit strong validators where possible
    • Prefer stable, deterministic ETag generation per representation.
  2. Honor conditional requests correctly
    • If-None-Match / If-Modified-Since should return 304 only when representation truly unchanged.
  3. Keep validator scope aligned with variants
    • If response varies by locale/device/encoding, validator must reflect that representation.
  4. Avoid weak timestamp-only logic for highly dynamic responses
    • clock skew + coarse granularity can cause false 304s.

Invalidation strategy: purge surgically, not globally

Global purge is a recovery tool, not a deploy routine.

Prefer tag/key-based purge:

Pattern:

Benefits:


Anti-patterns that cause incidents

  1. no-store everywhere
    • correctness is easy, performance collapses.
  2. Long TTL on mutable HTML without validators
    • stale deploys and support tickets.
  3. Unbounded Vary dimensions
    • cache fragmentation, low hit ratios.
  4. Purge-everything as default deploy step
    • origin load spikes and unstable latency.
  5. ETag generated from non-deterministic metadata
    • phantom cache misses and revalidation churn.

30-day rollout plan

Week 1 — Inventory + classification

Week 2 — Validator and policy hardening

Week 3 — Tag-based purge adoption

Week 4 — Observability and guardrails

Track:

Set guardrails:


Practical header templates

Versioned static file

Cache-Control: public, max-age=31536000, immutable

SSR/HTML page (non-personalized)

Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=30, stale-if-error=600
ETag: "<stable-representation-hash>"
Vary: Accept-Encoding

Authenticated profile page

Cache-Control: private, no-cache
Vary: Cookie, Accept-Encoding

Sensitive account/checkout endpoint

Cache-Control: no-store

Bottom line

Good HTTP caching is an operations contract:

Do this well and you get both speed and correctness. Skip it and your CDN becomes a randomizer.


References

  1. RFC 9111 — HTTP Caching (obsoletes RFC 7234)
    https://www.rfc-editor.org/rfc/rfc9111.html
  2. RFC 5861 — HTTP Cache-Control Extensions for Stale Content (stale-while-revalidate, stale-if-error)
    https://www.rfc-editor.org/rfc/rfc5861
  3. RFC 8246 — HTTP Immutable Responses (immutable)
    https://www.rfc-editor.org/rfc/rfc8246.html
  4. MDN Cache-Control reference (practical directive behavior)
    https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control
  5. Cloudflare docs — Purge by cache tags (Cache-Tag)
    https://developers.cloudflare.com/cache/how-to/purge-cache/purge-by-tags/
  6. Fastly docs — Working with surrogate keys (Surrogate-Key)
    https://www.fastly.com/documentation/guides/full-site-delivery/purging/working-with-surrogate-keys/