rgoussu@goussu: ~/library/rust/storage
~/library/rust/storage cat time-series.md

Time-series stores from Rust

# Prometheus exposition with prometheus-client and the metrics facade, InfluxDB via influxdb2, the PG-wire stores through sqlx, and Rust as the new TSDB implementation language.

Conceptsaved 2026-08-09updated 2026-08-11 #rust#storage#time-series#prometheus#metrics#influxdb

Overview

As in Go, the time-series story is mostly metrics exposition — your service publishes, Prometheus scrapes — plus client paths for the stores you query directly. Rust's exposition landscape has two poles: the official CNCF prometheus-client crate (openmetrics-first, typed registries) and the metrics facade (instrument once, choose an exporter later — the Micrometer role). And the ecosystem note that colors everything: the new generation of time-series engines — InfluxDB 3, GreptimeDB, QuestDB's ILP ecosystem — is increasingly written in Rust, so first-party client attention follows.

Key points

  • prometheus-client (official): typed metric families (Family<Labels, Counter>), label sets as structs with EncodeLabelSet derives, OpenMetrics text exposition — wire it to an axum /metrics handler and you're scrapeable; the older prometheus crate remains widespread in existing code.
  • The metrics facade: counter!("http_requests_total", "route" => "/users") macros in library/app code, metrics-exporter-prometheus (or OTLP) chosen at the binary edge — instrument-once-decide-later, the same argument as Micrometer's; the tracing ecosystem interoperates (tracing spans → metrics via layers).
  • OpenTelemetry: opentelemetry + opentelemetry-otlp for the collector-centric shops; maturing steadily, and the natural pick when traces and metrics should share pipelines — same convergence story as the other two stacks.
  • InfluxDB: influxdb2 for the 2.x Flux/line-protocol API; InfluxDB 3's (itself Rust) FlightSQL path via arrow-flight — line protocol remains the lowest-common-denominator write path.
  • The PG-wire stores need no special client: TimescaleDB and QuestDB speak Postgres wire, so sqlx/tokio-postgres apply unchanged — hypertables and time_bucket are SQL, not API.
  • GreptimeDB / QuestDB ILP: official ingestion clients (greptimedb-ingester, questdb-rs) for the high-throughput write paths of the Rust/Java newcomers.
  • Querying Prometheus from Rust (dashboard/automation use) is a plain HTTP+serde affair (prometheus-http-query wraps it) — PromQL over the HTTP API, no special driver.

Examples

// prometheus-client exposition
#[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)]
struct Labels { route: &'static str, status: u16 }

let requests = Family::<Labels, Counter>::default();
registry.register("http_requests", "Requests served", requests.clone());
requests.get_or_create(&Labels { route: "/users", status: 200 }).inc();

async fn metrics(State(reg): State<Arc<Registry>>) -> impl IntoResponse {
    let mut buf = String::new();
    encode(&mut buf, &reg).unwrap();
    ([(header::CONTENT_TYPE, "application/openmetrics-text; version=1.0.0")], buf)
}

Related