From drupal-workflow
Implements Drupal 10/11 caching with bins, tags, contexts, invalidation strategies, external backends, lazy builders, and CacheableMetadata. For performance optimization and cache configuration.
How this skill is triggered — by the user, by Claude, or both
Slash command
/drupal-workflow:drupal-cachingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Always use cache metadata on render arrays. Never return a render array without `#cache` keys. Check for proper cache tag, cache context, and max-age on every render array you create.
Always use cache metadata on render arrays. Never return a render array without #cache keys. Check for proper cache tag, cache context, and max-age on every render array you create.
Every render array should include cache metadata:
$build = [
'#theme' => 'my_template',
'#data' => $data,
'#cache' => [
'keys' => ['my_module', 'block', $id],
'contexts' => ['user', 'url.query_args'],
'tags' => ['node:' . $nid, 'node_list'],
'max-age' => 3600,
],
];
| Context | Varies By | Use When |
|---|---|---|
user | Current user ID | Content per user |
user.roles | User roles | Content per role |
user.permissions | Permissions | Access-dependent |
url | Full URL | Page-specific |
url.path | URL path only | Path-dependent |
url.query_args | Query parameters | Filtered content |
languages | Current language | Multilingual |
theme | Active theme | Theme-specific |
session | Session ID | Session-dependent |
// Entity-based tags (auto-invalidated).
'tags' => ['node:42'] // Specific node.
'tags' => ['node_list'] // Any node list.
'tags' => ['taxonomy_term:5'] // Specific term.
'tags' => ['config:system.site'] // Config object.
// Custom tags.
'tags' => ['my_module:feature_x']
Use CacheableMetadata to merge cache metadata from multiple sources. This is cleaner than manually assembling #cache arrays, especially in complex render pipelines.
use Drupal\Core\Cache\CacheableMetadata;
// Build cache metadata from multiple sources.
$cache = new CacheableMetadata();
$cache->addCacheableDependency($node);
$cache->addCacheableDependency($user);
$cache->addCacheContexts(['url.query_args']);
$cache->addCacheTags(['my_module:feature_x']);
$cache->setCacheMaxAge(3600);
// Apply to a render array.
$cache->applyTo($build);
// Merge metadata from an access result into the render array.
$access = $entity->access('view', $account, TRUE);
$cache->addCacheableDependency($access);
Use #lazy_builder for fragments that vary per user inside otherwise cacheable pages. Lazy builders defer rendering until after the page cache is resolved, so the rest of the page can still be cached.
$build['user_greeting'] = [
'#lazy_builder' => [
'my_module.greeting_builder:build', // Service::method
[$user_id], // Arguments (scalars only)
],
'#create_placeholder' => TRUE,
];
The service must implement a build() method returning a render array:
final class GreetingBuilder {
public function build(int $user_id): array {
return ['#markup' => 'Hello, ' . $this->loadUserName($user_id)];
}
}
In services, inject CacheTagsInvalidatorInterface — never use \Drupal::service() calls.
// In a service with injected $cacheInvalidator:
$this->cacheInvalidator->invalidateTags(['node:42', 'my_module:feature_x']);
| Bin | Purpose |
|---|---|
default | General-purpose |
render | Render arrays |
page | Full page cache |
dynamic_page_cache | Authenticated pages |
discovery | Plugin discovery |
data | Data processing |
config | Configuration |
menu | Menu trees |
// settings.php
$settings['redis.connection']['interface'] = 'PhpRedis';
$settings['redis.connection']['host'] = '127.0.0.1';
$settings['cache']['default'] = 'cache.backend.redis';
// Ensure proper cache headers.
$response->headers->set('Cache-Control', 'public, max-age=3600');
$response->headers->set('Surrogate-Control', 'max-age=86400');
#cache).// Bad: N queries.
foreach ($nids as $nid) {
$node = Node::load($nid);
}
// Good: 1 query.
$nodes = Node::loadMultiple($nids);
accessCheck() explicitly.npx claudepluginhub gkastanis/drupal-workflow --plugin drupal-workflowProvides caching patterns like cache-aside, write-through, stampede prevention, CDN headers, multi-level L1/L2/L3 caches, and invalidation strategies for high-traffic systems and CDN design.
Configures caching on Netlify's CDN including Cache-Control headers, stale-while-revalidate, durable cache, on-demand purge, cache tags, and cache key variation.
Implements Redis caching patterns like cache-aside, write-through, write-behind; covers Memcached, invalidation strategies, TTL design, stampede prevention, CDN config, distributed caching. For optimizing read performance, reducing DB load, designing cache layers.