Grafana — Structure#
Layout pattern#
Monorepo (custom multi-language, multi-module)
Grafana does not follow the standard cmd/internal/pkg Go layout. Instead it is a true polyglot monorepo with a Go backend under pkg/, a TypeScript/React frontend under public/, standalone App SDK Go modules under apps/, Yarn workspace packages under packages/, CUE schemas under kinds/, and ~35 Go modules all managed by a root go.work file. This is a custom layout evolved for enterprise-scale, with no single idiomatic Go convention dominating.
Directory map#
grafana/
├── apps/ # Standalone Grafana App SDK apps (each is its own Go module)
│ ├── advisor/ # Health/configuration advisor app
│ ├── alerting/ # Alerting sub-apps (enrichment, historian, notifications, rules)
│ ├── dashboard/ # Dashboard resource app
│ ├── folder/ # Folder resource app
│ ├── iam/ # Identity & access management app
│ ├── plugins/ # Plugin management app
│ ├── provisioning/ # Provisioning app (GitHub-backed)
│ └── ... # ~20 other domain apps
├── conf/ # Default configuration (defaults.ini, provisioning examples)
├── contribute/ # Contributor guides (architecture docs, backend/frontend style)
├── cue.mod/ # CUE module definition for schema generation
├── devenv/ # Local dev environment (Docker compose, dashboards, scripts)
├── docs/ # End-user documentation source (served by Grafana website)
├── e2e/ # Cypress end-to-end test suites
├── e2e-playwright/ # Playwright end-to-end test suites
├── emails/ # Email notification templates
├── kinds/ # CUE schema definitions → generates Go + TypeScript types
├── kindsv2/ # Next-gen CUE schema definitions
├── packages/ # Frontend Yarn workspace packages (@grafana/data, ui, runtime…)
├── packaging/ # Linux (deb/rpm), macOS, Docker packaging scripts
├── pkg/ # Go backend source code (primary Go module)
│ ├── aggregator/ # API aggregation layer (Kubernetes-style)
│ ├── api/ # HTTP API handlers, routes, DTOs
│ ├── apimachinery/ # Kubernetes API machinery abstractions
│ ├── apis/ # Kubernetes-style API group registrations
│ ├── apiserver/ # Embedded kube-apiserver support
│ ├── build/ # Build tooling Go code (Dagger pipelines, e2e runners)
│ ├── bus/ # In-process event bus
│ ├── cmd/ # Binary entry points (grafana, grafana-cli, grafana-server)
│ ├── codegen/ # Go code generation tooling
│ ├── components/ # Shared utility components (simplejson, imguploader, etc.)
│ ├── expr/ # Server-side expression evaluation (math, classic conditions)
│ ├── generated/ # Generated Kubernetes client/informer/lister code
│ ├── infra/ # Cross-cutting infrastructure (logging, metrics, DB, caching)
│ ├── kinds/ # CUE-generated Go types for Grafana kinds
│ ├── middleware/ # HTTP middleware (auth, CSRF, logging, rate limiting)
│ ├── mocks/ # Shared mock implementations
│ ├── models/ # Legacy shared domain model types
│ ├── modules/ # Module lifecycle management
│ ├── operators/ # Kubernetes operator extensions
│ ├── plugins/ # Plugin system (loader, gRPC backend, registry)
│ ├── registry/ # API and service registries
│ ├── server/ # Server initialization, Wire DI wiring
│ ├── services/ # Business logic organized by domain (~60 sub-packages)
│ ├── setting/ # Configuration management (INI-based)
│ ├── storage/ # Unified storage abstraction layer
│ ├── tests/ # Integration test helpers
│ ├── tsdb/ # Time series data source query backends (per data source)
│ └── util/ # General utilities
├── public/ # Frontend assets (TypeScript/React, SASS, images)
│ ├── app/ # React application (features/, core/, plugins/, store/)
│ └── ... # Static assets (fonts, maps, swagger, views)
├── scripts/ # Build/CI shell scripts, code generation helpers
└── tools/ # Developer toolingEntry points#
| Binary | Path | Purpose |
|---|---|---|
grafana | pkg/cmd/grafana/main.go | Unified binary; hosts server and cli as subcommands via urfave/cli/v2 |
grafana server | pkg/cmd/grafana-server/commands/ | Starts the Grafana HTTP server and all backend services |
grafana cli | pkg/cmd/grafana-cli/commands/ | Plugin management CLI (install, update, list plugins) |
The single grafana binary is the modern entry point (combining what were previously two separate binaries). An optional third command — the standalone API server — is injected at startup if server.InitializeAPIServerFactory() succeeds, enabling a Kubernetes-style API server mode.
Package organization#
Internal packages: All backend code lives under
pkg/but most packages are directly importable — there is no root-levelinternal/boundary. The fewinternal/subdirs (e.g. within individual services) enforce package-level encapsulation. Key sub-areas:pkg/infra/— Infrastructure primitives: logging (log), metrics, database (db), tracing, caching (remotecache,localcache), kvstore, httpclient, feature flagspkg/services/— ~60 domain service packages (alerting/ngalert, dashboards, users, auth, LDAP, SCIM, secrets, etc.). Each service package typically defines its interface in the same package and provides one or more implementations.pkg/plugins/— Plugin lifecycle: discovery, loading, signature verification, gRPC backend communication, plugin registrypkg/tsdb/— One sub-package per data source backend (cloudwatch, azuremonitor, cloud-monitoring, elasticsearch, etc.)pkg/api/— HTTP handlers and route registration; handlers delegate to servicespkg/server/— Application bootstrap; Wire DI wiring files (wire.go,wire_gen.go)pkg/apiserver/+pkg/apis/+pkg/aggregator/— Kubernetes API server embedding for the new API layerpkg/expr/— Server-side expression evaluation enginepkg/setting/— INI-based configuration loading and hot-reload
Public packages (pkg/): No explicit
pkg/boundary in the classic sense — the Go module root isgithub.com/grafana/grafanaand most packages underpkg/are importable. The sub-modules listed ingo.work(e.g.pkg/apimachinery,pkg/apiserver,pkg/plugins) are explicitly published as separate modules for use by the Grafana App SDK ecosystem.apps/modules: ~20 standalone Go modules using the Grafana App SDK pattern. Each app is a self-contained resource API (e.g.apps/dashboard,apps/folder,apps/alerting/rules). They are included ingo.workbut independently versioned and can be tested in isolation.Layering: The project follows a loose layered architecture:
- Infrastructure (
pkg/infra/) — no domain knowledge - Services (
pkg/services/) — business logic, depend on infra and each other via interfaces - API handlers (
pkg/api/) — HTTP layer, depend on services - Server (
pkg/server/) — wires everything together at startup
This is enforced by convention rather than Go’s
internal/mechanism. Wire provides compile-time validation of the dependency graph.- Infrastructure (
Build system#
- Build tool: GNU Make (
Makefile) as the primary orchestrator; delegates to Go toolchain, Yarn, and Dagger - Key targets:
make build-backend— Compiles./bin/<OS>/<ARCH>/grafanafrom./pkg/cmd/grafanamake run— Backend hot-reload viaairmake test-go-unit/make test-go-integration— Backend test suitesmake gen-go— Regenerates Wire DI (wire_gen.go) after service changesmake gen-cue— Regenerates Go + TS types from CUE schemas inkinds/make gen-apps— Generates App SDK app scaffoldingmake swagger-gen— Regenerates OpenAPI/Swagger specificationsmake gen-feature-toggles— Regenerates feature flag code from definitionsmake devenv— Starts backing services (Postgres, InfluxDB, Loki, etc.) via Docker Compose
- Frontend build: Yarn 4 (via corepack) with webpack.
yarn startfor dev server,yarn buildfor production. - Docker: Yes, multi-stage (
Dockerfile). Stages:go-builder-base(golang:1.26.1-alpine),js-builder-base(node:24-alpine),alpine-base,ubuntu-base. The final image is minimal Alpine. Uses BuildKit syntax (dockerfile:1.7-labs). - CI: Dagger-based pipeline (
pkg/build/daggerbuild/) for reproducible builds; test sharding viaSHARD/SHARDSenv vars. - Go workspace:
go.workmanages 35+ Go modules. Runmake update-workspaceafter adding modules.
Notable structural decisions#
Single unified binary with subcommands: What were historically two binaries (
grafana-serverandgrafana-cli) are now a singlegrafanabinary withserverandclias top-level subcommands. A third subcommand (standalone API server) is conditionally injected if enterprise features are available — the same binary can run as a full monolith or a Kubernetes API server.go.work multi-module workspace: Grafana manages 35+ Go modules in a single workspace. Modules like
pkg/apimachinery,pkg/apiserver,pkg/plugins, and allapps/are independently versioned and published (used by the external Grafana App SDK), yet developed in a unified workspace with local replace directives handled automatically bygo.work.Wire-generated dependency injection at 1939-line scale:
pkg/server/wire_gen.go(1939 lines, generated) wires together hundreds of services. The human-authoredwire.gouses//go:build wireinjectto stay separate from the generated file. OSS vs. enterprise variants are separated intowireexts_oss.go/wireexts_enterprise.gowith build tags (oss,enterprise).apps/as the future architectural direction: Theapps/directory represents Grafana’s migration toward the App SDK pattern — each domain resource (dashboard, folder, alerting) becomes a standalone Kubernetes-style app with its own Go module, API types, and storage handlers. This is being phased in alongside the legacypkg/services/approach.CUE as the schema source of truth: Dashboard and panel type schemas live in
kinds/as CUE definitions and drive code generation in both directions:make gen-cueemits Go structs intopkg/kinds/and TypeScript types intopackages/grafana-schema/. This eliminates manual frontend/backend type synchronization for any Grafana-native resource type.pkg/tsdb/as a data source plugin repository: Core data source backends (CloudWatch, Azure Monitor, Google Cloud Monitoring, Elasticsearch, etc.) live inpkg/tsdb/as Go packages inside the monorepo. Each has its ownstandalone/subdirectory for running as an independent gRPC plugin binary — the same code can run embedded or as an external process.