Cache Controls & Policies
Intelligent Cache-Control headers with per-context TTLs, stale directives, and smart policies.
How It Works
Cacheability Pro sets Cache-Control response headers based on the type of content being served. This tells your reverse proxy (Varnish, Nginx, CDN) how long to cache each response.
Per-Context TTLs
Configure different cache durations for each content type:
| Context | Default TTL | Description |
|---|---|---|
| Homepage | 14 days | Front page |
| Single Posts | 14 days | Blog posts |
| Pages | 14 days | Static pages |
| Archives | 14 days | Category, tag, date archives |
| Search | 1 hour | Search results pages |
| 404 | 1 hour | Not found pages |
| Feeds | 14 days | RSS/Atom feeds |
| WooCommerce Products | 14 days | Product pages |
| WooCommerce Categories | 14 days | Product category pages |
Stale Directives
- stale-while-revalidate - Serve stale content while fetching a fresh copy in the background. Eliminates cache miss latency for visitors.
- stale-if-error - Serve stale content if the origin server is down. Keeps your site available during outages.
Pagination Boost
Deeper paginated pages (page 2, 3, etc.) get progressively longer TTLs. This is because deeper pages change less frequently and receive less traffic, so longer caching is safe and reduces origin load.
Scheduled Post TTL Reduction
When a post is scheduled for future publication, Cacheability Pro automatically reduces TTLs on affected archive pages so the new post appears promptly when published.
Redirect Caching
Cache 301 and 308 redirects with configurable TTLs. This reduces origin requests for permanent redirects.
Age Multiplier
Older posts get progressively longer cache TTLs since their content is less likely to change.
Excluding Transactional Pages (cacheability_pro_skip)
Some pages must never inherit the blanket cache policy — payment-success and
checkout-confirmation pages, one-time download links, anything that renders
per-request state. Historically these pages tried to override the header with a
late header('Cache-Control: …') call inside the template, but that only wins
when PHP output buffering is on; with output_buffering=0 the call is a silent
no-op and the page is cached for the full TTL.
The cacheability_pro_skip filter is the deterministic fix. Return true and
Cacheability Pro gets out of the way entirely for that request:
- it sets no
Cache-Controlheader, so the page's ownheader()call (or an earlierwp_headersfilter) stays authoritative; and - the page is never written to the Full-Page Cache, so it can't be stored or served from the disk/Redis cache either.
add_filter( 'cacheability_pro_skip', function ( $skip ) {
// Never cache the payment-success page.
return is_page( 'checkout-thank-you' ) ? true : $skip;
} );
The filter runs during wp_headers (the queried object is already known, so
is_page(), is_singular(), etc. work) and again at full-page-cache store time,
so a single hook covers both layers.
Already deployed a cached copy?
The opt-out stops new stores; an entry cached before you added the hook is served until it expires. Flush the Full-Page Cache once after deploying the opt-out for a URL that was previously cached.
The free Cacheability plugin exposes the same opt-out under the name
cacheability_skip (header layer only — the free plugin has no Full-Page Cache).