
How to configure caching headers on Netlify
Introduction
Caching is one of the biggest performance wins you can get on the web, but it’s also one of the easiest things to get wrong. Cache too aggressively and users see stale content. Cache too little and you lose most of the benefit of a CDN.
Netlify gives you fine-grained control over HTTP headers so you can tune caching behavior exactly the way your site needs. In this guide, you’ll learn how Netlify headers work, how to configure them, and how to apply sensible caching strategies for common use cases.
How Netlify handles caching
Netlify sits in front of your site as a global CDN. By default:
- Static assets like images, JS, and CSS are cached aggressively
- HTML is cached conservatively to avoid serving stale pages
- The CDN respects standard HTTP cache headers
You can override and customize this behavior by defining headers explicitly.
Ways to define headers on Netlify
There are two supported ways to configure headers:
- Using a
_headersfile - Using
netlify.toml
Both approaches are equivalent in terms of capabilities. Choose the one that fits your workflow.
Using the _headers file
The _headers file lives at the root of your published site (usually the build output directory).
Example structure:
/public
|_ index.html
|_ _headers
Basic syntax:
/path
Header-Name: value
Another-Header: value
Example: cache static assets aggressively
/assets/*
Cache-Control: public, max-age=31536000, immutable
This tells browsers and Netlify’s CDN to cache files for one year and never revalidate them.
This works best when filenames include a hash (for example, app.83hd73.js).
Using netlify.toml
If you prefer configuration in code, netlify.toml is usually the better option.
Example:
[[headers]]
for = "/assets/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
This is especially useful for larger projects or monorepos.
Common caching strategies
HTML pages
HTML usually changes more often than assets, so cache it carefully.
Recommended:
/*
Cache-Control: public, max-age=0, must-revalidate
This ensures users always get fresh HTML while still allowing CDN optimization.
Static assets (JS, CSS, images)
For hashed assets:
/assets/*
Cache-Control: public, max-age=31536000, immutable
For non-hashed assets, lower the cache duration.
API responses
If you’re serving JSON or API-like responses:
/api/*
Cache-Control: public, max-age=60
This allows short-term caching while keeping data reasonably fresh.
Security-related headers
Headers aren’t just for caching. You can also improve security.
Example:
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
You can define these alongside caching rules.
Debugging caching issues
If changes don’t appear immediately:
- Check the response headers in your browser’s dev tools
- Verify the file path matches your rule
- Make sure your build output actually includes
_headers - Redeploy the site after changes
Netlify applies headers at deploy time, not dynamically.
When headers don’t apply
Headers won’t apply if:
- The
_headersfile is not in the published directory - The path pattern doesn’t match the requested URL
- Another rule overrides it later in the file
Order matters: more specific rules should come before generic ones.
Final thoughts
Correct caching can drastically improve performance, reliability, and user experience. Netlify gives you powerful tools to control it, without needing custom infrastructure or complex CDN setups.
Once you’re comfortable with headers, you can combine them with redirects, rewrites, and deploy previews to build fast, production-grade sites with confidence.
Manage Netlify on the go
Download Netli.fyi and monitor your sites, check deploys, and manage your projects from anywhere.


