Cache-Control headers
P2Lab Cache controls four independent cache lifetimes on every cacheable response. Get the combination wrong and you’ll either over-cache stale content at the edge or under-cache and lose the speed benefit.
All four are configured under Settings → Speed Boost → Dashboard → Configuration.
The four lifetimes
Section titled “The four lifetimes”Server TTL (serverTtl)
Section titled “Server TTL (serverTtl)”How long the entry lives inside your origin’s cache (Filesystem / Redis / APCu). Default 1 day.
When this expires, the next request triggers a regeneration regardless of any HTTP header.
Set this to your “maximum tolerable staleness” — how long it’s acceptable for a page to sit in cache without anyone touching it.
Cache-Control: max-age (browser)
Section titled “Cache-Control: max-age (browser)”How long the browser is allowed to reuse the cached response without re-validating against your origin. Default 0 (no browser cache).
0 means every page load hits your origin (which then likely serves from cache — fast — but the round-trip happens). Bump to e.g. 300 (5 minutes) if you want the browser to skip the round-trip for a short window.
Cache-Control: s-maxage (shared cache)
Section titled “Cache-Control: s-maxage (shared cache)”How long a shared cache between the browser and your origin (Varnish, Nginx, a CDN that doesn’t understand CDN-Cache-Control) is allowed to reuse the response. Default 6 hours.
When Varnish receives a response with s-maxage: 21600, it stores the response for 6 hours and serves subsequent requests from its own memory — without ever hitting your origin (unless an explicit purge fires).
CDN-Cache-Control: max-age (CDN-only)
Section titled “CDN-Cache-Control: max-age (CDN-only)”A CDN-specific directive recognised by Cloudflare, Fastly and Akamai. Default disabled (header not sent).
The value applies only at the CDN and only to those CDNs that understand it. Browsers and other shared caches ignore the header.
Use when you want different cache durations at the CDN vs other shared caches (e.g. 1 day at the CDN, 6 hours at Varnish).
How they combine
Section titled “How they combine”For each request, the cache layers act independently:
[Browser] ←─ Cache-Control: max-age=0 ↓[CDN] ←─ CDN-Cache-Control: max-age=86400 ↓[Varnish] ←─ Cache-Control: s-maxage=21600 ↓[Origin / P2Lab Cache] ←─ serverTtl=86400 ↓[Shopware render]A typical “fast but accurate” setup:
serverTtl: 86400(1 day — long, since invalidation purges anyway)max-age: 0(let the browser always check)s-maxage: 21600(Varnish serves for 6 hours, then re-fetches)CDN-Cache-Control: 86400(CDN serves for 1 day; CDN purge on deploy)
A “max speed, accept some staleness”:
serverTtl: 86400max-age: 300(browser holds for 5 minutes)s-maxage: 86400(Varnish holds for 1 day; deploys must trigger purges)CDN-Cache-Control: 86400
A “always fresh, no staleness”:
serverTtl: 3600max-age: 0s-maxage: 0CDN-Cache-Control: disabled
Sales-channel scope
Section titled “Sales-channel scope”All four are per sales channel. Typical: a B2B channel with s-maxage: 0 (no shared caching) and a B2C channel with longer durations.
What about invalidation?
Section titled “What about invalidation?”The four lifetimes are expiry-based. Invalidation is event-based and runs independently:
- A product save with Smart invalidation purges the affected entries from the origin cache immediately, regardless of
serverTtl. - An xkey purge to Varnish drops the response from Varnish immediately, regardless of
s-maxage. - The browser is not purged —
max-agestill applies. Setmax-age: 0if you can’t tolerate browser-cached stale pages. - The CDN is purged only if you have set up CDN purges separately (we don’t ship that integration out of the box).
Per-route overrides
Section titled “Per-route overrides”The plugin sets the same headers on every cacheable response. To override for a specific route (e.g. lower s-maxage for a stock-sensitive page), add a custom event subscriber that mutates the response.