Prometheus — API Surface#
API types#
REST/HTTP, Protobuf-over-HTTP (remote read/write), OTLP (OpenTelemetry), CLI (two binaries), Library
Prometheus exposes multiple API surfaces: a versioned REST API for queries and metadata, a binary protobuf-over-HTTP protocol for remote read/write, an OTLP receiver for OpenTelemetry metrics ingestion, and two CLI tools. It is also consumed as a library by the wider ecosystem (Thanos, Cortex, Mimir) via its public Go packages.
REST/HTTP API#
Router#
- Router: Custom
github.com/prometheus/common/route.Router(wrapsjulienschmidt/httprouter) - Route registration: Explicit programmatic registration in two places:
web/web.go(Newfunction, lines 458–609): top-level routesweb/api/v1/api.go(API.Register, lines 392–483):/api/v1/*routes
- Mount path:
/api/v1/(or<route-prefix>/api/v1/)
Middleware chain#
Applied in this order (outermost first):
- OpenTelemetry tracing —
otelhttp.NewHandlerwraps the entire mux - Stack tracer —
withStackTracerlogs panics with goroutine stacks - Prometheus instrumentation —
promhttp.InstrumentHandlerCounter / Duration / ResponseSizeper handler - Readiness gate —
testReadywrapper blocks requests when TSDB is not yet ready - Compression —
httputil.CompressionHandler(gzip) on query endpoints and federation - OpenAPI wrapper —
OpenAPIBuilder.WrapHandlerrecords API coverage on every handler
Authentication#
Authentication is delegated to prometheus-community/toolkit/web (the FlagConfig{WebConfigFile} path). The web config file (--web.config.file) supports TLS with client certificate verification (mTLS), HTTP Basic Auth, and per-user bcrypt hashing. No auth is applied at the Go route level; the http.Server is wrapped by the toolkit’s ServeMultiple which handles TLS setup.
CORS is supported via a configurable origin regex (--web.cors.origin), applied at handler construction.
Key endpoints#
Top-level routes (registered directly on the router mux):
| Method | Path | Description |
|---|---|---|
| GET | / | Redirect to /graph (or custom root) |
| GET | /graph | React UI (Mantine-based) |
| GET | /metrics | Prometheus self-metrics (promhttp) |
| GET | /federate | Federation endpoint — returns metrics matching match[] selectors in text format |
| GET | /consoles/*filepath | Legacy Go console templates |
| GET | /version | Build version JSON |
| GET/POST | /-/reload | Trigger config reload (requires --web.enable-lifecycle) |
| GET/POST | /-/quit | Graceful shutdown (requires --web.enable-lifecycle) |
| GET/HEAD | /-/healthy | Liveness probe — always 200 OK |
| GET/HEAD | /-/ready | Readiness probe — 200 once TSDB is open and initial config loaded |
| GET/POST | /debug/*subpath | Go pprof + fgprof profiling endpoints |
API v1 routes (all under /api/v1/):
| Method | Path | Description |
|---|---|---|
| GET/POST | /query | Instant PromQL query |
| GET/POST | /query_range | Range PromQL query |
| GET/POST | /query_exemplars | Query exemplars for a PromQL expression |
| GET/POST | /format_query | Pretty-print a PromQL expression |
| GET/POST | /parse_query | Parse a PromQL expression, return AST as JSON |
| GET/POST | /labels | List all label names matching optional selectors |
| GET | /label/:name/values | List values for a specific label name |
| GET/POST | /series | List time series matching selectors |
| GET | /scrape_pools | List configured scrape pool names |
| GET | /targets | List all active and dropped scrape targets |
| GET | /targets/metadata | Per-target metric metadata |
| GET | /targets/relabel_steps | Debug relabeling pipeline for a target |
| GET | /alertmanagers | List discovered Alertmanager instances |
| GET | /metadata | Global metric metadata (type, help, unit) |
| GET | /status/config | Currently loaded config (YAML, redacted) |
| GET | /status/runtimeinfo | Go runtime and process info |
| GET | /status/buildinfo | Build version, revision, Go version |
| GET | /status/flags | All CLI flag values |
| GET | /status/tsdb | TSDB head stats (series count, chunks, head blocks) |
| GET | /status/tsdb/blocks | List of all TSDB blocks with metadata |
| GET | /status/walreplay | WAL replay progress (during startup) |
| GET | /features | List of enabled feature flags |
| GET | /notifications | Pending UI notifications (JSON poll) |
| GET | /notifications/live | SSE stream of live UI notifications |
| GET | /alerts | List currently firing and pending alerts |
| GET | /rules | List all loaded recording and alerting rules |
| POST | /admin/tsdb/delete_series | Delete matching series (requires --web.enable-admin-api) |
| POST | /admin/tsdb/clean_tombstones | Apply tombstones (requires --web.enable-admin-api) |
| POST | /admin/tsdb/snapshot | Create TSDB snapshot (requires --web.enable-admin-api) |
| GET | /openapi.yaml | OpenAPI 3.x specification (self-documenting) |
Write receiver routes (gated by separate feature flags):
| Method | Path | Flag required |
|---|---|---|
| POST | /api/v1/write | --web.enable-remote-write-receiver |
| POST | /api/v1/read | always enabled |
| POST | /api/v1/otlp/v1/metrics | --web.enable-otlp-receiver |
Protobuf-over-HTTP (Remote Read/Write)#
Prometheus does not use gRPC. The remote read/write protocol uses HTTP POST with protobuf-encoded bodies, snappy-compressed.
Proto files#
prompb/types.proto— Core types:TimeSeries,Label,Sample,Exemplar,Histogram,LabelMatcher,ReadHints,ChunkedSeriesprompb/remote.proto— Wire protocol messages:WriteRequest,ReadRequest,ReadResponse,ChunkedReadResponseprompb/io/prometheus/write/v2/types.proto— Remote Write 2.0 format (newer protocol revision)prompb/io/prometheus/client/metrics.proto— Prometheus exposition format (OpenMetrics-compatible)
There are no gRPC service definitions in these proto files. All transport is plain HTTP.
Remote Write protocol#
- Endpoint (outbound): Configured in
prometheus.ymlunderremote_write:. Prometheus POSTs to external receivers. - Endpoint (inbound):
POST /api/v1/write— acceptsWriteRequest(v1) orwritev2.Request(v2). Content-Type negotiated viaX-Prometheus-Remote-Write-Versionheader. - Handler:
storage/remote.NewWriteHandler— accepts either protobuf message type, snappy-decompresses, and appends viastorage.Appendable.
Remote Read protocol#
- Endpoint:
POST /api/v1/read - Response types:
SAMPLES(single protobuf response) orSTREAMED_XOR_CHUNKS(chunked streaming). Negotiated viaaccepted_response_typesin the request. - Handler:
storage/remote.NewReadHandler— backed bystorage.SampleAndChunkQueryable.
OTLP Write (OpenTelemetry)#
- Endpoint:
POST /api/v1/otlp/v1/metrics - Handler:
storage/remote.NewOTLPWriteHandler— acceptspmetricotlp.ExportRequest, converts to Prometheus format (delta-to-cumulative conversion optional via feature flag), appends viastorage.AppendableV2.
CLI#
prometheus binary (cmd/prometheus)#
- Framework:
github.com/alecthomas/kingpin/v2 - Mode control: Single
--agentboolean flag switches between Server mode and Agent mode - Flag categories and counts (~78 total):
| Category | Scope | Examples |
|---|---|---|
config.* | both | --config.file, --config.auto-reload-interval |
web.* | both | --web.listen-address, --web.external-url, --web.enable-lifecycle, --web.enable-admin-api, --web.enable-remote-write-receiver, --web.enable-otlp-receiver, --web.cors.origin |
storage.tsdb.* | server only | path, retention.time, retention.size, wal-segment-size, block-duration, compaction settings (15 flags) |
storage.agent.* | agent only | path, wal-segment-size, retention.min-time, retention.max-time (6 flags) |
storage.remote.* | both | --storage.remote.flush-deadline |
query.* | server only | --query.max-concurrency, --query.max-samples, --query.timeout, --query.lookback-delta |
rules.* | server only | --rules.alert.for-outage-tolerance, --rules.alert.for-grace-period, --rules.max-concurrent-evals |
scrape.* | both | --scrape.adjust-timestamps, --scrape.timestamp-tolerance, --scrape.discovery-reload-interval |
log.* | both | --log.level, --log.format |
enable-feature | both | Comma-separated list of 20+ feature flags |
| runtime tuning | both | --auto-gomaxprocs, --auto-gomemlimit, --auto-gomemlimit.ratio |
Server-only and agent-only flags produce a clear error if used in the wrong mode (enforced via PreAction).
promtool binary (cmd/promtool)#
- Framework:
github.com/alecthomas/kingpin/v2 - Top-level commands:
| Command | Subcommands | Description |
|---|---|---|
check | config, rules, metrics, web-config, service-discovery, healthy, ready | Validate configs, rule files, and server health |
query | instant, range, series, labels, analyze | Run PromQL queries against a live server |
push | metrics | Push metrics via remote write (testing use) |
test | rules | Unit-test recording/alerting rules in isolation |
tsdb | bench write, analyze, list, dump, dump-openmetrics, create-blocks-from openmetrics, create-blocks-from rules | TSDB introspection and block operations |
promql | format, label-matchers set/delete | PromQL formatting and AST manipulation (experimental) |
Plugin / Extension System#
Prometheus does not have a general-purpose plugin system in the traditional sense (no hashicorp/go-plugin, no WASM, no shared libraries). Extension is achieved through three interface-based mechanisms:
Service Discovery plugins#
- Mechanism:
discovery.Configinterface +discovery.RegisterConfig(Config)global registry - Extension point: Each SD provider implements
Config(withNewDiscoverer(DiscovererOptions)andNewDiscovererMetrics(...)) and self-registers viainit()indiscovery/install/install.go - Examples:
discovery/kubernetes,discovery/aws,discovery/consul,discovery/azure— 30+ built-in providers, all using the same pattern - Third-party: External binaries can implement the HTTP SD endpoint (
discovery/http) to feed target groups without modifying Prometheus itself
Storage backends#
- Mechanism:
storage.Storage,storage.Queryable,storage.Appendableinterfaces - Extension point: The fanout storage accepts any
storage.Storageimplementation. Remote write/read adapters allow any HTTP-compatible backend. - Examples: Thanos, Cortex, Mimir all implement
storage.Queryableand run the Prometheus PromQL engine against their own storage backends
Remote write receivers (third-party)#
- Mechanism: Any HTTP server that accepts protobuf
WriteRequestat the remote write endpoint URL - Protocol: Documented in
prompb/remote.proto; no Go interface required - Examples: InfluxDB, Elasticsearch, Cortex, VictoriaMetrics all implement this receiver
Library API#
The wider ecosystem uses Prometheus as a Go library, not just as a binary. Key public packages:
| Package | Exported for external use | Description |
|---|---|---|
github.com/prometheus/prometheus/storage | Storage, Queryable, Appendable, SeriesSet, Series, ChunkQueryable | Core storage interfaces — the primary extension seam |
github.com/prometheus/prometheus/tsdb | DB, Head, Block, Options, Open() | Embedded TSDB — usable standalone by Thanos/Cortex |
github.com/prometheus/prometheus/promql | Engine, Query, NewEngine() | PromQL evaluator — embeddable in any backend |
github.com/prometheus/prometheus/promql/parser | ParseExpr, Expr AST nodes, Walk() | PromQL parser — used by query frontends and linters |
github.com/prometheus/prometheus/model/labels | Labels, Builder, Matcher, Selector | Label set operations — high-performance, symbol-table backed |
github.com/prometheus/prometheus/model/relabel | Process(), Config | Relabeling pipeline — used by exporters and collectors |
github.com/prometheus/prometheus/storage/remote | NewWriteHandler, NewReadHandler, codec functions | HTTP handlers + codec for implementing remote read/write |
github.com/prometheus/prometheus/discovery | Manager, Discoverer, Config, RegisterConfig | SD framework — embeddable in custom collectors |
github.com/prometheus/prometheus/prompb | TimeSeries, WriteRequest, ReadRequest | Protobuf types for remote protocol |
github.com/prometheus/prometheus/config | Config, ScrapeConfig, RemoteWriteConfig | Config types for embedding Prometheus config loading |
API style: Constructor functions + option structs. No fluent builder or functional options pattern at the top level; configuration is explicit through typed structs. Example:
eng := promql.NewEngine(promql.EngineOpts{
MaxSamples: 50_000_000,
Timeout: 2 * time.Minute,
LookbackDelta: 5 * time.Minute,
})
q, _ := eng.NewInstantQuery(ctx, queryable, nil, expr, time.Now())
res := q.Exec(ctx)Backward compatibility: Prometheus follows semver-like conventions but the module path is github.com/prometheus/prometheus (no /v2). Breaking changes are rare and announced through the CHANGELOG. The ecosystem projects (Thanos, Cortex) pin specific commits or minor versions rather than relying on formal guarantees.
Notable API design observations#
Self-describing via OpenAPI. The
/api/v1/openapi.yamlendpoint returns a live OpenAPI 3.x spec generated byOpenAPIBuilder, which wraps every registered handler. This means the spec is always synchronized with the actual routes — no code generation drift.Dual content-type on write endpoints.
/api/v1/writeaccepts both Remote Write 1.0 (application/x-protobuf) and 2.0 (application/x-protobuf; proto=io.prometheus.write.v2.Request), negotiated via theX-Prometheus-Remote-Write-Versionheader. This backward compatibility design is a deliberate protocol versioning strategy without path versioning.Admin API gating. Destructive admin operations (
delete_series,clean_tombstones,snapshot) are registered as normal routes but require--web.enable-admin-api. Without the flag, the routes are still registered but return 403. This means they appear in the OpenAPI spec unconditionally while being runtime-gated.Agent mode API is a strict subset. The
wrapAgentwrapper (vswrap) signals which endpoints are available in agent mode. In agent mode, query endpoints return 503 since there is no query engine. The route table itself does not change between modes.No versioning of the HTTP API beyond v1. There is no
/api/v2/path. New endpoints are added to the/api/v1/namespace; breaking changes are avoided by additive design (new optional parameters, new response fields).