Prometheus — Structure#
Layout pattern#
Custom Domain-Driven Layout (no traditional pkg/)
Prometheus does not use the common cmd/internal/pkg layout. Instead, all major domain subsystems live as top-level packages — tsdb/, promql/, discovery/, scrape/, storage/, web/, rules/, model/, etc. — and are public by default. The internal/ directory is minimal and used only for build tooling, not for hiding domain logic. This reflects Prometheus’s dual role: it is both a runnable server and a library of reusable components widely imported by the ecosystem.
Directory map#
prometheus/
├── cmd/
│ ├── prometheus/ Main Prometheus server binary
│ └── promtool/ CLI tool for validation, querying, and testing
├── config/ Configuration file loading and struct definitions
├── discovery/ Service discovery (30+ provider packages)
│ ├── aws/ Amazon EC2, ECS, Kafka MSK discovery
│ ├── azure/ Azure discovery
│ ├── consul/ Consul discovery
│ ├── kubernetes/ Kubernetes pods/services/nodes/endpoints discovery
│ ├── install/ Meta-package: blank-imports all discoverers (registration)
│ ├── refresh/ Generic polling/refresh helper for SD providers
│ ├── targetgroup/ TargetGroup type shared by all discoverers
│ └── ... (22 more cloud/infra providers)
├── model/ Core data model types
│ ├── exemplar/ OpenMetrics exemplar type
│ ├── histogram/ Native histogram type
│ ├── labels/ Label set and label matching
│ ├── relabel/ Relabeling configuration and execution
│ ├── rulefmt/ Rule file format
│ ├── textparse/ Prometheus and OpenMetrics text format parser
│ ├── timestamp/ Millisecond timestamp helpers
│ └── value/ Special metric values (NaN, StaleNaN, etc.)
├── promql/ PromQL query engine
│ ├── parser/ Lexer, parser, AST definitions
│ └── promqltest/ Test harness for PromQL evaluation
├── prompb/ Protobuf definitions for remote read/write protocol
│ ├── io/ Protobuf codec I/O helpers
│ └── rwcommon/ Shared remote write types
├── storage/ Storage abstraction layer
│ └── remote/ Remote read/write client implementation
├── tsdb/ Embedded time-series database
│ ├── agent/ Agent mode TSDB (write-only head)
│ ├── chunkenc/ Chunk encoding (XOR, histogram)
│ ├── chunks/ On-disk chunk management
│ ├── index/ Inverted index implementation
│ ├── record/ WAL record types
│ ├── wlog/ Write-ahead log (WAL) implementation
│ ├── tombstones/ Tombstone handling for deletions
│ └── tsdbutil/ Utilities for TSDB users
├── scrape/ Target scraping engine (HTTP metric collection)
├── rules/ Recording rules and alerting rules engine
├── notifier/ Alertmanager notification dispatch
├── web/ HTTP server, REST API, and embedded React UI
│ ├── api/v1/ HTTP API handlers
│ ├── testhelpers/ Test infrastructure for web layer
│ └── ui/ React/TypeScript frontend (Mantine UI)
├── template/ Go template engine for alert annotations
├── tracing/ OpenTelemetry tracing integration
├── compliance/ Remote write compliance test suite (separate module)
├── plugins/ Discovery plugin registration via blank imports
├── internal/
│ └── tools/ Build-only tool dependencies (go:build tools)
├── schema/ Schema validation helpers
├── util/ ~25 small utility packages
│ ├── features/ Feature flag registry
│ ├── gate/ Concurrency gate (semaphore)
│ ├── httputil/ HTTP compression, cookies
│ ├── pool/ Byte buffer pool
│ ├── testutil/ Test assertion helpers
│ └── ... (20 more: annotations, logging, stats, etc.)
├── documentation/ Example configs, Prometheus mixin, remote_storage example
├── docs/ Markdown documentation
├── scripts/ Build and release shell scripts
├── Makefile Primary build targets
├── Makefile.common Shared build logic (included from Makefile)
├── Dockerfile Production Docker image (pre-built binaries)
├── Dockerfile.distroless Distroless variant
├── go.mod Module root
└── go.work Go workspace (5 member modules)Entry points#
| Binary | File | Purpose |
|---|---|---|
prometheus | cmd/prometheus/main.go | Main monitoring server: scraping, TSDB, PromQL, alerting, web UI |
promtool | cmd/promtool/main.go | CLI for: config validation, rule checking, metric querying, TSDB analysis, backfill, unit testing, remote write debugging |
The promtool binary is a substantial CLI with ~15 subcommands (analyze, archive, backfill, debug, query, rules, sd, tsdb, unittest, etc.).
Package organization#
Internal packages:
internal/tools— build tooling dependencies using//go:build toolspattern. No domain logic is hidden ininternal/.Public packages (top-level): All major subsystems are public packages, making Prometheus a large importable library:
tsdb/— TSDB is widely used directly by other projectspromql/— PromQL engine imported by Thanos, Cortex, etc.model/labels,model/textparse— Shared with the ecosystemstorage/— Storage interfaces used by compatible systemsdiscovery/— SD packages reused by other CNCF tools
Layering: Domain-driven rather than clean architecture. The layers are roughly:
web/api → promql → storage → tsdb ↘ scrape → targets rules → promql discovery → scrape notifier → (alertmanager HTTP) config → (all of the above)There is no strict dependency inversion; packages depend on concrete types from peer packages. The
storagepackage defines interfaces (Queryable,Appendable) that decouplepromqlfromtsdb.
Build system#
- Build tool: GNU Make with
Makefile.common(shared across Prometheus org projects) - Key targets:
make build— Buildsprometheusandpromtoolbinariesmake test— Runs Go test suitemake lint— Runsgolangci-lintmake assets— Builds React frontend, embeds into Go binarymake docker— Multi-arch Docker image buildmake genproto— Regenerates protobuf Go code
- Docker: Yes. Two images:
Dockerfile(busybox base) andDockerfile.distroless. Both are single-stage, consuming pre-built binaries from.build/— actual compilation happens in Makefile, not Docker build. Multi-arch: amd64, armv7, arm64, ppc64le, riscv64, s390x. - UI build: React/TypeScript app in
web/ui/mantine-ui/built with npm and embedded viago:embed. Can be skipped by settingPREBUILT_ASSETS_STATIC_DIR. - Go workspace:
go.workgroups 5 modules: root,compliance/,documentation/examples/remote_storage/,internal/tools/, andweb/ui/mantine-ui/src/promql/tools/.
Notable structural decisions#
No
pkg/directory. All domain packages are at the root. This makes the module surface area large and importable — intentional since much of the ecosystem imports Prometheus packages directly. The trade-off is that there’s no clear “public API” boundary.Discovery plugin registration via blank imports. The
discovery/install/package aggregates all discoverers via blank imports. Users embedding Prometheus can selectively import only the providers they need (seeplugins/minimum.gowhich includes only file and http). This is a clean self-registration pattern using Go’sinit()mechanism.tsdb/as a self-contained subsystem. The TSDB has its own sub-packages for WAL, chunks, index, encoding, tombstones, and an agent mode — essentially a separate library bundled in the repo rather than extracted. This enables tight co-evolution of the storage format and query engine.prompb/for the remote protocol. Protobuf definitions and generated code live alongside the project, withbuf.yamlfor schema management. The remote write/read protocol is versioned within the package.Go workspace with multiple modules. The compliance test suite and the embedded PromQL tools for the UI are separate Go modules, preventing the main module from pulling in heavy test/frontend dependencies. This is increasingly common in large Go projects.
compliance/as a separate module. Remote write compliance testing has its own module with its owngo.mod, allowing it to be used as a standalone tool or imported by third parties implementing remote write.