Prompt
How do I set cache rules so frequent deploys don't break things?
Latest observation
To keep frequent deploys from breaking due to cached assets, the usual goal is:
- Never cache HTML too aggressively
- Cache static assets very aggressively
- Use versioned filenames for assets
- Set up a deploy strategy that avoids mixing old HTML with new assets
Recommended cache rules
1) HTML / app shell
For pages that reference assets:
Cache-Control: no-cacheor a very short TTL- This lets browsers re-check for updates frequently
Example:
Cache-Control: no-cache, must-revalidate
If you use a CDN, you can also set HTML to:
Cache-Control: public, max-age=0, must-revalidate
2) Static assets with content hashes
For files like JS/CSS/images that change only when the content changes:
- Use hashed filenames, e.g.:
app.8f3c1a.jsstyles.a91b22.css
Then serve them with long-lived caching:
Cache-Control: public, max-age=31536000, immutable
This works well because when content changes, the filename changes too.
3) Avoid caching unversioned assets
If a file keeps the same name but its contents change, don’t cache it long-term.
Example:
Cache-Control: no-cache
or
Cache-Control: max-age=60
4) Invalidate CDN cache on deploy if needed
If you must keep stable URLs, make sure deploys purge the CDN for changed files. But hashed filenames are usually better than purging.
Safe default setup
A common setup is:
- HTML:
Cache-Control: no-cache - JS/CSS/images with hashed names:
Cache-Control: public, max-age=31536000, immutable
This prevents the browser from using old HTML for too long while allowing static assets to be cached heavily.
Extra deployment tip: avoid partial deploy states
Frequent deploys can break when:
- old HTML points to new assets not yet available
- new HTML points to assets that haven’t propagated to CDN yet
To avoid this:
- upload assets first
- then switch/replace HTML
- or deploy atomically using a versioned release directory
- or use blue/green deployments
Example Nginx config
location ~* \.(js|css|png|jpg|jpeg|gif|svg|webp|woff2)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
location ~* \.html$ {
add_header Cache-Control "no-cache, must-revalidate";
}
Example for CloudFront / CDN
- Cache static assets by filename hash for a year
- Set HTML to no-cache
- If needed, invalidate only HTML or the top-level shell on deploy
If you tell me what stack you’re using (Nginx, Apache, S3/CloudFront, Vercel, Netlify, React/Vite/Next.js, etc.), I can give you exact cache headers/config.