moxie/caching-deep-dive

Caching deep dive

Route entries reference a caching key. The Router merges the matching policy from src/settings/caching/ into the response so CloudFront (and browsers) can cache consistently.

Mental model

  • Application-defined policies — not ad-hoc Cache-Control strings in every handler.
  • Policies typically include max-age, stale-while-revalidate, and stale-if-error (exact fields live in the JSON files — treat this page as conceptual).
  • Route chooses which bucket; policy file chooses TTL strategy.

Common policy names

Policy (typical) TTL / behavior (conceptual) Good for
standard Short default (e.g. minutes) Most JSON / JSON:API content
mobile Similar to standard, separate bucket Mobile-specific tuning without touching standard
liveblog Fresher updates Liveblogs and fast-moving editorial
disabled Minimal caching / noindex-style Debug-like or highly sensitive responses

Exact numbers belong in src/settings/caching/*.json — do not duplicate magic numbers in handlers.

Choosing a policy

  • Editorial homepage / section — usually standard or mobile depending on route.
  • Live tickers / blogs — prefer liveblog when stale content is unacceptable.
  • Partner RSS — often standard or dedicated partner policies if split out.
  • One-off experimentaldisabled only when you explicitly need to avoid CDN stickiness (discuss with team — impacts cost and origin load).

Stale-while-revalidate

  • Lets CDNs serve slightly stale content while fetching fresh copy in the background — improves perceived latency.
  • stale-if-error shields users from origin blips.

Operational checks

  • Compare CDN age headers vs policy when debugging “old data” — use ?debugga= and identity env to ensure you hit the expected stage/prod origin.
  • Changing caching affects all routes using that policy — review blast radius.