Caching & Performance
Relevant source files
The following files were used as context for generating this wiki page:
Caching and performance optimization in Grafana are multi-layered, spanning from frontend data fetching strategies to backend infrastructure instrumentation. The system utilizes automated caching mechanisms for API responses, specifically within the Unified Alerting system and Prometheus data sources, alongside standardized performance monitoring via metrics, logs, and traces.
Performance is managed through a combination of TTL-based (Time-To-Live) caching, debounce logic for high-frequency operations, and a resource-oriented backend architecture that leverages unified storage for efficient data access and "Watch" capabilities.
Sources: packages/grafana-prometheus/src/caching.test.ts:1-118, public/app/features/alerting/unified/AGENTS.md:75-85, contribute/architecture/k8s-inspired-backend-arch.md:85-105
Data Source Caching (Prometheus)
The Prometheus implementation defines specific caching behaviors based on a PrometheusCacheLevel. This configuration affects query debounce times, metadata cache duration, and HTTP header generation for backend caching.
Cache Levels and Durations
The system supports different caching intensities: None, Low, Medium, and High. Each level maps to specific performance parameters:
| Cache Level | Debounce Time (ms) | Metadata Cache (Days) | Cache Duration (Minutes) |
|---|---|---|---|
| None | 350 | 1 | 1 |
| Low | 350 | 1 | 1 |
| Medium | 600 | 7 | 10 |
| High | 1200 | 30 | 60 |
Sources: packages/grafana-prometheus/src/caching.test.ts:13-75
HTTP Cache Headers
Grafana utilizes a custom header, X-Grafana-Cache, to communicate cache policies. This header typically uses the private, max-age=<seconds> format. For example, a "Medium" cache level (10 minutes) generates a max-age=600 directive.
Sources: packages/grafana-prometheus/src/caching.test.ts:80-118
Frontend Performance Patterns
RTK Query & Polling
For the Unified Alerting system, Grafana prioritizes RTK Query for data fetching over traditional Redux. This provides automatic caching and supports configurable polling intervals, such as RULE_LIST_POLL_INTERVAL_MS, which defaults to a 2-minute interval for refreshing alert rules.
Sources: public/app/features/alerting/unified/AGENTS.md:75-85
Style Memoization
Frontend rendering performance is optimized using the useStyles2 hook from Emotion. This hook memoizes style generation to prevent unnecessary recalculations during component re-renders. Developers are encouraged to compose classes using the Emotion cx function rather than passing dynamic props to style generators to maintain performance.
Sources: contribute/style-guides/frontend.md:43-55, public/app/features/alerting/unified/AGENTS.md:38-41
Backend Architecture & Unified Storage
Performance on the backend is enhanced by the Unified Storage layer, which translates Kubernetes-style storage operations (Create, Get, List, Watch) into efficient SQL queries.
Native Watch Support
To avoid expensive continuous polling in high-availability (HA) modes, the architecture implements a resource_history table.
- HA Mode: An internal poller reads the history table based on a
resourceVersioncounter to detect changes. - Non-HA Mode: Writes trigger direct notifications via Go channels.
This ensures that clients connected via the "Watch" API receive updates efficiently without constant database scanning.
Sources: contribute/architecture/k8s-inspired-backend-arch.md:85-105
Request Flow for Cached Resources
The following diagram illustrates how requests flow through the API layers to the Unified Storage:
The K8sHandler acts as a loopback client, allowing legacy services to benefit from the standardized Resource API performance features.
Sources: contribute/architecture/k8s-inspired-backend-arch.md:160-200
Performance Instrumentation
Grafana enforces strict instrumentation guidelines to monitor and debug performance bottlenecks.
Metrics (Prometheus)
Backend performance is measured using the RED method (Rate, Errors, Duration).
- Namespace: All metrics use the
grafana_prefix. - Histograms: Used for measuring durations (e.g.,
grafana_http_request_duration_seconds). - Gauges: Used for tracking concurrent operations (e.g.,
grafana_http_request_in_flight).
Sources: contribute/backend/instrumentation.md:95-125
Distributed Tracing
Grafana uses OpenTelemetry to track request flow. Spans are created for I/O bound work, such as database calls, but avoided for simple wrappers to prevent "data noise" without insight.
Resource Optimization Guidelines
To maintain system performance, the following coding practices are recommended:
- Date Comparison: Store date columns as Unix timestamps (epoch-based integers) to allow unified comparison across different databases (PostgreSQL, MySQL, SQLite) without time zone transformation overhead.
- Avoid Global State: Migrate away from global variables toward dependency injection using Wire to improve testability and reduce resource contention.
- Context Propagation: Always propagate
context.Contextthrough all layers (API to Database) to support contextual logging and request cancellation, which prevents orphaned backend processing.
Sources: contribute/backend/recommended-practices.md:65-145
Conclusion
Caching and performance in Grafana are achieved through a combination of strategic frontend polling, standardized data source cache levels, and a backend architecture designed for efficient resource synchronization. By adhering to strict instrumentation standards and utilizing unified storage patterns, the system maintains high responsiveness and observability.