D11 Pipeline: Caching & BigPipe
Caching Layers & BigPipe
Drupal 11 ships multiple interlocking caching strategies: Internal Page Cache (anonymous full-page), Dynamic Page Cache (context-aware), render cache (element-level), and BigPipe for streaming personalised content.
Layer | Scope | Users | Storage | Invalidation |
|---|---|---|---|---|
Internal Page Cache | Full page response | Anonymous only |
| Cache tags |
Dynamic Page Cache | Full page, context-aware | All users |
| Cache tags + contexts |
Render Cache | Individual render elements | All users |
| Cache tags + contexts + max-age |
BigPipe Placeholders | Uncacheable sub-trees only | All (session-aware) | Streamed inline | Per-request (max-age=0) |
Stores complete
Response objects keyed by URL + request headers.cache.page. The entire render pipeline (Phases ②–⑤) is bypassed entirely.PageCacheSubscriber stores the response on KernelEvents::RESPONSE if it is cacheable (max-age > 0, no user-specific contexts).Cookie session header disables it. BigPipe is also not involved at this layer.Works for both anonymous and authenticated users. Key = URL + resolved cache contexts.
BubbleableMetadata. Invalidated when any referenced cache tag is cleared.renderer.config services.yml. Any render element meeting the conditions belowis automatically replaced with a placeholder during Phase ⑤, regardless of whether BigPipe is active.
<drupal-render-placeholder> HTML elements in the non-BigPipe case (replaced server-side before response is sent), or <span data-big-pipe-placeholder-id="…"> elements streamed to the browser when BigPipe is active.Non-personalized HTML skeleton is sent first; personalized/uncacheable parts are streamed after.
<span data-big-pipe-placeholder-id="…"></span> elements (or with #lazy_builder_preview content inside).#lazy_builder callback (a service method) to produce the actual render array, which is then rendered through the full Renderer pipeline (Phase ⑤).<script> that calls Drupal.bigPipe.setPageState() or uses a small DOM replacement script to inject the HTML into the placeholder <span>.</body></html>. Total flush count = 1 (skeleton) + N (one per placeholder).For anonymous users without a session, BigPipe uses a no-JS fallback: placeholders become data-big-pipe-nojs-placeholder-id attributes, resolved server-side before response ends. This is transparent to the browser — no JavaScript required for the skeleton content.
DynamicPageCacheSubscriber stores the render array (with placeholders) at this point.HtmlResponse headers are set (X-Drupal-Cache-Tags, X-Drupal-Cache-Contexts, Cache-Control).Response is sent to the client. Then
KernelEvents::FINISH_REQUEST and kernel.terminate fire for async cleanup.