Caching & Edge
The fastest response is one you don’t compute
Section titled “The fastest response is one you don’t compute”Static pages are already the ideal case: built once, served from a CDN, cached everywhere. The interesting question is what to do when a route is rendered on demand — you don’t want to re-run the render for every visitor if the result is the same for a while. That’s what caching is for: turn a repeated render into a cheap lookup.
Cache-Control on on-demand responses
Section titled “Cache-Control on on-demand responses”For a route rendered on demand (prerender = false), you set caching headers on the response. The browser and any CDN in front of your server will then reuse the response instead of hitting your render again:
---export const prerender = false;
// Cache this response at the CDN for 1 hour; allow serving a stale copy// for a day while revalidating in the background.Astro.response.headers.set( 'Cache-Control', 'public, max-age=0, s-maxage=3600, stale-while-revalidate=86400');
const articles = await getArticles();---<ArticleList articles={articles} />The key directives: s-maxage controls how long a shared cache (the CDN) keeps it, and stale-while-revalidate lets the CDN serve a slightly-stale copy instantly while it refreshes in the background — so users almost never wait on a cold render.
Edge caching
Section titled “Edge caching”A CDN caches responses at edge locations near users, so a cached page is served from a nearby city rather than your origin. A static Astro site is edge-cached by nature. An on-demand site becomes edge-friendly the moment you add the right Cache-Control — the CDN caches the rendered HTML at the edge and only calls your server when the cache expires.
flowchart LR user["User request"] --> edge["CDN edge"] edge -->|cache hit| fast["Serve cached HTML (fast)"] edge -->|cache miss| origin["Origin renders, then caches at edge"] origin --> edge
The powerful pattern: cacheable shell + server islands
Section titled “The powerful pattern: cacheable shell + server islands”Pure per-request SSR is hard to cache — if the page contains “Welcome back, Ana,” you can’t share that response with the next visitor. The elegant fix combines what earlier modules taught: make the page shell static/cacheable, and defer only the personalized part to a server island (server:defer).
---// This page is static and fully cacheable at the edge...---<Layout> <ArticleList /> <!-- same for everyone: cached --> <UserGreeting server:defer> <!-- per-user: deferred, fetched separately --> <p slot="fallback">Loading…</p> </UserGreeting></Layout>Now the heavy, shared part is cached at the edge and served instantly, while the tiny personalized island is rendered per request. You get CDN-speed pages and personalization — instead of making the whole page uncacheable for the sake of one greeting.
When static-with-islands beats full SSR
Section titled “When static-with-islands beats full SSR”If a page is mostly the same for everyone with a few dynamic bits, static (or cached) + islands almost always beats full SSR: better cacheability, less server load, faster responses. Reserve full on-demand rendering for pages that are genuinely different on every request (a personalized dashboard, search results). Choosing the cacheable option is itself a performance decision.