-
Deployment
Set the right cache headers on static assets and HTML
Cache aggressively for assets that never change and carefully for HTML, so users don't get stuck on old versions.
Free Prompt
Set correct cache headers on my app's responses. Right now they're probably either wildly permissive (users stuck on an old version for a week) or wildly conservative (revalidating every request and paying for it in latency).
Do this in three groups:
1. Fingerprinted static assets (JS/CSS bundles with content hashes in their filenames, hashed image URLs): serve with Cache-Control: public, max-age=31536000, immutable. Once the hash changes on next deploy, the URL is different, so caching forever is safe and free.
2. Non-fingerprinted static assets (favicon, robots.txt, sitemap): shorter max-age, maybe an hour or a day, so they can be updated without a stampede but aren't hit constantly.
3. HTML documents: Cache-Control: no-cache (must revalidate) plus a strong ETag. This means the browser has to check with the server, but the server can return 304 Not Modified cheaply if nothing changed. Do not cache HTML aggressively; that's the bug where users see an old version after a deploy that never goes away.
Also:
4. Authenticated responses: Cache-Control: private, no-store on anything that includes user data. A shared CDN caching one user's dashboard and serving it to another is a real, embarrassing bug.
5. API responses: default no-store unless a specific endpoint is genuinely public and stable. Then, short max-age with a stale-while-revalidate if the platform supports it.
6. CDN vs browser: use s-maxage for CDN-level caching separately from browser max-age when that distinction matters (e.g., long CDN cache but short browser cache with revalidation).
Don't set aggressive caching on anything that changes without a URL change. The deliverable is the headers applied by asset type, verified with curl -I on a few representative URLs, and a quick doc noting the strategy so it doesn't drift.
What This Does / How This Helps
This sets cache headers correctly per asset type: forever for fingerprinted static assets, brief with revalidation for HTML, and no-store for authenticated or dynamic responses. Getting this wrong is either 'the app is slow because nothing is cached' or, worse, 'a user saw another user's dashboard because the CDN cached it'. The fingerprint-and-cache-forever pattern for static assets is a huge free performance win; the no-store-for-private-data rule prevents leaking user data through a caching layer. Both are one-time setup that keeps paying.
Want to skip doing this by hand?
Fortivibe audits your app for all of the areas these prompts cover (and more).