Drupal
min read
Last update on

Mastering page and block Caching in Drupal

Mastering page and block Caching in Drupal
Table of contents

Slow pages lose users. For Drupal sites, smart caching flips that script, turning heavy, database-driven pages into quick, memory-efficient responses. Whether it’s a blog, nonprofit platform, or enterprise CMS, caching is essential to performance.

Picture this: a Drupal 10 site serving dynamic content to thousands daily. Without caching, every page view hits the backend, increasing load times and straining servers. With internal and dynamic caching in place, pages for anonymous and authenticated users are served in milliseconds, not seconds.

In this article, we’ll break down:

  • How internal page caching handles full-page delivery for anonymous users
  • How dynamic page caching serves partial responses for logged-in sessions
  • What developers need to know about cacheability at the block and component level

These aren’t optional tweaks. They’re foundational for performance, reliability, and scale.

Internal page Cache

Internal Page Cache is Drupal’s way of speeding up pages for anonymous users. When someone visits a page, Drupal saves the fully rendered HTML. If another user visits the same page, Drupal serves that saved version instantly, skipping the usual backend processing.

This reduces load times and server work, especially on high-traffic sites. It’s simple, fast, and only applies to users who aren’t logged in.

How it works

  • Complete HTML Storage: Stores a fully rendered HTML page in a dedicated cache bin.
  • Quick Retrieval: Anonymous user requests are served directly from the cache.
  • Automatic Invalidation: Content updates automatically clear the cache to ensure fresher content.

Further Reading:
Check out the official Internal Page Cache documentation for more details.

A practical use case: internal page Cache

The scenario

Imagine you manage a community news site that serves a large volume of anonymous visitors. Frequently, the site displays the same news articles repeatedly. Without caching, each page load requires Drupal to rebuild the entire page dynamically, which increases server load and slows down response times.

The goal

To optimise performance for anonymous users by reducing the processing time required for each page request. The aim is to serve fully rendered pages directly from the cache, thereby minimising database queries and PHP processing cycles.

Considerations

  • Consistency: Ensure that when content is updated (e.g., a breaking news update), the cache is properly invalidated.
  • Traffic pattern: Most visitors are anonymous, so the benefits of full page caching are maximised.
  • Cache Lifetime: Decide an appropriate max-age so that the page content stays fresh but does not require regeneration on every request.

Sample implementation

Although Internal Page Cache is largely managed by Drupal core, you can fine-tune certain configurations in your settings.php:

// In settings.php, set up the Internal Page Cache for anonymous users.
 $settings['cache']['bins']['page'] = 'cache.backend.internal_page_cache';

 // Optionally, configure the maximum age for cached pages.
 // This example sets the cache lifetime to 1 hour.
 $config['system.performance']['cache']['page']['max_age'] = 3600;

This configuration ensures that the full HTML page is cached and reused for subsequent requests. For more detailed guidelines, refer to the Internal Page Cache documentation.

Dynamic page Cache

Dynamic Page Cache is designed for handling pages for authenticated users, whose pages often include dynamic or personalised content. It caches page fragments instead of the entire page, making it possible to mix cached and dynamic content seamlessly.

Key characteristics

  • Fragment Caching: Caches parts of the page, so only static parts are served quickly.
  • Granular control: Uses cache tags to ensure that only the parts of the page affected by content changes are invalidated.
  • User personalisation: Supports customisation while still reusing cached fragments where applicable.

Further reading:
Visit the Dynamic Page Cache documentation for further details.

A practical use case: dynamic page Cache

The scenario

Consider an e-commerce platform where registered users see personalised information, such as greeting messages, recent order details, or custom promotions. In such cases, parts of the page remain the same across many users, while other parts vary.

The goal

To improve performance for authenticated users by caching as much of the page as possible without compromising personal or dynamic content. By caching static fragments, the platform reduces the load on the server while still delivering personalised content where necessary.

Considerations

  • User variation: Identify which parts of the page can be cached universally and which parts require dynamic processing.
  • Cache invalidations: Use cache tags so that changes in user-specific data (e.g., order updates) trigger appropriate cache invalidation.
  • Rendering balance: Find the right balance between speed and personalisation by considering the dynamic nature of user content.

Sample implementation

Dynamic Page Cache is enabled in Drupal core, but you can complement it by configuring it in your settings. For example, you might not change its default behavior in settings.php but ensure that your custom modules use cache tags and contexts appropriately when rendering parts of the page.

tags and contexts appropriately when rendering parts of the page.
// In settings.php, configure Dynamic Page Cache for authenticated pages.
 $settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.dynamic_page_cache';

In your custom module or theme, when rendering a personalized block, you might include cache metadata like this:

$build = [
   '#markup' => t('Welcome back, @user!', ['@user' => \Drupal::currentUser()->getDisplayName()]),
   '#cache' => [
     'tags' => ['user:' . \Drupal::currentUser()->id()],
     'contexts' => ['user.roles'],
     'max-age' => 1800,
   ],
 ];

This example ensures that while the personalised greeting is rendered dynamically, it still benefits from partial caching of related fragments. For more details, visit the Dynamic Page Cache documentation.

Block Caching strategies

Blocks are critical components of a Drupal site used in sidebars, headers, footers, and more. Proper caching of blocks can reduce server load considerably by ensuring that frequently used content is generated only once.

Cache Settings for Blocks

Drupal offers several caching configurations for blocks:

  • Global: Same cache applies to all pages (e.g., a universally consistent footer).
  • Per role: Different cached versions based on user role.
  • Per user: Custom caching for each individual user.
  • Custom/contextual: Tailored caching based on specific conditions such as language, region, or device type.

Further reading:
Learn more about block caching and cache tags on Drupal.org at Cache Tags.

A practical use case: block Caching

The scenario

Imagine you have a custom block on a dashboard that displays quick links and summary statistics. Since different user roles (such as administrators versus regular users) need to see different information, caching must be configured to account for these variations.

The goal

To cache the block efficiently while allowing for role-based customisations. The objective is to minimise repeated block rendering without serving incorrect data to different user types.

Considerations

  • User context: Determine if the block’s content should vary by user role or per individual.
  • Cache lifespan: Decide a suitable max-age for the block long enough to improve performance but short enough to keep the content current.
  • Invalidation strategies: Use cache tags to ensure that updates to the underlying data invalidate the cached block appropriately.

Sample implementation

Below are two examples. The first uses hook_block_alter() in a custom module to adjust the cache settings of an existing block, and the second shows how to define caching when creating a new block in your theme or module.

/**
  * Implements hook_block_alter().
  *
  * Use case: Adjusting cache settings for a block that shows role-specific dashboard information.
  */
 function mymodule_block_alter(&$blocks) {
   if (isset($blocks['my_custom_block']) && $blocks['my_custom_block']['id'] === 'my_custom_block') {
     $blocks['my_custom_block']['cache'] = [
       'max-age' => 3600,               // Cache for 1 hour.
       'contexts' => ['user.roles'],    // Cache varies by user role.
       'tags' => ['custom_dashboard'],
     ];
   }
 }

Alternatively, when defining a custom block:

/**
  * Implements hook_theme().
  */
 function mymodule_theme() {
   return [
     'my_cacheable_block' => [
       'render element' => 'content',
       'cache' => [
         'max-age' => 3600,              // Cache for 1 hour.
         'contexts' => ['user.roles'],   // Cache per user role.
       ],
     ],
   ];
 }

These examples ensure that the block content is cached efficiently while still allowing for customization based on user context.

Configuration examples

Below are additional examples that show how to enable and adjust page caching directly from your settings.php:

Enabling and configuring page Caching

// In settings.php:
 // Enable Internal Page Cache.
 $settings['cache']['bins']['page'] = 'cache.backend.internal_page_cache';

 // Configure Dynamic Page Cache for authenticated pages.
 $settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.dynamic_page_cache';

 // Set a maximum age for cached pages, e.g., 1 hour.
 $config['system.performance']['cache']['page']['max_age'] = 3600;

Performance considerations

Potential pitfalls

  • Over-aggressive Caching: Serving stale content if caches are not invalidated properly.
  • Underutilised Caching: Missing the opportunity to enhance performance by not caching frequently accessed elements.
  • Dynamic content challenges: Incorrect cache contexts can lead to personalisation issues.

Best practices

  • Leverage Cache tags: Use them for precise invalidation when content is updated.
  • Define Cache contexts: Ensure dynamic elements vary appropriately (e.g., by user roles or languages).
  • Set reasonable max-age values: Balance between performance and content freshness through careful cache lifetime decisions.

Debugging and verification

Tools for Caching insights

  1. Devel module: Provides insights into cache hits/misses.
  2. Application monitoring tools, Such as New Relic or Blackfire, for real-time performance metrics.

Sample debugging code

function mymodule_check_page_cache() {
   $cache_backend = \Drupal::cache('page');
  
   // Check for a specific cache entry.
   $cache_entry = $cache_backend->get('my_page_cid');
  
   if ($cache_entry) {
     \Drupal::logger('mymodule')->info('Page cache hit for my_page_cid!');
   }
   else {
     \Drupal::logger('mymodule')->warning('Page cache miss for my_page_cid.');
   }
 }

Series navigation

This article is part of our comprehensive 10-part series on Drupal caching:

  1. Introduction to Drupal Caching
  2. Understanding Drupal’s Cache API
  3. Choosing the Right Cache Backend for Your Drupal Site
  4. Mastering Page and Block Caching in Drupal (You are here)
  5. Optimising Drupal Views and Forms with Caching (Coming soon)
  6. Entity and Render Caching for Drupal Performance (Coming soon)
  7. Building Custom Caching Services in Drupal (Coming soon)
  8. Implementing Custom Cache Bins for Specialised Needs (Coming soon)
  9. Advanced Drupal Cache Techniques (Coming soon)
  10. Drupal Caching Best Practices and Performance Monitoring (Coming soon)

What’s next?

Page and block caching are essential tools in Drupal’s performance playbook. When implemented properly, they can reduce server strain, minimise database queries, and significantly improve how quickly pages are delivered to users.

Internal Page Cache serves pre-rendered HTML to anonymous visitors, allowing Drupal to bypass the full page build process. Dynamic Page Cache complements this by caching reusable parts of a page for logged-in users, even when the content is personalised. Combined with effective block caching, by configuring cache contexts, tags, and expiration times, Drupal can handle high volumes of traffic with far less effort on the backend.

Some sites have seen load times drop by as much as 80% for repeat page views just by using these built-in caching systems. That kind of performance boost improves everything from user experience to SEO.

To apply these strategies effectively:

  • Use Internal Page Cache to serve static pages quickly to anonymous users
  • Enable Dynamic Page Cache to accelerate pages for logged-in sessions
  • Configure block and component caching using the render API’s cacheability settings
  • Continuously monitor and troubleshoot cache behaviour using debugging tools and response metadata

Always tailor your caching setup to the structure and needs of your site, and reassess it as your content, audience, or features evolve.

Written by
Editor
Ananya Rakhecha
Tech Advocate