From drupal-boost
Drupal cache API patterns including cache tags, cache contexts, max-age, render caching, and cache invalidation strategies. Use when implementing caching, debugging cache issues, or optimizing Drupal performance.
npx claudepluginhub abderrahimghazali/drupal-boostThis skill is limited to using the following tools:
Every render array MUST include cache metadata:
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Every render array MUST include cache metadata:
$build = [
'#theme' => 'my_template',
'#data' => $data,
'#cache' => [
'tags' => ['node_list', 'node:42'], // WHAT invalidates this
'contexts' => ['user.permissions', 'url.path'], // WHAT varies this
'max-age' => 3600, // HOW LONG to cache (seconds)
],
];
node:NID — Invalidated when a specific node changesnode_list — Invalidated when any node is created/updated/deleteduser:UID — Invalidated when a specific user changestaxonomy_term:TID — Invalidated when a term changesconfig:system.site — Invalidated when site config changesMODULE_NAME:ENTITY:IDInvalidate manually:
\Drupal\Core\Cache\Cache::invalidateTags(['node:42']);
user — Different per useruser.permissions — Different per permission set (fewer variations)user.roles — Different per role combinationurl.path — Different per URL pathurl.query_args — Different per query stringurl.query_args:sort — Different per specific query paramlanguages:language_interface — Different per languagetheme — Different per themeroute — Different per routeCache::PERMANENT (or -1) — Never expires (invalidated by tags only)0 — Uncacheable (use sparingly — kills performance)3600 — Cache for 1 hour86400 — Cache for 1 dayCache metadata "bubbles up" from child elements to parents. Drupal automatically merges:
This means if ANY child has max-age: 0, the entire page becomes uncacheable.
For uncacheable content within cacheable pages:
$build['dynamic_part'] = [
'#lazy_builder' => ['MODULE_NAME.my_service:renderDynamic', [$entity_id]],
'#create_placeholder' => TRUE,
];
The lazy builder method:
public function renderDynamic(int $entity_id): array {
return [
'#markup' => $this->generateContent($entity_id),
'#cache' => ['max-age' => 0],
];
}
BigPipe streams these placeholders after the main page loads.
For storing computed data:
// In services.yml
services:
cache.MODULE_NAME:
class: Drupal\Core\Cache\CacheBackendInterface
tags:
- { name: cache.bin }
factory: cache_factory:get
arguments: [MODULE_NAME]
Usage:
// Store
$this->cache->set('my_key', $data, Cache::PERMANENT, ['node:42']);
// Retrieve
$cached = $this->cache->get('my_key');
if ($cached) {
return $cached->data;
}
max-age: 0 on render arrays that could be cached\Drupal::cache()->deleteAll() instead of tag-based invalidationdrupal_flush_all_caches() in code (use drush cr in dev only)# Clear all caches
drush cr
# Check specific cache bin
drush ev "\Drupal::cache('render')->get('KEY')"
Enable debug headers in development.services.yml:
parameters:
http.response.debug_cacheability_headers: true
Then check response headers: X-Drupal-Cache-Tags, X-Drupal-Cache-Contexts, X-Drupal-Cache-Max-Age.