Cache context
Cache contexts = (request) contextual dependencies
Cache contexts are similar to the HTTP
Varyheader.
Why?
Cache contexts provide a way to create context-dependent variants of something that needs to be cached. It makes caching logic easier to read and avoids repeating the same conditional logic wherever context-based variation is needed.
Examples:
- Output varies depending on the active theme → use the
themecache context. - A render array displays a personalized message → use the
usercache context. - Expensive computation that depends on the server environment → use the appropriate context.
How?
A cache context is a string referring to one of the available cache context services (see below).
Cache contexts are passed as unordered string arrays (string[]), because a cacheable item may depend on multiple contexts.
Typically, cache contexts are derived from the request context (HTTP requests). However, some may also depend on deployment-specific settings, like deployment_id.
Contexts are defined hierarchically. For instance, if a part of a page varies by user and another by permission, Drupal can simplify and avoid caching unnecessarily fine-grained variants.
Syntax
- Dots
.separate parent from child contexts. - Plural names can take parameters using
:(e.g.,user.roles:anonymous).
Drupal 8 Core Cache Context Hierarchy
cookies
:name
headers
:name
ip
languages
:type
protocol_version
request_format
route
.book_navigation
.menu_active_trails
:menu_name
.name
session
.exists
theme
timezone
url
.path
.is_front
.parent
.query_args
:key
.pagers
:pager_id
.site
user
.is_super_user
.node_grants
:operation
.permissions
.roles
:role
Note: To use url.path.is_front on older versions, see this change record.
Examples
theme– varies by current themeuser.roles– varies by user role combinationuser.roles:anonymous– varies by whether the user is anonymouslanguages:language_interface– varies by interface languageurl.query_args:foo– varies by query parameterfooprotocol_version– varies by HTTP/1 vs HTTP/2
Optimization & Simplification
Drupal automatically simplifies cache contexts using hierarchy rules. For example:
If one part varies by user and another by user.permissions, then only user is needed:
optimize([user, user.permissions]) = [user]
Even though user.permissions is more specific, its result will still vary per user.
If a cache context like user.node_grants has max-age = 0, then it can’t be optimized and must remain. In contrast, if user.node_grants has max-age = 3600, then it can be optimized out and replaced by user in caching logic.
How to Discover and Create Cache Contexts
Cache contexts are services tagged with cache.context. Any module can define its own.
They implement CacheContextInterface or CalculatedCacheContextInterface (for parameterized contexts).
You can find them using an IDE (by searching implementations of the interface) or use the Drupal Console:
$ drupal debug:cache:context
Example:
cache_context.route.book_navigation:
class: Drupal\book\Cache\BookNavigationCacheContext
arguments: ['@request_stack']
tags:
- { name: cache.context }
Debugging
Cache ID (CID) structure for debugging:
foo:bar:[languages:language_interface]=en:[user.permissions]=HASH:[route]=route_name.PARAMS_HASH
- Keys come first, in order.
- Cache contexts follow in alphabetical order.
- Each is formatted as
[context]=value.
Debug Headers
Check the X-Drupal-Cache-Contexts HTTP response header to see active cache contexts.
If it’s missing, enable development settings.
Dynamic Page Cache
Comprehensive use of cache contexts in Drupal 8 enables a dynamic page cache, enabled by default in core.
Internal Page Cache
The internal page cache assumes all pages served to anonymous users are identical. If content varies by cache context for anonymous users, this module should be disabled (may affect performance).