Setting up proper cache headers on Netlify
Configure precise HTTP cache headers on Netlify to maximize CDN edge performance and eliminate stale asset delivery. Proper configuration directly impacts Performance Optimization & Core Web Vitals for SSGs for production deployments. This guide provides exact _headers syntax, minimal reproduction steps for stale content bugs, and immutable caching strategies for fingerprinted assets.
Diagnosing Stale Asset Delivery & Cache Bypass
Verify header propagation using curl or browser DevTools. Incorrect headers often manifest as hydration errors or missing styles after a deployment.
Run the following command to inspect response headers for a specific asset:
curl -I https://your-site.netlify.app/asset.js
Check Netlify build logs for _headers parsing warnings. Reproduce stale scenarios by comparing soft-refreshes against hard-refreshes. Cross-reference your findings with established CDN Caching Rules for SSGs to understand edge behavior.
Configuring _headers for Immutable Assets
Apply long-term caching to fingerprinted JavaScript, CSS, images, and fonts. Fingerprinted files contain content hashes in their filenames, guaranteeing unique URLs per deployment.
Create a _headers file in your project root. Target glob patterns that match your asset directories. Set max-age=31536000 for a one-year TTL. Include the immutable directive to prevent unnecessary conditional requests.
/*.html
Cache-Control: public, max-age=0, must-revalidate
/assets/*
Cache-Control: public, max-age=31536000, immutable
/*.js
Cache-Control: public, max-age=31536000, immutable
/*.css
Cache-Control: public, max-age=31536000, immutable
/*.png
Cache-Control: public, max-age=31536000, immutable
This configuration locks static assets to edge memory while keeping HTML shells flexible. Frameworks like Astro, Hugo, Eleventy, and Jekyll output hashed assets by default. Ensure your build pipeline preserves these hashes before deployment.
HTML & Entry Point Revalidation Strategy
HTML files and routing entry points require a different caching strategy. Users must always fetch the latest document structure to avoid broken asset references.
Apply Cache-Control: public, max-age=0, must-revalidate to all HTML routes. This forces browsers to check with the CDN before serving a cached copy. It aligns perfectly with incremental regeneration patterns across modern SSGs.
Avoid no-store for HTML documents. That directive bypasses the CDN entirely, increasing origin load and degrading Time to First Byte (TTFB). The must-revalidate directive preserves edge caching while guaranteeing freshness checks.
Netlify Build & Deploy Header Validation
Netlify parses header configuration files during the build step. Invalid syntax triggers silent fallbacks to default one-hour caching rules.
Use the Netlify CLI to validate headers locally before pushing to production:
netlify dev
Deploy your changes and monitor the x-nf-request-id header in network responses. A HIT status confirms edge cache delivery. A MISS indicates the asset was fetched from the origin. Run netlify deploy to publish verified configurations.
Common Pitfalls
- Applying immutable to HTML files: Causes users to load outdated routing shells and stale asset references. This breaks navigation and triggers 404 errors on updated builds.
- Missing must-revalidate on HTML: Allows browsers to serve cached documents indefinitely. This bypasses Netlify’s CDN and delivers deprecated page structures.
- Incorrect glob syntax in
_headers: The Netlify parser is strict. Malformed globs result in silent header drops and default caching behavior. - Overriding headers via the UI: Netlify’s dashboard header rules lack granular control. Always use
_headersornetlify.tomlfor reliable, version-controlled deployments.
Frequently Asked Questions
How do I clear Netlify's CDN cache after updating headers?
Netlify automatically purges the cache on each successful deploy. For immediate local testing, append ?v=timestamp to URLs or use the dashboard’s Clear Cache button.
Why are my _headers rules being ignored?
Check for syntax errors, ensure the file resides at the project root, and verify it is not overridden by netlify.toml. Run netlify dev to inspect parsed headers locally.
Should I use no-cache or no-store for HTML?
Use no-cache (or max-age=0, must-revalidate). no-store bypasses the CDN entirely, increasing origin load and degrading TTFB for static sites.
How does Netlify handle immutable headers?
The CDN respects the immutable directive by skipping conditional If-Modified-Since requests. Assets serve directly from edge memory for faster subsequent loads.