09

Mimir: The Distributed Metrics Backend

Source: Observability Platform source — section 9, “Mimir: The Distributed Metrics Backend”

The enterprise problem and today’s slice

Enterprise problem: A platform team must retain and query metrics from many clusters, but a single Prometheus server eventually exposes one-node retention, availability, and query-capacity limits that can hide production history during an incident.

Whole-course context: The incoming evidence is a production Prometheus design that discovers targets, scrapes samples, evaluates rules, and writes a local write-ahead log; this slice turns that local evidence into a shared metrics service.

Today’s slice: Build the Mimir storage and query boundary without transferring target discovery or scraping responsibility away from Prometheus or Alloy.

End-of-day evidence: Produce a reviewed write/read-path map plus a query proving that a remotely written series is available through Mimir’s Prometheus-compatible API.

Still unsolved: Remote-write backlog behaviour, logs, traces, profiles, cross-signal navigation, and the complete operating model remain deliberately deferred.

Customer use cases

Without explicit customer jobs, a metrics backend can become expensive shared infrastructure with no proof that it improves diagnosis or governance. These use cases bind Mimir to durable multi-cluster history and tenant-safe querying.

Use case IDActorCustomer jobSuccess outcomeDenial or recovery evidence
D09-UC-01Service ownerCompare current checkout latency with the same service across clusters and prior releasesOne PromQL result returns the authorized long-range series with cluster and version dimensionsAn unauthorized tenant query is rejected and a same-tenant control query still returns data
D09-UC-02Observability platform operatorKeep metric writes available while query load or an ingester failure occursWrite acknowledgements continue and recent/historical query probes recover within the objectiveQueue lag, rejected samples, partition health, and a recovery probe identify the failed boundary

Actor-centred user stories

Vague requirements make availability and isolation impossible to test. These stories translate the two customer jobs into observable positive and negative outcomes.

Story IDUse case IDsUser storyObservable acceptance conditions
D09-US-01D09-UC-01As a service owner, I want one long-range PromQL view across my authorized clusters, so that I can distinguish a release regression from seasonal behaviourThe query spans the requested window, includes both clusters, and the same credentials cannot read another tenant
D09-US-02D09-UC-02As an observability platform operator, I want durable ingestion separated from expensive reads, so that query pressure does not silently discard new samplesA load test records successful writes, ingest lag, query latency, an injected read-path failure, and a recovered positive probe

End-to-end product flows

A metrics query can appear healthy even while writes are being lost, so the product flow must follow both ingestion and reading to terminal evidence. Mimir’s current ingest-storage architecture uses Kafka or a compatible system as the durable handoff between distributors and read-path consumers.

Flow IDUse case IDsPathTriggerNumbered stepsTerminal evidence
D09-FLOW-01D09-UC-01, D09-UC-02HappyOperator enables a tenant’s Mimir remote-write destination and the owner runs a long-range query1. Prometheus scrapes and queues samples.<br>2. The distributor authenticates, validates, and shards the request.<br>3. Kafka durably acknowledges the write.<br>4. Ingesters expose recent samples and upload blocks.<br>5. Queriers combine recent and historical results.Tenant, series selector, time range, write status, query result, environment, timestamp, and immutable test-run ID
D09-FLOW-02D09-UC-01, D09-UC-02RecoveryOperator injects a querier or ingester disruption during continuous writes1. Writes continue through distributors and Kafka.<br>2. Health and lag signals identify the impaired read component.<br>3. Replacement consumers catch up.<br>4. The owner repeats the bounded query.<br>5. A foreign-tenant query remains denied.Failure interval, Kafka lag, recovered query result, denied cross-tenant response, unaffected write counter, and run ID

System design derived from the flows

Combining every role into one unnamed “Mimir cluster” hides which failure can affect writes, reads, or both. The design therefore separates the write entry, durable ingest boundary, recent-data consumers, block storage, and query coordination.

Use case IDEntry pointResponsible servicesAuthoritative storeFailure evidence
D09-UC-01Prometheus-compatible query API through query frontendQuery frontend, query scheduler, querier, ingester, store-gatewayObject store for durable blocks; Kafka-backed ingesters for the recent query windowQuery error class, split-query retries, store-gateway failures, missing-window comparison, and tenant-denial response
D09-UC-02Remote-write or OTLP metrics endpoint through distributorDistributor, Kafka-compatible ingest storage, ingesters, compactor, partition ringKafka for accepted recent writes and object storage for long-term blocksRejected samples, distributor errors, partition lag, unhealthy consumer, block-upload failure, and recovery probe

Mimir and Prometheus are complementary. Prometheus or Alloy discovers and scrapes local targets, applies relabeling, and buffers delivery; Mimir receives many writers, enforces tenant policy, stores blocks, and executes distributed PromQL.

Data model and ownership

If tenant identity or block ownership is ambiguous, a valid query can leak another customer’s metrics or deletion can leave billable data behind. The ownership model keeps application data at its source while Mimir owns metric samples, blocks, policy, and operational evidence.

Generated-application database: Not created in this slice — durable Mimir, Kafka, object-storage, and audit records are sufficient because the observed application remains the authority for business data.

Record or entityStore and ownerPrimary keyForeign key or opaque referenceTenant keyMaterial constraintLifecycle and deletionUse case IDs
Tenant policyMimir runtime configuration owned by the platform teamtenant_idNone — tenant policy is the root isolation recordtenant_idAuthenticated tenant must match limits and query scopeProvision, version, revoke, retain audit record, then remove after data-retention policyD09-UC-01, D09-UC-02
Accepted write batchKafka topic owned by Mimir ingestiontopic_partition_offsetOpaque sender and request references; no authority transferredtenant_idAcknowledged only after durable Kafka acceptance; series consistently map to partitionsAppend, consume, retain for configured window, then expire by topic policyD09-UC-02
Metric blockObject store owned by Mimir storagetenant_id/block_ulidReferences accepted samples through block metadatatenant_idImmutable block identity; compaction preserves samples and tenant boundaryUpload, compact, apply retention, tombstone, and delete according to tenant policyD09-UC-01, D09-UC-02
Query evidencePlatform evidence store owned by operationsquery_run_idOpaque reference to tenant, query, and deployment revisiontenant_idResult digest and denial status are immutable for the test runCreate per probe, retain for audit window, then expire without deleting source metricsD09-UC-01, D09-UC-02

Write path, read path, and scaling

Scaling all Mimir components together wastes capacity and couples unrelated failures. The split paths let operators scale ingestion, recent reads, historical reads, and query coordination from their own saturation signals.

On the write path, distributors validate and shard series to Kafka partitions; successful persistence lets the distributor acknowledge the sender before ingesters process the records. On the read path, query frontends split and cache work, schedulers queue it, and queriers combine recent samples from ingesters with historical blocks reached through store-gateways. Compactors reduce block count and apply retention in object storage. Optional rulers evaluate recording and alerting rules per tenant.

ComponentPrimary responsibilityScale or failure signal
DistributorAuthenticate, validate, limit, transform, and shard writesRequest rate, rejection reason, Kafka append latency
Kafka-compatible ingest storageDurable accepted-write pipelinePartition throughput, unavailable partitions, consumer lag
IngesterConsume partitions and serve recent samplesLag, memory/disk use, partition ownership
Query frontend and schedulerSplit, queue, cache, retry, and fairly schedule queriesQueue length, cache hit rate, rejected or retried work
Querier and store-gatewayEvaluate PromQL across recent and block dataQuery latency, object-store errors, fetched bytes
CompactorCompact blocks and enforce retentionBacklog, failed jobs, deletion-marker age

Practical proof: Prometheus to Mimir

A configuration file is only intended state, so it cannot prove that a sample crossed every boundary. Reuse the Kubernetes Day 56 checkout lab or an equivalent isolated environment and capture a runtime query plus failure counters.

Configure the writer with the in-cluster Mimir endpoint:

prometheus:
  prometheusSpec:
    retention: 2h
    remoteWrite:
      - url: http://mimir.observability.svc:9009/api/v1/push

After generating checkout traffic, query Mimir directly:

kubectl port-forward -n observability service/mimir 9009:9009
curl -fsS -G http://localhost:9009/prometheus/api/v1/query \
  --data-urlencode 'query=sum(checkout_requests_total)' \
  | jq '.data.result'

A non-empty vector proves export, scrape, remote write, Mimir acceptance, and Mimir read-path availability for that series. It does not prove long retention, cross-zone survival, or tenant isolation; record separate tests for those claims.

Production decisions and failure drills

A development single-process deployment can teach API flow but cannot prove production durability. Production design must explicitly choose tenant authentication, object storage, ingest-storage capacity, availability zones, limits, and recovery objectives.

Run these bounded drills:

  1. Deny a request with a missing or incorrect tenant identity and verify the authorized tenant still queries successfully.
  2. Stop one recent-data consumer while writes continue; record append success, lag, catch-up time, and query recovery.
  3. Apply a deliberately expensive bounded query; verify query fairness and that write acceptance stays within its objective.
  4. Temporarily deny object-store access in a test tenant; verify historical read and block-upload errors are distinguishable from live ingestion.

Choose Mimir when multi-cluster aggregation, long retention, multi-tenancy, independent scaling, or centralized governance justify the added operational system. For a small environment, one well-operated Prometheus can remain the safer design.

Key takeaways

Missing component boundaries make failures look like generic “Mimir outages,” which slows recovery. Keep these decisions explicit:

  • Prometheus or Alloy scrapes and forwards; Mimir stores and queries at shared scale.
  • Mimir 3.x ingest storage durably separates write acceptance from recent-query consumers.
  • Recent data comes from ingesters; historical data comes from object-store blocks through store-gateways.
  • Tenant identity, limits, retention, and evidence are owned platform state, not application authority.
  • A successful query is necessary evidence, but resilience and isolation require independent negative-path drills.

Checklist

An architecture review can pass while its operating evidence is missing. Complete this checklist with links to actual artifacts:

  • [ ] Named the tenant model, authentication boundary, limits, and retention policy.
  • [ ] Diagrammed separate write, recent-read, and historical-read paths.
  • [ ] Queried a known remotely written series through Mimir.
  • [ ] Captured rejected-write, ingest-lag, block-upload, and query-failure signals.
  • [ ] Proved one cross-tenant denial with an unaffected authorized control.
  • [ ] Recorded why Mimir is justified instead of assuming every cluster needs it.

Sources

Architecture claims drift as major versions change, so implementation must be checked against current primary documentation. These sources define the responsibilities used in this lesson: