
Caching Strategy for Static and Hybrid Sites
A decision framework for choosing cache headers, CDN rules, and invalidation strategies across fully static, ISR, and hybrid rendering architectures.
Caching is the single most effective performance lever for sites that serve pre-built content. Get it right and your pages load in milliseconds from edge nodes worldwide. Get it wrong and users see stale content, broken deployments, or—worst case—cached error pages that refuse to go away.
This article is a 2026 operator's guide to caching strategy for static and hybrid sites. It covers Cache-Control headers, CDN-layer configuration, stale-while-revalidate patterns, and validation workflows. It is written for site operators, front-end engineers, and DevOps practitioners who deploy to CDN platforms and need to understand the mechanics.
The caching for static sites guide on this site covers foundational concepts. This article goes deeper into 2026-specific patterns, especially for sites that mix static exports with dynamic or personalised elements. The web fundamentals path provides broader context on web performance, and the web development hub links to related front-end resources.
If you have been following the performance series, the earlier articles on INP optimisation, main-thread work, and performance budgets address the client-side half of the equation. This article covers the network and server side.
The three-layer caching model
For most static and hybrid sites, caching happens at three layers:
- Browser cache: controlled by
Cache-Controlheaders on the response. The browser stores the resource locally and reuses it without any network request until it expires. - CDN edge cache: the CDN stores a copy at each edge node. Requests from users near that node are served directly without hitting your origin.
- Origin cache: some setups include a caching reverse proxy at the origin (Varnish, Nginx microcache) as a buffer against cache misses reaching the application server.
For fully static sites, the origin layer is often unnecessary—the CDN is your primary cache and your build output is the origin.
Cache-Control headers: what to set where
Immutable assets (JS, CSS, fonts, images with hashed filenames)
These files change content whenever their hash changes, so the filename is the cache key.
Set Cache-Control: public, max-age=31536000, immutable. This tells both the browser and CDN to cache the file for one year and never revalidate. When you deploy a new version, the HTML references a new filename, and the old cached file is simply never requested again.
HTML pages
HTML is the entry point that references all other assets. It must be fresh enough to point to the correct versioned assets after a deployment.
For static sites that deploy infrequently (daily or weekly): Cache-Control: public, max-age=300, stale-while-revalidate=3600. The page is fresh for 5 minutes, and for the next hour the CDN can serve the stale version while fetching a fresh one in the background.
For sites that deploy multiple times per day: Cache-Control: public, max-age=60, stale-while-revalidate=600. Shorter fresh period, shorter stale window.
API responses (hybrid sites)
If your site has dynamic API routes that return JSON, caching depends on the data freshness requirements:
- Public, infrequently changing data:
Cache-Control: public, max-age=300, s-maxage=600 - User-specific data:
Cache-Control: private, no-store - Data that should be cached at the CDN but not the browser:
Cache-Control: public, s-maxage=600, max-age=0
Stale-while-revalidate in practice
The stale-while-revalidate directive is one of the most useful caching tools for content sites. It lets the CDN (and browser) serve a stale response immediately while fetching a fresh one in the background. The user gets instant load times, and the next request gets fresh content.
The pattern works well for:
- Blog posts and articles that update occasionally
- Topic index pages that change when new content is published
- Sitemaps and RSS feeds
It does not work well for:
- Shopping cart or checkout pages
- Real-time data (stock prices, live scores)
- Pages with user-specific content in the HTML
Cache invalidation strategies
Purge on deploy
Most CDN platforms support a "purge all" or "purge by path" API. Wire this into your deployment pipeline so that every deploy clears stale HTML from the edge. Hashed assets do not need purging—they have unique filenames.
Surrogate keys (cache tags)
Advanced CDN platforms let you tag cached responses with custom keys. When content changes, you purge by tag instead of by path. This is useful when a single content change affects multiple pages (e.g., a topic hub and every article in that topic).
Time-based expiry
For sites without deploy-triggered purging, rely on short max-age values for HTML (60–300 seconds). The trade-off is that users may see stale content for up to that duration after a deploy.
Validation workflow
After configuring caching, validate with these checks:
- Deploy and check response headers. Use
curl -Ior browser DevTools to confirmCache-Controlvalues on HTML, JS, CSS, and images. - Verify cache hit ratios. Check your CDN analytics dashboard. Aim for 90%+ cache hit ratio on static assets and 70%+ on HTML.
- Test a deploy cycle. Deploy a content change, purge (if applicable), and confirm the updated content appears within your expected freshness window.
- Test error handling. Verify that 404 and 500 responses are not cached (or are cached with very short TTLs). A cached error page is one of the most damaging caching mistakes.
Common mistakes
- Caching HTML for too long without a purge mechanism. If you set
max-age=86400on HTML and deploy a broken asset reference, users are stuck with a broken page for 24 hours. - Setting
no-cachewhen you meanno-store.no-cachestill caches the response but revalidates on every request.no-storeprevents caching entirely. Know the difference. - Ignoring
Varyheaders. If your server sends different responses based onAccept-EncodingorCookie, make sure the appropriateVaryheader is set. Otherwise the CDN may serve a gzip response to a client that requested brotli, or vice versa. - Forgetting about service worker caches. If your site uses a service worker, it has its own cache that ignores CDN and server headers. Make sure the service worker's cache strategy is aligned with your server-side caching.
Trade-offs
- Longer cache TTLs improve performance but increase stale content risk. Find the right balance for your deploy frequency and content sensitivity.
- CDN purging adds deployment complexity. Simple
max-age + stale-while-revalidatemay be sufficient for sites that deploy once daily. - Caching at multiple layers compounds debugging difficulty. When content is stale, you need to check browser cache, service worker cache, CDN cache, and origin cache to find where the stale copy lives.
Further reading on EBooks-Space
- Caching for Static Sites guide — foundational caching concepts and header recipes
- Web Development topic hub — curated front-end reading lists
- Web Fundamentals learning path — structured path from basics to deployment
- Fast Sites for Readers guide — broader performance principles for content sites