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#

BinaryFilePurpose
prometheuscmd/prometheus/main.goMain monitoring server: scraping, TSDB, PromQL, alerting, web UI
promtoolcmd/promtool/main.goCLI 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 tools pattern. No domain logic is hidden in internal/.

  • Public packages (top-level): All major subsystems are public packages, making Prometheus a large importable library:

    • tsdb/ — TSDB is widely used directly by other projects
    • promql/ — PromQL engine imported by Thanos, Cortex, etc.
    • model/labels, model/textparse — Shared with the ecosystem
    • storage/ — Storage interfaces used by compatible systems
    • discovery/ — 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 storage package defines interfaces (Queryable, Appendable) that decouple promql from tsdb.

Build system#

  • Build tool: GNU Make with Makefile.common (shared across Prometheus org projects)
  • Key targets:
    • make build — Builds prometheus and promtool binaries
    • make test — Runs Go test suite
    • make lint — Runs golangci-lint
    • make assets — Builds React frontend, embeds into Go binary
    • make docker — Multi-arch Docker image build
    • make genproto — Regenerates protobuf Go code
  • Docker: Yes. Two images: Dockerfile (busybox base) and Dockerfile.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 via go:embed. Can be skipped by setting PREBUILT_ASSETS_STATIC_DIR.
  • Go workspace: go.work groups 5 modules: root, compliance/, documentation/examples/remote_storage/, internal/tools/, and web/ui/mantine-ui/src/promql/tools/.

Notable structural decisions#

  1. 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.

  2. 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 (see plugins/minimum.go which includes only file and http). This is a clean self-registration pattern using Go’s init() mechanism.

  3. 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.

  4. prompb/ for the remote protocol. Protobuf definitions and generated code live alongside the project, with buf.yaml for schema management. The remote write/read protocol is versioned within the package.

  5. 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.

  6. compliance/ as a separate module. Remote write compliance testing has its own module with its own go.mod, allowing it to be used as a standalone tool or imported by third parties implementing remote write.