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 (wraps julienschmidt/httprouter)
  • Route registration: Explicit programmatic registration in two places:
    • web/web.go (New function, lines 458–609): top-level routes
    • web/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):

  1. OpenTelemetry tracingotelhttp.NewHandler wraps the entire mux
  2. Stack tracerwithStackTracer logs panics with goroutine stacks
  3. Prometheus instrumentationpromhttp.InstrumentHandlerCounter / Duration / ResponseSize per handler
  4. Readiness gatetestReady wrapper blocks requests when TSDB is not yet ready
  5. Compressionhttputil.CompressionHandler (gzip) on query endpoints and federation
  6. OpenAPI wrapperOpenAPIBuilder.WrapHandler records 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):

MethodPathDescription
GET/Redirect to /graph (or custom root)
GET/graphReact UI (Mantine-based)
GET/metricsPrometheus self-metrics (promhttp)
GET/federateFederation endpoint — returns metrics matching match[] selectors in text format
GET/consoles/*filepathLegacy Go console templates
GET/versionBuild version JSON
GET/POST/-/reloadTrigger config reload (requires --web.enable-lifecycle)
GET/POST/-/quitGraceful shutdown (requires --web.enable-lifecycle)
GET/HEAD/-/healthyLiveness probe — always 200 OK
GET/HEAD/-/readyReadiness probe — 200 once TSDB is open and initial config loaded
GET/POST/debug/*subpathGo pprof + fgprof profiling endpoints

API v1 routes (all under /api/v1/):

MethodPathDescription
GET/POST/queryInstant PromQL query
GET/POST/query_rangeRange PromQL query
GET/POST/query_exemplarsQuery exemplars for a PromQL expression
GET/POST/format_queryPretty-print a PromQL expression
GET/POST/parse_queryParse a PromQL expression, return AST as JSON
GET/POST/labelsList all label names matching optional selectors
GET/label/:name/valuesList values for a specific label name
GET/POST/seriesList time series matching selectors
GET/scrape_poolsList configured scrape pool names
GET/targetsList all active and dropped scrape targets
GET/targets/metadataPer-target metric metadata
GET/targets/relabel_stepsDebug relabeling pipeline for a target
GET/alertmanagersList discovered Alertmanager instances
GET/metadataGlobal metric metadata (type, help, unit)
GET/status/configCurrently loaded config (YAML, redacted)
GET/status/runtimeinfoGo runtime and process info
GET/status/buildinfoBuild version, revision, Go version
GET/status/flagsAll CLI flag values
GET/status/tsdbTSDB head stats (series count, chunks, head blocks)
GET/status/tsdb/blocksList of all TSDB blocks with metadata
GET/status/walreplayWAL replay progress (during startup)
GET/featuresList of enabled feature flags
GET/notificationsPending UI notifications (JSON poll)
GET/notifications/liveSSE stream of live UI notifications
GET/alertsList currently firing and pending alerts
GET/rulesList all loaded recording and alerting rules
POST/admin/tsdb/delete_seriesDelete matching series (requires --web.enable-admin-api)
POST/admin/tsdb/clean_tombstonesApply tombstones (requires --web.enable-admin-api)
POST/admin/tsdb/snapshotCreate TSDB snapshot (requires --web.enable-admin-api)
GET/openapi.yamlOpenAPI 3.x specification (self-documenting)

Write receiver routes (gated by separate feature flags):

MethodPathFlag required
POST/api/v1/write--web.enable-remote-write-receiver
POST/api/v1/readalways 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, ChunkedSeries
  • prompb/remote.proto — Wire protocol messages: WriteRequest, ReadRequest, ReadResponse, ChunkedReadResponse
  • prompb/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.yml under remote_write:. Prometheus POSTs to external receivers.
  • Endpoint (inbound): POST /api/v1/write — accepts WriteRequest (v1) or writev2.Request (v2). Content-Type negotiated via X-Prometheus-Remote-Write-Version header.
  • Handler: storage/remote.NewWriteHandler — accepts either protobuf message type, snappy-decompresses, and appends via storage.Appendable.

Remote Read protocol#

  • Endpoint: POST /api/v1/read
  • Response types: SAMPLES (single protobuf response) or STREAMED_XOR_CHUNKS (chunked streaming). Negotiated via accepted_response_types in the request.
  • Handler: storage/remote.NewReadHandler — backed by storage.SampleAndChunkQueryable.

OTLP Write (OpenTelemetry)#

  • Endpoint: POST /api/v1/otlp/v1/metrics
  • Handler: storage/remote.NewOTLPWriteHandler — accepts pmetricotlp.ExportRequest, converts to Prometheus format (delta-to-cumulative conversion optional via feature flag), appends via storage.AppendableV2.

CLI#

prometheus binary (cmd/prometheus)#

  • Framework: github.com/alecthomas/kingpin/v2
  • Mode control: Single --agent boolean flag switches between Server mode and Agent mode
  • Flag categories and counts (~78 total):
CategoryScopeExamples
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 onlypath, retention.time, retention.size, wal-segment-size, block-duration, compaction settings (15 flags)
storage.agent.*agent onlypath, 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-featurebothComma-separated list of 20+ feature flags
runtime tuningboth--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:
CommandSubcommandsDescription
checkconfig, rules, metrics, web-config, service-discovery, healthy, readyValidate configs, rule files, and server health
queryinstant, range, series, labels, analyzeRun PromQL queries against a live server
pushmetricsPush metrics via remote write (testing use)
testrulesUnit-test recording/alerting rules in isolation
tsdbbench write, analyze, list, dump, dump-openmetrics, create-blocks-from openmetrics, create-blocks-from rulesTSDB introspection and block operations
promqlformat, label-matchers set/deletePromQL 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.Config interface + discovery.RegisterConfig(Config) global registry
  • Extension point: Each SD provider implements Config (with NewDiscoverer(DiscovererOptions) and NewDiscovererMetrics(...)) and self-registers via init() in discovery/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.Appendable interfaces
  • Extension point: The fanout storage accepts any storage.Storage implementation. Remote write/read adapters allow any HTTP-compatible backend.
  • Examples: Thanos, Cortex, Mimir all implement storage.Queryable and run the Prometheus PromQL engine against their own storage backends

Remote write receivers (third-party)#

  • Mechanism: Any HTTP server that accepts protobuf WriteRequest at 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:

PackageExported for external useDescription
github.com/prometheus/prometheus/storageStorage, Queryable, Appendable, SeriesSet, Series, ChunkQueryableCore storage interfaces — the primary extension seam
github.com/prometheus/prometheus/tsdbDB, Head, Block, Options, Open()Embedded TSDB — usable standalone by Thanos/Cortex
github.com/prometheus/prometheus/promqlEngine, Query, NewEngine()PromQL evaluator — embeddable in any backend
github.com/prometheus/prometheus/promql/parserParseExpr, Expr AST nodes, Walk()PromQL parser — used by query frontends and linters
github.com/prometheus/prometheus/model/labelsLabels, Builder, Matcher, SelectorLabel set operations — high-performance, symbol-table backed
github.com/prometheus/prometheus/model/relabelProcess(), ConfigRelabeling pipeline — used by exporters and collectors
github.com/prometheus/prometheus/storage/remoteNewWriteHandler, NewReadHandler, codec functionsHTTP handlers + codec for implementing remote read/write
github.com/prometheus/prometheus/discoveryManager, Discoverer, Config, RegisterConfigSD framework — embeddable in custom collectors
github.com/prometheus/prometheus/prompbTimeSeries, WriteRequest, ReadRequestProtobuf types for remote protocol
github.com/prometheus/prometheus/configConfig, ScrapeConfig, RemoteWriteConfigConfig 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#

  1. Self-describing via OpenAPI. The /api/v1/openapi.yaml endpoint returns a live OpenAPI 3.x spec generated by OpenAPIBuilder, which wraps every registered handler. This means the spec is always synchronized with the actual routes — no code generation drift.

  2. Dual content-type on write endpoints. /api/v1/write accepts both Remote Write 1.0 (application/x-protobuf) and 2.0 (application/x-protobuf; proto=io.prometheus.write.v2.Request), negotiated via the X-Prometheus-Remote-Write-Version header. This backward compatibility design is a deliberate protocol versioning strategy without path versioning.

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

  4. Agent mode API is a strict subset. The wrapAgent wrapper (vs wrap) 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.

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