Drupal Caching — Internal Caching, BigPipe, CDN and Performance
In this tutorial, you'll learn how Drupal caching works — from internal page cache and BigPipe to render cache, views cache, CDN integration, and cache invalidation strategies that keep your production site fast and fresh.
What You'll Learn
- The different cache types in Drupal and what each one does
- How BigPipe progressively renders pages for perceived performance
- Configuring view caching for database query optimization
- Integrating CDN services like Cloudflare with Drupal
- Cache invalidation strategies for content freshness
Why It Matters
Drupal is a dynamic CMS — every page request can involve dozens of database queries, plugin calculations, and render operations. Without caching, a single page can take 2-3 seconds to load. With proper caching, that same page loads in under 200 milliseconds. Caching is not optional for production Drupal sites. It directly impacts user experience, search engine rankings, server costs, and scalability. A well-cached Drupal site can handle 10 times the traffic with the same server resources.
Real-World Use
A high-traffic news website using Drupal serves 500,000 visitors per day. Page cache serves anonymous users static HTML copies of articles from Redis. BigPipe delivers authenticated user pages progressively — the main content loads first, then personalization blocks (user menu, shopping cart) load asynchronously. The CDN caches images and aggregated CSS/JS at 50 edge locations worldwide. When an editor publishes a new article, cache tags invalidate the homepage, category pages, and search index simultaneously.
Learning Path
flowchart LR A[Essential Modules] --> B[Caching] B --> C[SEO] C --> D[Multilingual] D --> E[User Roles] E --> F[User Management] F --> G[Security Hardening]
Cache Types Overview
Drupal has multiple cache layers. Understanding each one helps you configure them correctly.
- Page cache — stores full HTML pages for anonymous users
- Dynamic Page Cache — caches pages for authenticated users per-session fragments
- BigPipe — sends content progressively using lazy loading
- Render cache — caches individual rendered elements (blocks, nodes)
- Views cache — caches query results and rendered output from Views
- Entity cache — caches loaded entities (nodes, users, taxonomy)
- Block cache — caches rendered block content
Internal Page Cache
The Internal Page Cache module stores complete HTML pages and serves them to anonymous users without bootstrapping Drupal fully.
# Enable the Page Cache module:
drush en page_cache
How It Works
When an anonymous user visits a page, Drupal generates the HTML and stores it. The next anonymous Visitor gets the cached HTML directly — no database queries, no module hooks, no Twig rendering.
Configuration
# Performance settings for page cache:
page_cache:
max_age: 21600 # 6 hours in seconds
Go to Configuration > Development > Performance to set:
- Page cache max age — how long browsers can cache the page
- Cache pages for anonymous users — enable/disable
Limitations
Page cache works only for anonymous users. Authenticated users get personalized content (user menu, contextual links) that cannot be fully cached.
Dynamic Page Cache
The Dynamic Page Cache module extends caching to authenticated users. It caches everything except personalized fragments.
# Enable Dynamic Page Cache:
drush en dynamic_page_cache
How It Works
Drupal renders the page and caches the entire output except for placeholders. Placeholders represent personalized content that differs per user. When a request comes in, Drupal serves the cached page and fills in the placeholders with user-specific content.
# Dynamic page cache configuration:
dynamic_page_cache:
max_age: 3600 # 1 hour
BigPipe
BigPipe is a technique developed by Facebook for progressive page rendering. Drupal's BigPipe module sends the page shell immediately, then streams content blocks one by one.
# Enable BigPipe:
drush en big_pipe
How It Works
When a page is requested, Drupal sends the main HTML structure (page shell) immediately. Content blocks that are cacheable and not user-specific are included in this initial response. Blocks that depend on user context (user menu, cart, personalized recommendations) are replaced with placeholders. After the initial HTML is sent, Drupal sends each placeholder's content through additional HTTP responses using JavaScript.
<!-- Initial HTML contains placeholders -->
<div id="big-pipe-placeholder-1">
<!-- User menu loads here -->
</div>
<script>
// BigPipe JavaScript progressively fills placeholders
big_pipe.fillPlaceholder('big-pipe-placeholder-1', '/big_pipe/session/1');
</script>
When to Use BigPipe
BigPipe benefits authenticated users who see personalized blocks. It is especially valuable for complex pages with many dynamic elements like dashboards or community sites.
Render Cache
The render cache stores the rendered output of individual elements. When a block or entity is rendered, the result is cached by cache tags, contexts, and max-age.
# Render cache configuration:
render_cache:
max_age: -1 # -1 means permanent until invalidated
Render cache works per-element:
- A node's rendered HTML is cached by cache tag
node:123 - A block's rendered HTML is cached by cache tag
block:my_block - Cache contexts like
url,user, andlanguagecreate separate cache entries per variation
Cache Tags
Every entity in Drupal has cache tags. When an entity is updated, all cached content containing that entity is invalidated.
<?php
// Cache tags are automatically set by Drupal:
$build['#cache']['tags'] = [
'node:123', // Specific node
'node_list', // List of all nodes
'config:views.view.my_view', // View configuration
'taxonomy_term:5', // Specific taxonomy term
];
// You can add custom cache tags:
$build['#cache']['tags'][] = 'my_custom_tag';
When node 123 is updated:
<?php
// Drupal automatically invalidates all caches with tag 'node:123'
Cache::invalidateTags(['node:123']);
This means the homepage (which lists node 123), the node page itself, and any block showing node 123 are all invalidated simultaneously.
Cache Contexts
Cache contexts define variations of cached content. Each context creates a separate cache entry.
<?php
// Cache contexts create separate cache entries per variation:
$build['#cache']['contexts'] = [
'url', // Different URL = different cache entry
'user', // Per-user cache entry
'user.roles', // Per-role cache entry
'language', // Per-language entry
'timezone', // Per-timezone entry
'cookies:my_cookie', // Based on a cookie value
'headers:X-My-Header', // Based on a request header
'route', // Per-route entry
];
Choose the minimum set of contexts needed. Each context multiplies cache entries. Adding user context creates a separate cache entry for every user, which defeats caching on high-traffic sites.
Cache Max-Age
Max-age defines how long a cached element is valid. When the max-age expires, the content is re-rendered.
<?php
// Cache max-age settings:
$build['#cache']['max-age'] = 3600; // 1 hour
$build['#cache']['max-age'] = 86400; // 1 day
$build['#cache']['max-age'] = -1; // Permanent (until tag invalidation)
$build['#cache']['max-age'] = 0; // Never cache
Views Caching
Views has its own caching layer with two levels: query results and rendered output.
- Go to Structure > Views > Edit your view
- Click on the display (e.g., Page, Block)
- Click "Caching" in the advanced settings
# Views caching configuration:
cache:
type: time
results:
lifetime: 3600 # Cache query results for 1 hour
output:
lifetime: 3600 # Cache rendered output for 1 hour
Query Results Cache
Caches the SQL query result. Useful for views that perform complex joins or aggregations.
Rendered Output Cache
Caches the fully rendered HTML of the view output. More aggressive caching.
# Aggressive views caching with tag-based invalidation:
cache:
type: tag
results:
lifetime: 3600
output:
lifetime: 3600
CDN Integration
A CDN (Content Delivery Network) caches your site's static assets at edge locations worldwide.
Cloudflare
- Enable the Cloudflare module:
composer require drupal/cloudflare
drush en cloudflare
- Configure Cloudflare API credentials
- Set caching rules for static assets
- Enable "Automatic HTTPS Rewrites"
# Cloudflare module configuration:
cloudflare:
apikey: 'your_api_key'
email: 'your_email@example.com'
zone_id: 'your_zone_id'
Fastly
For enterprise setups:
composer require drupal/fastly
drush en fastly
Cache Invalidation
The Purge module manages cache invalidation across CDNs:
composer require drupal/purge drupal/purge_drush
drush en purge purge_drush
# Invalidate CDN cache for specific URLs:
drush purge-invalidate 'node:123'
drush purge-invalidate 'http://example.com/node/123'
Varnish
Varnish is an HTTP cache accelerator that sits in front of Drupal.
# Install Varnish (on server):
sudo apt install varnish
Varnish configuration for Drupal (/etc/varnish/default.vcl):
sub vcl_recv {
# Pass through admin paths
if (req.url ~ "^/admin" || req.url ~ "^/user") {
return (pass);
}
# Remove cookies for anonymous users
if (req.http.cookie ~ "SESS") {
return (pass);
}
# Cache static assets aggressively
if (req.url ~ "\.(css|js|png|jpg|jpeg|gif|ico|svg)$") {
unset req.http.cookie;
return (hash);
}
}
sub vcl_backend_response {
# Set cache TTL
set beresp.ttl = 1h;
# Cache tagged content
if (beresp.http.X-Drupal-Cache-Tags) {
set beresp.ttl = 2h;
}
}
Cache Metadata Best Practices
Always set cache tags on custom render arrays so they invalidate properly. Use the minimum number of cache contexts to avoid cache fragmentation. Set reasonable max-age values — not everything needs permanent caching. Use tag-based invalidation instead of time-based expiration where possible. Monitor cache hit rates to verify your caching Strategy is working. Test cache invalidation by updating content and verifying the changes appear immediately.
Common Mistakes
Not enabling Dynamic Page Cache for authenticated users: Authenticated users get no caching benefits without the Dynamic Page Cache module, causing poor performance for logged-in traffic.
Excessive cache contexts: Adding
usercontext to everything creates separate cache entries for every user, negating caching benefits. Useuser.rolesinstead ofuserwhen possible.Not setting cache tags on custom blocks: Custom blocks without cache tags are never invalidated when content changes. Add the appropriate entity cache tags to your block's render array.
Disabling caching during development and forgetting to re-enable: Production sites with caching disabled perform terribly. Always verify cache settings before launch.
Not clearing caches after configuration changes: Configuration changes have their own cache tags, but some settings require a manual
drush crto take effect.
Practice Questions
How does BigPipe improve perceived performance compared to traditional synchronous page loading?
What is the difference between cache tags, cache contexts, and cache max-age? Give an example of each.
How would you configure Views caching for a listing page that updates hourly but must reflect content changes immediately?
Challenge: Design a caching strategy for a community forum site with anonymous visitors, registered members, and moderators. Define which cache types to use for each user group, how to handle personalized blocks (user menu, notifications), what CDN setup to use, and how cache invalidation works when a moderator edits a post.
FAQ
Mini Project
Goal: Configure and test a multi-layer caching setup.
- Enable Internal Page Cache and Dynamic Page Cache modules
- Configure page cache max age to 6 hours in Performance settings
- Enable BigPipe module for authenticated users
- Create a View with tag-based caching
- Add cache tags to a custom block in a preprocess function
- Install and configure the Purge module with a CDN (Cloudflare or Fastly)
- Test anonymous page load speed before and after caching
- Update a node and verify cache invalidation works
- Monitor cache hit rate using the web profiler from Devel
What's Next
Now that you understand caching, proceed to Drupal SEO to learn about search engine optimization with Metatag, XML Sitemap, and Schema.org. After that, explore multilingual Drupal for international sites.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro