Using permission caching for faster access checksfor Drupal 11 , 10 , 9 , and 8

Last updated :  

Every access-controlled action on your site — viewing a node, seeing an admin link, accessing a route — triggers a permission check somewhere. Drupal computes a user's full set of permissions from their assigned roles and caches that computed result, rather than re-deriving it from the roles table on every single check — exactly the same "compute once, reuse many times" principle you've seen applied to render output and query results throughout this tutorial, applied here to access control.

What you'll learn in this lesson

  • How permission caching actually works under the hood
  • The user.permissions cache context, and why it's coarser than user
  • What invalidates a cached permission set, and why that's usually rare

How it's cached

// Checking a permission triggers this, cached per unique role combination —
// not per individual user.
\Drupal::currentUser()->hasPermission('administer nodes');

// Internally backed by the permissions.yml definitions and each role's
// assigned permission set, computed once per role combination and reused.
Cached per role combination, not per user. Two users who both have exactly the "authenticated" and "editor" roles share the same computed permission set — Drupal doesn't redundantly compute and cache permissions separately for every individual user account, only for each distinct combination of roles that actually exists across your user base. A site with thousands of users but five distinct role combinations only ever caches five permission sets.

user.permissions vs. user as a cache context

This connects directly to the cache contexts lesson from the Caching Strategies section: if a render array's content only depends on what a user is allowed to do (show an "Edit" link only to users who can edit), tag it with the user.permissions cache context — coarser and cheaper than the full user context, since it produces one cached variant per role combination rather than one per individual account. Reaching for user when user.permissions would do is a real, avoidable cost, exactly the "narrowest context that's still correct" principle from earlier in this tutorial.

What actually invalidates a cached permission set

Changing a role's permissions (at /admin/people/permissions) invalidates the cached computation for every user with that role — a genuinely rare administrative action, not something that happens on normal site traffic. This is exactly why permission caching is safe and effective: the underlying data it caches changes infrequently, unlike, say, a specific node's content.

Quick check: a block shows an "Edit" link only to users who can edit articles — nothing else about the block varies by which specific user is viewing it. Should it use the user or user.permissions cache context? If you said user.permissions — the content only depends on permission level, not individual identity, so the coarser, cheaper context is correct — you've applied this tutorial's core caching principle correctly one more time.

Key takeaways

  • Permission sets are cached per unique role combination, not per individual user — far fewer cached variants than user count would suggest.
  • Use the user.permissions cache context (not the finer user) for content that varies only by permission level, not by individual identity.
  • A cached permission set is invalidated only when a role's own permissions change — a rare administrative action, which is why this caching is both safe and effective.

Coming up next

You've now covered the complete session-and-user performance toolkit. Next, we shift to verification itself: load testing and monitoring your site's real performance under real traffic conditions.