Astro, set caching headers
By Flavio Copes
A quick reference for setting caching headers in Astro, using Astro.response.headers.set to send a Cache-Control header like public, max-age=3600.
To set caching headers in Astro, use Astro.response.headers.set() in the frontmatter of your page. Writing this down for reference:
Astro.response.headers.set('Cache-Control', 'public, max-age=3600')
This tells browsers (and any CDN in front of your site) to cache the page for one hour. public means shared caches can store it too, and max-age=3600 is the lifetime in seconds.
Where to put it
Astro.response is available in the frontmatter of any .astro page. A full page looks like this:
---
Astro.response.headers.set('Cache-Control', 'public, max-age=3600')
const posts = await getPosts()
---
<html>
<!-- your page -->
</html>
You can set any header this way, not just Cache-Control. It’s the same Headers object you’d use with fetch().
This only works with on-demand rendering
Here’s the catch. Astro.response only has an effect on pages rendered on demand, on the server, at request time.
If your page is prerendered (the default in a static Astro site), there’s no server responding to the request. Your host serves a plain HTML file, and the host decides the headers. The Astro.response.headers.set() line runs at build time and its result is thrown away.
If you set the header and it never shows up in the browser devtools, check this first. The page is probably static.
For static pages, set headers at the hosting level. On Cloudflare Pages and Netlify that’s a _headers file in your public folder:
/blog/*
Cache-Control: public, max-age=3600
API endpoints
In an endpoint you don’t have Astro.response. You return a Response object, so you pass the headers there:
export async function GET() {
return new Response(JSON.stringify({ status: 'ok' }), {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, max-age=60'
}
})
}
Same rule applies: this matters when the endpoint runs on demand.
Picking the right Cache-Control value is its own topic. public, max-age=3600 is a good default for pages that change rarely. For pages that must always be fresh, use no-store. If you need a different caching policy, I built a free Cache-Control header builder that puts together the right directives for you.
Related posts about astro: