Two gears: freshness (max-age — serve without asking) and validation (ETag — cheap 304). Hashed statics + no-cache/ETag for HTML/API = 90% solved.
Разбор
Three cache states:
max-age not expired stale, ETag matches stale, changed
FRESH ─────────────────────▶ serve ─────────────▶ 304 (revalidate) ──────▶ 200 (full body)
(0 network) (headers only, tiny) (full download)
- Freshness — skip network?
Cache-Control: max-age.
- Validation — stale but changed? Conditional
If-None-Match → 304 or full 200.
Orthogonal: max-age decides whether to ask; ETag decides how cheap the ask.
Итог
Layer freshness for speed, validation for correctness at stable URLs.