CDN caching infrastructure diagram

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.

cachingcdnstatic-sitescache-controlstale-while-revalidate

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:

  1. Browser cache: controlled by Cache-Control headers on the response. The browser stores the resource locally and reuses it without any network request until it expires.
  2. 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.
  3. 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:

  1. Deploy and check response headers. Use curl -I or browser DevTools to confirm Cache-Control values on HTML, JS, CSS, and images.
  2. Verify cache hit ratios. Check your CDN analytics dashboard. Aim for 90%+ cache hit ratio on static assets and 70%+ on HTML.
  3. Test a deploy cycle. Deploy a content change, purge (if applicable), and confirm the updated content appears within your expected freshness window.
  4. 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=86400 on HTML and deploy a broken asset reference, users are stuck with a broken page for 24 hours.
  • Setting no-cache when you mean no-store. no-cache still caches the response but revalidates on every request. no-store prevents caching entirely. Know the difference.
  • Ignoring Vary headers. If your server sends different responses based on Accept-Encoding or Cookie, make sure the appropriate Vary header 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-revalidate may 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