You met cache tags in the Caching Strategies section as a general concept — invalidate exactly what changed, leave everything else alone. Entities are where that idea earns its keep the most: Drupal automatically tags every rendered entity with its own cache tag, so saving one node invalidates only the caches that actually rendered that node, not your entire site.
What you'll learn in this lesson
- The automatic
entity_type:idcache tag every entity gets for free - How list cache tags (
node_list) differ from individual entity tags - When you need to add cache tags manually, and when Drupal already does it
The automatic entity cache tag
// Just by loading and rendering a node, Drupal attaches:
// cache tag "node:42"
$node = \Drupal\node\Entity\Node::load(42);
$build = \Drupal::entityTypeManager()
->getViewBuilder('node')
->view($node);
// $build['#cache']['tags'] now includes 'node:42' automatically.
You don't write this yourself — EntityViewBuilder adds it for every entity it renders. The moment that node is saved again, Drupal calls Cache::invalidateTags(['node:42']) internally, and every cached render array anywhere on the site carrying that tag gets invalidated — a page, a block, a Views row, all of it, regardless of where it lives.
List tags: the one that trips people up
// A "recent articles" listing needs to know about NEW articles too —
// not just edits to ones it already knows about.
$build['#cache']['tags'][] = 'node_list';
node_list tag (invalidated on every node save, of any node) is what catches "a new one appeared" cases. Drupal's own Views module adds this automatically for entity-based views; hand-rolled listings need to add it themselves.When you need to add tags manually
If your render array pulls data from an entity without going through EntityViewBuilder — a custom block that queries and displays a related entity's title, say — you're responsible for adding that entity's cache tag yourself, using Cache::mergeTags() or by adding the entity's own getCacheTags() to your render array's #cache metadata, exactly as covered in the Cache API section of the Module Development tutorial.
Quick check: a custom block shows "You have 3 unread messages," counting rows in a custom table with no entity involved at all. Would
node:42-style tags help here? If you said no — there's no node being rendered, so this needs its own custom cache tag scheme entirely, unrelated to entity tags — you've understood the boundary of what entity cache tags actually cover.
Key takeaways
- Every entity gets an automatic
entity_type:idcache tag the moment it's rendered via its view builder. - Saving an entity automatically invalidates every cache carrying its tag, site-wide.
- Add the generic
*_listtag (e.g.node_list) to any listing that needs to react to brand-new entities appearing, not just edits to ones it already shows. - Custom render logic that reads entity data without going through the view builder must add cache tags manually.
Coming up next
Cache tags handle correctness — making sure stale data gets invalidated. Next, we tackle a different cost entirely: the rendering overhead of field formatters themselves.