S3, CloudFront, and caching notes
Cache keys, invalidations, immutable assets, browser caching defaults, and how to avoid stale docs after deploys.
Takeaway
Cache immutable assets aggressively, keep HTML and metadata easy to refresh, and invalidate only the paths that can actually go stale.
01
Separate assets from documents
Hashed JavaScript, CSS, and media can use long-lived cache headers. HTML, sitemap, robots, and metadata routes should be easier to refresh because they represent the current public surface.
The deploy pipeline should treat these two classes differently. Immutable assets reward aggressive caching; documents need freshness when content, navigation, or metadata changes.
- Cache hashed static assets for a long duration with immutable semantics.
- Use shorter or explicitly invalidated caching for HTML and metadata routes.
- Check sitemap and robots after content changes, not only after code changes.
02
Know the cache key
CloudFront cache behavior depends on path, query strings, headers, cookies, and compression settings. Write down what varies before debugging a stale response so the team does not invalidate blindly.
A stale response is easier to diagnose when the team knows whether the CDN, browser, origin, or application cache is responsible.
- Record whether query strings are forwarded for pages that use shareable search state.
- Avoid cookie-based variation unless the route truly needs it.
- Compare a normal request with a cache-busting request before invalidating broad paths.
03
Invalidate with intent
A full distribution invalidation is simple but slow and noisy. Prefer targeted invalidations for changed HTML, sitemap, robots, and content pages, then smoke test with a cache-busting request if needed.
Targeted invalidations also create a better release note because they reveal which public surfaces were expected to change.
- Invalidate changed routes and generated metadata paths.
- Avoid invalidating immutable asset prefixes unless the deploy process is broken.
- Keep post-invalidation smoke URLs in the release checklist.