Render Caching
When to Use
When you need to cache rendered output of render arrays. Render caching stores the final rendered HTML along with cache metadata, avoiding expensive re-rendering on subsequent requests.
Steps
-
Add cache keys to render array — Define unique identifier for this cacheable content
Cache keys must uniquely identify the render array. Contexts will create variations automatically.$build = [ '#theme' => 'my_template', '#cache' => [ 'keys' => ['my_module', 'component', $entity->id()], ], ]; -
Add cache metadata (tags, contexts, max-age)
All three metadata properties required for proper caching.$build['#cache']['tags'] = ['node:' . $entity->id()]; $build['#cache']['contexts'] = ['user.roles']; $build['#cache']['max-age'] = Cache::PERMANENT; -
Render the array — Renderer checks cache, serves cached if available
Renderer handles cache lookup, storage, and metadata bubbling automatically.$output = \Drupal::service('renderer')->render($build); -
Cache metadata bubbles up — Child metadata merges with parent
No manual metadata copying needed; renderer handles bubbling.$parent = [ 'child' => $build, // Child metadata automatically bubbles to parent ];
Decision Points
| At this step... | If... | Then... |
|---|---|---|
| Defining cache keys | Content varies by parameter | Include parameter in keys array: ['my_module', $type, $id] |
| Defining cache keys | Content varies by context (user, language) | Use cache contexts, not keys: contexts create variations automatically |
| Adding cache tags | Using entity data | Add entity cache tags: $entity->getCacheTags() |
| Adding cache contexts | Content differs per user/URL/language | Add appropriate contexts: ['user.roles', 'url.path'] |
| Setting max-age | Content updates on schedule | Set expiration in seconds: max-age => 3600 |
| Setting max-age | Content updates when entity changes | Use Cache::PERMANENT and rely on cache tags |
Common Mistakes
- Forgetting cache keys — Render cache not used (no unique identifier to look up)
- Using contexts in keys — Creates separate cache entry per variation instead of using Drupal's context system
- Manually copying child cache metadata to parent — Renderer does this automatically through bubbling
- Rendering without cache metadata — Content cached with wrong tags/contexts, serves stale data
- Setting cache keys on non-cacheable elements — Waste (elements like
#markupwithout#cachekeys don't cache)
See Also
- BubbleableMetadata & Cache Bubbling — How metadata bubbles
- Cache Metadata Trinity — Required metadata properties
- Reference:
/core/lib/Drupal/Core/Render/RenderCache.php