Caching System - Render Cache

Render Cache in Drupal stores the final rendered HTML of components (render arrays) so they don’t need to be rebuilt on every request.

At scale, this is where most performance wins come from — caching fragments (blocks, views, components) instead of rebuilding them repeatedly.

In Level 5 architecture, Render Cache is not just “on/off” — it’s about correct metadata, safe variation, and precise invalidation.


Core Concept

Drupal builds pages using render arrays. Each render array carries cache metadata.

Build Render Array
   ↓
Attach Cache Metadata (#cache)
   ↓
Render to HTML
   ↓
Store in cache_render
   ↓
Next request → return cached HTML

Render Cache Architecture

Controller / Block / View
        ↓
Render Array (+ #cache metadata)
        ↓
Render Cache (cache_render bin)
        ↓
HTML Fragment

Real Project Example (Enterprise)

Homepage components:

  • Hero banner
  • Latest news (View)
  • Alerts
  • Featured content

Each component is cached separately.

Request
   ↓
Hero → cached
News → cached
Alerts → cached
   ↓
Assemble page fast

Critical Concept: Cache Bubbling

Cache metadata bubbles up from child to parent.

If a child is uncacheable, it breaks the parent cache.

Child max-age = 0
   ↓
Parent becomes uncacheable ❌

Example:

$child['#cache']['max-age'] = 0; // kills parent caching

This is one of the most common production issues.


Cache Metadata is Additive

Drupal does NOT override cache metadata — it merges it.

Parent: max-age 3600
Child: max-age 600

Result → 600 (lowest wins)

Same applies to:

  • tags → merged
  • contexts → combined

Always think entire render tree, not individual components.


Solution for Dynamic Content: Lazy Builder

Instead of disabling cache, use #lazy_builder.

$build['user_block'] = [
  '#lazy_builder' => ['my_module.service:getData', [$uid]],
  '#create_placeholder' => TRUE,
];

Benefits:

  • page remains cached
  • dynamic part loads separately
  • safe personalization

This is the correct pattern for advanced Drupal builds.


Cache Contexts (Granularity Matters)

Choosing the right context is critical.

ContextImpact
userone cache per user (expensive)
user.rolesshared by role (better)
url.pathper page
languagesper language

Wrong context = cache explosion


Full Cache Lifecycle (Real Flow)

Render Component
   ↓
Attach tags (node:42)
   ↓
Store in cache_render
   ↓
Cache HIT (fast)
   ↓
Node updated
   ↓
Invalidate node:42
   ↓
Rebuild component

Code:

Cache::invalidateTags(['node:42']);

Developer Usage

$build = [
  '#markup' => 'Example',
  '#cache' => [
    'max-age' => 600,
    'tags' => ['node:42'],
    'contexts' => ['user.roles'],
  ],
];

Debugging Render Cache

Advanced debugging tools:

  • add ?cache=0 → bypass cache
  • check cache_render table/bin
  • use Webprofiler → see cache hits/misses
  • inspect $build['#cache'] via debug tools

If you can’t debug cache, you can’t scale Drupal.


Platform / DevOps Layer

Render cache must align with infrastructure.

Redis config example:

$settings['cache']['bins']['render'] = 'cache.backend.redis';

Flow:

Render Cache (Redis)
   ↓
Varnish / CDN
   ↓
User

CI/CD:

  • avoid full cache rebuild
  • rely on tag invalidation

Performance Strategy

Best practices:

  • cache all reusable components
  • avoid max-age 0 unless required
  • use lazy builder for dynamic parts
  • keep contexts minimal

Common Production Issues

  • cache bubbling breaks pages
  • missing tags → stale content
  • too many contexts → low cache hit
  • no lazy builder → disabled caching
  • CDN not aligned with Drupal

AI / Future Integration

  • predictive component caching
  • AI-based cache warming
  • edge rendering optimization

Render Cache in Drupal stores rendered HTML fragments of components to avoid rebuilding them on every request. It uses cache metadata including tags, contexts, and max-age, which bubble through the render tree. Advanced usage includes lazy builders for dynamic content and proper cache debugging and invalidation strategies.


Practice Questions

  1. What is Render Cache?
  2. What is cache bubbling?
  3. Why is #lazy_builder important?
  4. How does metadata merging work?
  5. How do you debug render cache?

Memory Trick

Render Cache = Component HTML
Bubbling = Child controls parent
Lazy Builder = Safe dynamic
Tags = Invalidate
Contexts = Vary
Max-Age = Expire