Parent guide: AGENTS.md — product overview, architecture, domain model, global conventions Related: api/AGENTS.md (API definitions) · agent/AGENTS.md (client agent) · qan-api2/AGENTS.md (QAN backend)
pmm-managed is the core backend service of PMM Server. It manages configuration of server-side components (VictoriaMetrics, Grafana, QAN, VMAlert, Alertmanager), maintains the inventory of monitored nodes/services/agents, orchestrates backups, runs advisor checks, handles HA consensus, and exposes gRPC/REST APIs consumed by pmm-admin, pmm-agent, and the UI.
pmm-admin (CLI) ──→ gRPC/REST API ──→ pmm-managed ──→ PostgreSQL (inventory, settings)
PMM UI ───────────→ gRPC-Gateway ──→ ──→ VictoriaMetrics (scrape config)
pmm-agent ────────→ bidirectional gRPC stream ──→ ──→ Grafana API (dashboards, users)
──→ Supervisord (process management)
──→ qan-api2 (QAN forwarding)
──→ VMAlert (alerting rules)
Services follow a consistent dependency-injection pattern:
type Service struct {
db *reform.DB
l *logrus.Entry
// other dependencies as interfaces
}
func New(db *reform.DB, logger *logrus.Entry, ...) *Service {
return &Service{db: db, l: logger, ...}
}All services are composed and wired in managed/cmd/pmm-managed/main.go.
- gRPC (port 7771) — primary API protocol
- REST/JSON (port 7772) — gRPC-Gateway, auto-generated from proto definitions
- Debug (port 7773) —
/debug/metrics,/debug/pprof,/debug/vars
Some gRPC server implementations live in services/*/grpc/ subdirectories. They delegate to the parent service package for business logic. This is legacy, and newer services must implement gRPC directly in the service package.
| Entity | Table | Model File | Description |
|---|---|---|---|
| Node | nodes |
node_model.go |
Host or target: generic, container, remote, remote_rds, remote_azure_database |
| Service | services |
service_model.go |
DB/app: mysql, mongodb, postgresql, proxysql, haproxy, external, valkey |
| Agent | agents |
agent_model.go |
Monitoring agent: pmm-agent, exporters, QAN agents, vmagent, etc. |
| Settings | settings |
settings_model.go |
Server configuration (JSONB, singleton row) |
| BackupLocation | backup_locations |
— | S3/local backup storage targets |
| Artifact | artifacts |
— | Backup artifacts |
| ScheduledTask | scheduled_tasks |
— | Scheduled backup tasks |
| RestoreHistory | restore_history |
— | Backup restore records |
| Role | roles |
— | Access control roles |
Node (1) ──→ (N) Service
Service (1) ──→ (N) Agent (via service_id)
Node (1) ──→ (N) Agent (via runs_on_node_id)
PMM Agent (1) ──→ (N) Child Agent (via pmm_agent_id)
PMM uses reform (NOT gorm) for PostgreSQL:
//go:generate go tool reform
//reform:nodes
type Node struct {
NodeID string `reform:"node_id,pk"`
NodeName string `reform:"node_name"`
}Key conventions:
- Models:
managed/models/*_model.go— a new model file must carry its own//go:generate go tool reformline, ormake gensilently generates no*_reform.gofor it - Generated:
managed/models/*_reform.go(never edit) - CRUD helpers:
managed/models/*_helpers.go - Always accept
reform.Querierparameter (works with both*reform.DBand*reform.TX) - Check
reform.ErrNoRowsexplicitly for "not found" - Use
models.Find*()helpers, notq.Reload()orq.SelectOneFrom()directly - Transactions:
db.InTransactionContext(ctx, nil, func(tx *reform.TX) error { ... }) - Schema migrations in
models/database.go(databaseSchemamap, versioned)
- Environment variables:
utils/envvars.ParseEnvVars()parsesPMM_*vars;server.UpdateSettingsFromEnv()persists to DB - Database settings:
settingstable (JSONB);models.GetSettings(),models.UpdateSettings() - YAML config:
services/configloads/etc/percona/pmm/pmm-managed.yml(deprecated, mainly telemetry) - CLI flags: Kingpin flags for PostgreSQL DSN, VictoriaMetrics URL, HA config, debug ports
| Package | Responsibility |
|---|---|
models |
Domain types, reform models, DB schema migrations, CRUD helpers |
services/agents |
Agent registry, bidirectional gRPC handler, state tracking |
services/inventory |
Nodes, Services, Agents CRUD with validation |
services/management |
High-level add/remove operations (combines inventory + agent setup) |
services/server |
Settings, version, update logic, logs |
services/backup |
Backup orchestration, compatibility checks, PBM PITR |
services/checks |
Advisor check execution via Starlark |
services/alerting |
Alert template management |
services/victoriametrics |
VictoriaMetrics scrape config generation from agent/service inventory |
services/vmalert |
VMAlert alerting rules generation |
services/grafana |
Grafana API client (users, dashboards, annotations) |
services/supervisord |
Supervisord config file generation and process control |
services/ha |
Raft consensus, gossip protocol, leader election |
services/telemetry |
Telemetry data collection and reporting to Percona |
PMM supports HA via Raft consensus (services/ha/):
- Distributed state using
hashicorp/raft - Agent states synchronized across nodes via gossip
- Leader election determines which node runs certain operations (e.g., scheduled backups)
Go style, error handling, logging, and code generation follow the global conventions and are not repeated here. What follows is specific to pmm-managed.
- Define small interfaces in
deps.gofiles for dependency injection and mocking
- Don't connect to a real database in unit tests — use
github.com/DATA-DOG/go-sqlmockto mock SQL queries; reservetestdb.Openfor integration tests that genuinely require fixtures or migrations - Don't use
gormor other ORMs — onlyreform - Don't commit test binaries or artifacts
- Don't create subshells in Makefiles without reason
mock_*_test.gofiles are generated by mockerygo-sqlmockwraps areform.DB, so mocked queries are matched as SQL text- Run:
make test(in managed/) ormake test-common(from root)
testdata/pg/— PostgreSQL fixturestestdata/victoriametrics/— VictoriaMetrics configs
managed/cmd/pmm-managed/main.go— application bootstrap, all service wiringmanaged/models/database.go— database schema and migrationsmanaged/models/node_model.go,service_model.go,agent_model.go— core domain modelsmanaged/services/agents/registry.go— agent registration and lifecyclemanaged/services/agents/grpc/agent_server.go— bidirectional agent stream handlermanaged/services/inventory/grpc/— inventory API implementationsmanaged/services/ha/— HA/Raft implementationmanaged/utils/envvars/parser.go— environment variable parsingdocker-compose.yml— development environmentMakefile,Makefile.include— build and development targetsmanaged/CONTRIBUTING.md— pmm-managed contribution notes (dev setup, patterns)