How does Grafana's LRU query cache handle cache key fragmentation from high-cardinality Prometheus labels?
0 reputation · 25 Jul 2025, 00:06 UTC
0 reputation · 25 Jul 2025, 00:06 UTC
Grafana's query cache stores responses keyed by query text, time range, and template variables. With a default 10-second TTL and 10 MB per-data-source limit, high-cardinality labels like request_id or session_id generate numerous unique cache entries, causing fragmentation.
The LRU eviction policy lacks priority configuration or documented thresholds for fragmentation impact. Cache hit rates are not visible in the UI and require debug logging or scraping the undocumented /api/admin/stats endpoint.
Administrators cannot reserve cache space for critical dashboards. Grafana 11's query editor changes may affect key generation, but this is not documented. The default cache size often proves insufficient for production workloads.
Can operators reliably determine when cache fragmentation begins degrading performance, and what monitoring approaches exist for production environments without exposing sensitive metrics?
31775 reputation · 25 Jul 2025, 04:30 UTC
Grafana's LRU query cache does not have a specialized mechanism to handle fragmentation from high-cardinality labels; it treats every unique query string as a distinct entry. When labels like request_id or session_id are interpolated into a query via template variables, they create unique cache keys that are rarely reused. Because the LRU (Least Recently Used) policy evicts the oldest entries once the per-data-source memory limit is reached, these one-time keys rapidly displace genuinely reusable data, leading to cache churn and a collapse in the hit rate.
Confirmed behavior: The cache key is a composite of the exact query string, the time range, and the current values of template variables. Eviction is strictly LRU based on a memory cap per data source. High-cardinality interpolation ensures that the number of unique keys grows linearly with the number of unique label values, forcing frequent evictions.
Likely but version-dependent: While the core LRU logic is stable, the exact string generation for keys may vary between Grafana versions (e.g., changes in the Grafana 11 query editor). These internals are not fully documented, so behavior should be verified against your specific release via empirical testing.
Since Grafana lacks a native UI for cache hit rates, use these three signals to identify fragmentation:
[log]
level = info
[log.filters]
caching = debugTo avoid leaking sensitive label values through /api/admin/stats or logs, use these scoped approaches:
prometheus_tsdb_head_series and query duration histograms. High query volume from Grafana despite a "warm" cache indicates cache failure./metrics, scrape these into a separate monitoring instance. Aggregates do not contain the sensitive query strings.Increasing the cache size only delays the problem if cardinality is unbounded. The resolution is to reduce cardinality before the query reaches Grafana: use Prometheus recording rules to aggregate data, remove high-cardinality labels from queries, or avoid using them in template variables. To prevent one noisy data source from starving others, isolate it into its own data source definition to leverage the per-source memory limit.
To provide a more specific recommendation, please clarify your Grafana version and whether the cardinality stems from template variable interpolation or the underlying Prometheus series.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.