From netlify-skills
Guides Netlify CDN caching: Cache-Control headers, stale-while-revalidate, cache tags, on-demand purges, durable cache, vary keys, and Next.js ISR patterns.
npx claudepluginhub netlify/context-and-tools --plugin netlify-skillsThis skill uses the workspace's default tool permissions.
**Static assets** are cached automatically:
Guides designing CDN architectures, caching strategies, and global content distribution. Covers cache hierarchies, origin shielding, invalidation, and edge optimization.
Guides HTTP caching with Cache-Control directives, ETag/Last-Modified validation, and Vary headers. Useful for API endpoints, CDN debugging, cache invalidation, and PR reviews.
Guides Vercel Runtime Cache API for ephemeral per-region KV caching with tag-based invalidation in Functions, Routing Middleware, and Builds. For strategies beyond framework caching.
Share bugs, ideas, or general feedback.
Static assets are cached automatically:
max-age=0, must-revalidate)Dynamic responses (functions, edge functions, proxied) are not cached by default. Add cache headers explicitly.
Three headers control caching, from most to least specific:
| Header | Who sees it | Use case |
|---|---|---|
Netlify-CDN-Cache-Control | Netlify CDN only (stripped before browser) | CDN-only caching |
CDN-Cache-Control | All CDN caches (stripped before browser) | Multi-CDN setups |
Cache-Control | Browser and all caches | General caching |
// Cache at CDN for 1 hour, browser always revalidates
return new Response(body, {
headers: {
"Netlify-CDN-Cache-Control": "public, s-maxage=3600, must-revalidate",
"Cache-Control": "public, max-age=0, must-revalidate",
},
});
// Stale-while-revalidate (serve stale for 2 min while refreshing)
return new Response(body, {
headers: {
"Netlify-CDN-Cache-Control": "public, max-age=60, stale-while-revalidate=120",
},
});
// Durable cache (shared across edge nodes, serverless functions only)
return new Response(body, {
headers: {
"Netlify-CDN-Cache-Control": "public, durable, max-age=60, stale-while-revalidate=120",
},
});
For fingerprinted files (hash in filename):
# netlify.toml
[[headers]]
for = "/assets/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
Tag responses for selective cache invalidation:
return new Response(body, {
headers: {
"Netlify-Cache-ID": "product,listing",
"Netlify-CDN-Cache-Control": "public, s-maxage=86400",
},
});
Purge by tag:
import { purgeCache } from "@netlify/functions";
export default async () => {
await purgeCache({ tags: ["product"] });
return new Response("Purged", { status: 202 });
};
Purge entire site:
await purgeCache();
Responses with Netlify-Cache-ID are excluded from automatic deploy-based invalidation — they must be purged explicitly.
Customize what creates separate cache entries:
return new Response(body, {
headers: {
"Netlify-Vary": "cookie=ab_test|is_logged_in",
// Other options: query=param1|param2, header=X-Custom, country=us|de, language=en|fr
},
});
ISR uses Netlify's durable cache automatically (runtime 5.5.0+). revalidatePath and revalidateTag trigger cache purge.
Full control over cache headers in server routes. Set Netlify-CDN-Cache-Control in responses for CDN caching.
Default Nitro preset handles caching. ISR-style patterns use routeRules with swr or isr options.
Static assets are cached by default. API responses from Netlify Functions need explicit cache headers.
Check the Cache-Status response header:
HIT — served from cacheMISS — generated freshREVALIDATED — stale content was revalidatedNetlify-Vary headers across responses