Netlify Caching Headers: _headers File and netlify.toml Configuration

Netlify Caching Headers: _headers File and netlify.toml Configuration

Perttu Lähteenlahti
Updated March 11, 20263 min read
headerscachingperformancecdn
Share:

Caching is one of the biggest performance wins on the web, and also one of the easiest things to mess up. Cache too aggressively and users see stale content. Cache too little and you're wasting your CDN. I've managed to do both on the same project.

Netlify gives you fine-grained control over HTTP headers, so you can tune caching behavior for different file types. Here's how to set it up without shooting yourself in the foot.

How Netlify caches things by default

Netlify's CDN sits in front of your site. Out of the box:

  • Static assets (images, JS, CSS) get cached aggressively
  • HTML gets cached conservatively so visitors don't see stale pages
  • Standard HTTP cache headers are respected

For many sites, the defaults are fine. But if you want more control — say, immutable caching for hashed assets or short TTLs for API responses — you'll need to set headers explicitly.

Two ways to set headers

You can use either a _headers file or netlify.toml. They do the same thing.

The _headers file

Drop it in your publish directory (wherever Netlify serves from — usually public/, dist/, or build/).

/assets/*
  Cache-Control: public, max-age=31536000, immutable

netlify.toml

If you prefer keeping config in one place:

[[headers]]
  for = "/assets/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"

I tend to use netlify.toml for larger projects because everything's in one file. For a quick static site, _headers is less ceremony.

Caching strategies that actually work

HTML pages: don't cache aggressively

HTML changes often. You want browsers to check for updates every time:

/*
  Cache-Control: public, max-age=0, must-revalidate

This tells the browser "always revalidate with the server." Netlify's CDN is fast enough that this doesn't hurt performance — the CDN still caches the page, it just checks if it's changed.

Hashed assets: cache forever

If your bundler produces files like app.83hd73.js (with a content hash in the filename), you can cache them aggressively:

/assets/*
  Cache-Control: public, max-age=31536000, immutable

One year, immutable. When the content changes, the hash changes, so the browser fetches the new file. This is the ideal caching setup — zero unnecessary requests for assets that haven't changed.

Important: this only works if your filenames include hashes. If you're serving app.js without a hash, don't set immutable or users will be stuck with stale code.

API responses: short TTL

If you're serving JSON from Netlify Functions:

/api/*
  Cache-Control: public, max-age=60

One minute. Keeps things reasonably fresh while avoiding hammering your functions on every request.

Security headers

While you're setting up headers, you might as well add the security basics:

/*
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin

These prevent clickjacking, MIME type sniffing, and leaking referrer information. They cost nothing and take 30 seconds to add.

When your headers aren't working

If your headers aren't showing up, check these in order:

  1. Open browser dev tools — Network tab, click a request, look at response headers
  2. Is _headers in the right folder? — It has to be in the published directory, not the project root. This is the most common mistake.
  3. Do your path patterns match?/assets/* won't match /static/assets/app.js
  4. Did you redeploy? — Netlify applies headers at deploy time, not dynamically
  5. Check rule ordering — more specific rules need to come before generic ones, just like redirects

I've spent way too long debugging a caching issue that turned out to be _headers sitting in the project root instead of dist/.

Perttu Lähteenlahti

Perttu Lähteenlahti

Developer Advocate at RevenueCat and creator of Netli.fyi. Building on Netlify since 2019. Writes from hands-on experience deploying dozens of production sites.

Manage Netlify on the go

Download Netli.fyi and monitor your sites, check deploys, and manage your projects from anywhere.

Related articles