Skip to main content

Cache-Control Headers

Set the right Cache-Control headers on your origin for optimal caching with ModPageSpeed 2.0.

Requires ModPageSpeed 2.0.x or later with conditional revalidation support. Without conditional revalidation, must-revalidate causes full origin re-fetches on every stale request. Upgrade before following these recommendations.

Your origin’s Cache-Control headers directly control how ModPageSpeed caches and serves your content. Getting these right eliminates stale content surprises and minimizes unnecessary origin traffic.

When your origin sends no Cache-Control header, ModPageSpeed applies configurable defaults (HTML: no-cache, CSS/JS: 300s, images: 3600s) and logs a warning. Setting explicit headers is better than relying on defaults.

HTML Pages

Cache-Control: public, max-age=60, must-revalidate
ETag: "content-hash-or-version"

HTML references hashed assets. A deploy changes HTML content to point at new asset URLs. Short max-age=60 provides one minute of caching. With conditional revalidation, stale requests are cheap — origin returns 304 when content hasn’t changed.

Use max-age=0 only when absolute real-time freshness is required (stock tickers, live scores). Every request with max-age=0 triggers a conditional revalidation, which means an origin round-trip even when content hasn’t changed.

Hashed Static Assets (CSS/JS with Fingerprints)

Cache-Control: public, max-age=31536000, immutable

The URL changes on every build. Content at a given URL never changes. ModPageSpeed respects immutable and caps the max-age at pagespeed_immutable_max_age (default: 7 days).

Non-Hashed Static Assets

Cache-Control: public, max-age=3600, must-revalidate
ETag: "file-mtime-and-size"

The URL is stable but content may change. Short max-age with must-revalidate keeps content fresh. Conditional revalidation makes the revalidation cheap.

User-Uploaded Images

Cache-Control: public, max-age=86400

User images rarely change at the same URL. 24-hour caching is reasonable. If images can be replaced at the same URL, add must-revalidate and an ETag.

API Responses and Dynamic Content

Cache-Control: no-store

ModPageSpeed does not cache no-store responses. The response passes through unchanged.

Framework Configuration

FrameworkWhere to Set HeadersHTMLHashed Assets
nginx (static)nginx.conf per locationmax-age=60, must-revalidatemax-age=31536000, immutable
Apache.htaccess Header setmax-age=60, must-revalidatemax-age=31536000, immutable
Next.js 13+next.config.js headers()max-age=60, must-revalidateAutomatic for _next/static/
Astro 4+Server adapter headersmax-age=60, must-revalidateAutomatic via content hashing
Rails 7+config.public_file_server.headersmax-age=60, must-revalidateAutomatic via Propshaft
WordPressCache plugin or .htaccessmax-age=60, must-revalidateTheme-dependent

PURGE vs Natural Expiration

PURGE immediately invalidates all cached variants for a URL. Use it for urgent content corrections. For routine deploys, let must-revalidate handle freshness naturally — conditional revalidation is cheaper than purge-and-rebuild because it preserves optimized image variants (AVIF, WebP) when only the HTML changed.

ModPageSpeed Directives

These directives control the default max-age values applied when origin responses lack a Cache-Control header. They do not override explicit origin headers.

pagespeed_html_max_age 0;      # Default for HTML (seconds, default: 0 = no-cache)
pagespeed_css_max_age 300;     # Default for CSS/JS (seconds, default: 300)
pagespeed_image_max_age 3600;  # Default for images (seconds, default: 3600)

When pagespeed_html_max_age is 0 and the origin sends no Cache-Control, HTML responses are served with Cache-Control: no-cache — the client must revalidate on every request.

Conditional Revalidation

pagespeed_conditional_revalidation on;   # default: on

When enabled, stale cache entries with stored ETag or Last-Modified values trigger conditional requests (If-None-Match / If-Modified-Since) instead of full re-fetches. On 304, the cached content is refreshed without re-downloading or re-optimizing. Disable only if your origin mishandles conditional requests.

Auditing Your Origin

The web console flags URLs where the origin sends no Cache-Control header. Use the URL inspector to check freshness status and identify origins that need explicit headers.