Backend architecture
Grafana’s backend is written in Go and follows a clean, service-oriented architecture with compile-time dependency injection.Directory structure
The backend code lives inpkg/ and is organized by concern:
| Directory | Purpose |
|---|---|
pkg/api/ | HTTP API handlers and routes |
pkg/services/ | Business logic by domain (alerting, dashboards, auth, etc.) |
pkg/server/ | Server initialization and Wire DI setup |
pkg/tsdb/ | Time series database query backends |
pkg/plugins/ | Plugin system and loader |
pkg/infra/ | Logging, metrics, database access |
pkg/middleware/ | HTTP middleware |
pkg/setting/ | Configuration management |
pkg/models/ | Shared data models |
Dependency injection with Wire
Grafana uses Google Wire for compile-time dependency injection, providing type safety and circular dependency detection.Wire configuration
The main Wire configuration is inpkg/server/wire.go:
pkg/server/wire.go:
- Provider functions - Functions like
ProvideService()that return initialized services - Wire sets - Groups of related providers (
wireBasicSet,withOTelSet) - Interface bindings -
wire.Bind()to bind implementations to interfaces - Injector functions -
Initialize()functions that Wire generates implementations for
Regenerating Wire code
After modifying service initialization or dependencies:pkg/server/wire_gen.go with the actual initialization code.
Common Wire patterns:
Service layer architecture
Services contain business logic and are organized by domain.Service structure
Typical service structure inpkg/services/<domain>/:
Service interface pattern
Services implement interfaces defined in the same package:- Interfaces in the package root, implementations in
service/or implementation-specific subdirectories - Business logic in services, not in API handlers
- Services depend on other services through interfaces
- Data access through repository/store patterns
API handlers
HTTP API handlers live inpkg/api/ and delegate to services.
API structure
- Request parsing and validation
- Authentication/authorization checks
- Calling service methods
- Response formatting
- Error handling
Routing
Routes are registered inpkg/api/api.go:
Database access
Database access is handled through thesqlstore package.
SQLStore
The main database interface ispkg/services/sqlstore/sqlstore.go:
- XORM for ORM
- Raw SQL for complex queries
- Transactions via
WithDbSessionorWithTransactionalDbSession - Migration system in
pkg/services/sqlstore/migrations/
Example repository
Plugin backend system
Backend plugins run as separate processes and communicate via gRPC.Plugin structure
Frompkg/plugins/plugins.go:
Plugin loading
Plugins are discovered and loaded through a pipeline:- Discovery - Find plugin directories
- Validation - Check signatures and compatibility
- Initialization - Load plugin.json, start backend process
- Registration - Register with plugin registry
pkg/plugins/manager/pipeline/ for pipeline implementation.
Data source query system
Data source backends live inpkg/tsdb/:
backend.QueryDataHandler interface.
Infrastructure services
Logging
Metrics
Prometheus metrics viapkg/infra/metrics/:
Tracing
OpenTelemetry tracing viapkg/infra/tracing/:
Server initialization
The server starts inpkg/server/server.go:
- Load configuration from
conf/defaults.iniandconf/custom.ini - Initialize database connection and run migrations
- Wire builds the dependency graph
- Start HTTP server
- Start background services
Testing patterns
Unit tests
Integration tests
Key patterns summary
- Wire DI - Compile-time dependency injection for type safety
- Service interfaces - Business logic behind interfaces
- Thin handlers - API handlers delegate to services
- Repository pattern - Data access abstraction
- Plugin architecture - Extensibility via gRPC
- Migration system - Database schema versioning