cache
The cache configuration controls the router’s in-memory caches for parsing, validation,
normalization, and query plans, as well as the shared cache of plugin-selected supergraph runtimes.
Operation caches make repeated operations fast, but their memory usage grows with the number of
distinct queries.
Each operation cache supports a size limit (max_entries) and optional time-based expiry
(time_to_live, time_to_idle). These settings are independent for each cache, so you can size the
query-plan cache differently from the parsing cache.
Scopes
router - one instance per process
Caches under cache.router are shared by everything the router serves.
| Cache | What it holds |
|---|---|
parsing | Parsed GraphQL documents, keyed by the incoming query hash. Parsing is schema-independent, so this cache is shared across supergraph variants. |
plugin_supergraph_runtimes | Router runtimes for plugin-selected supergraphs, retained in a shared FIFO cache. The configured supergraph runtime is separate. |
plugin_supergraph_runtimes
- Type: non-negative
integer - Default:
10 - Environment Variable:
ROUTER_CACHE_PLUGIN_SUPERGRAPH_RUNTIMES
Maximum number of plugin-selected supergraph runtimes retained under
cache.router.plugin_supergraph_runtimes. When the cache is full, adding a runtime evicts the
oldest entry (FIFO). Cache hits do not change that order. The configured supergraph runtime does
not count toward this limit.
Set the value to 0 to disable caching for plugin-selected runtimes; each selection then builds a
new runtime. The environment override takes precedence over the configuration file:
The cache grows as runtimes are added, so a large limit does not reserve memory at startup. Each retained runtime has its own supergraph-scoped operation caches. Eviction does not retire the supergraph or interrupt existing requests or subscriptions; those retain their pinned runtime. A later selection rebuilds the runtime if it is no longer cached.
This setting is an entry count, not a cache-limits object: max_entries, time_to_live, and
time_to_idle do not apply to it.
supergraph - one instance per served variant
Caches under cache.supergraph are created per supergraph variant. The configured supergraph
(supergraph.source) gets one set, each plugin-constructed variant gets its own. Memory here is multiplied by the number of live variants.
| Cache | What it holds |
|---|---|
validation | Validation results for an operation against this supergraph. |
normalization | Normalized operations, ready to be planned. |
query_plans | Query plans built for this supergraph. |
Options
Each of the four caches (router.parsing, supergraph.validation, supergraph.normalization,
supergraph.query_plans) accepts the same three fields.
max_entries
- Type:
integer - Default:
1000
Maximum number of entries to keep. Once full, the cache evicts entries according to its LRU policy to make room.
time_to_live
- Type:
string(duration, e.g.30m,1h,300s) - Default: unset (disabled)
Expires an entry a fixed duration after it was created or last updated, even if it is still hot. Disabled by default, preserving the previous LRU-only behavior.
time_to_idle
- Type:
string(duration, e.g.5m,10m) - Default: unset (disabled)
Expires an entry after it has not been read or updated for the configured duration. Disabled by default.
When both time_to_live and time_to_idle are set, whichever fires first evicts the entry.
Per-variant overrides in plugins
Plugins serving extra supergraph variants inherit cache.supergraph by default. Override per
variant with SupergraphOptions::cache - each dimension (max_entries, time_to_live,
time_to_idle) inherits independently, so touching one never resets the others. Pass None to
explicitly disable an expiry the router config sets.
SupergraphOptions::try_from(payload.router_config())? also leaves cache overrides unset while
inheriting the router’s other graph-bound settings. See
Supergraph-bound configuration.
Useful helpers: disable() turns one cache off for that variant, inherit() resets a cache back to the router config.