Full-page caching is the secret sauce that lets you serve even dynamically generated HTML pages at CDN speeds, making your website feel impossibly fast for every single user, every single time.
Let’s watch this in action. Imagine a typical e-commerce product page.
GET /products/super-widget-123 HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 ...
Accept: text/html,...
HTTP/1.1 200 OK
Cache-Control: public, max-age=3600
Content-Type: text/html
X-Cache-Status: HIT
Content-Length: 8542
... (HTML content for Super Widget 123) ...
See that X-Cache-Status: HIT? That’s the magic. Instead of hitting your origin server, processing database queries, rendering templates, and assembling HTML for every request, the CDN just served a pre-built copy of that page. The max-age=3600 tells the CDN to keep this copy for an hour.
How it Works: The "Static" Dynamic Page
At its core, full-page caching treats dynamic HTML like static assets. When a user requests a page that could be dynamic (like /products/super-widget-123), the request first hits your CDN. The CDN checks its cache for a stored version of that exact URL.
- Cache HIT: If it finds one, it serves the stored HTML directly to the user. This is lightning fast, as the CDN is geographically closer to the user and doesn’t involve any server-side computation.
- Cache MISS: If it doesn’t find a stored version, the CDN forwards the request to your origin server. Your server then generates the HTML (fetches data, renders templates, etc.) and sends it back to the CDN. The CDN then caches this newly generated HTML (according to your caching rules, like
max-age) and serves it to the user. Subsequent requests for the same URL within the cache duration will be cache HITS.
This strategy is incredibly powerful because it offloads the vast majority of requests from your application servers, dramatically reducing load, latency, and infrastructure costs. It works best for content that doesn’t change on every single page load for every user, such as product pages, articles, or even personalized dashboards after the initial load.
Key Levers for Control
The primary control mechanism is your cache-control headers and your CDN’s configuration.
-
Cache-Control: public, max-age=<seconds>: This is crucial.publicallows intermediate caches (like CDNs) to store the response.max-agedefines how long the resource is considered fresh. For a product page that updates daily,max-age=86400(24 hours) is common. For content that changes hourly,max-age=3600. -
Vary Header: If your page content changes based on request headers (e.g.,
Accept-Language), you need to use theVaryheader.Vary: Accept-Encodingis standard for GZIP/Brotli compression.Vary: User-AgentorVary: Cookiecan cause issues with full-page caching as they create many cache keys, reducing cache efficiency. Avoid these if possible for full-page caching. -
CDN Rules: Your CDN provider (Cloudflare, Akamai, AWS CloudFront, etc.) will have specific settings to define cache behavior. You can often set default
max-agevalues, purge specific URLs or patterns, and configureVaryheader handling. For example, in Cloudflare, you might set a Page Rule like:- URL:
www.example.com/products/* - Setting: Cache Level: Cache Everything
- Setting: Edge Cache TTL: 1 week
- Setting: Browser Cache TTL: 2 hours
This tells Cloudflare to cache all responses for URLs matching
/products/*, store them at the edge for a week, and instruct browsers to cache them for 2 hours. - URL:
-
Cache Invalidation: When content does change (e.g., a product price update), you need to invalidate the cache. This means telling the CDN to delete the stale copy. Most CDNs provide APIs or dashboard options to purge specific URLs, URL patterns, or even the entire cache (use with caution!). A common pattern is to purge the specific product page URL whenever its data is updated in your CMS or database.
When to Use It (And When Not To)
Full-page caching is ideal for content that is:
- Read-heavy: Frequently accessed but infrequently updated.
- Not user-specific per request: While personalization can be added client-side, the base HTML should be the same for many users.
- Has a reasonable staleness tolerance: A few minutes or hours of outdated information is acceptable.
It’s generally not suitable for:
- Real-time data: Stock tickers, live sports scores.
- Highly personalized content: A shopping cart or user dashboard that changes with every click.
- Content that must be absolutely fresh: Unless you have a robust, near-instantaneous cache invalidation strategy.
The real power of full-page caching comes from its ability to make your application servers almost irrelevant for read traffic. When your CDN is serving 95% of your HTML directly from cache, your origin servers can handle 20x more traffic with the same resources, or you can scale down your infrastructure significantly.
Even with full-page caching, you’ll eventually encounter situations where your cache invalidation strategy isn’t perfect, leading to users seeing slightly stale data. The next problem you’ll grapple with is managing those edge cases and ensuring data consistency across your cached and origin layers.