cloudparts

Grafana Tempo

A tracing backend that keeps every span as Parquet files in object storage, with no database to run, and finds traces by trace ID or with TraceQL.

Type
Open source
Made by
Grafana Labs
License
AGPLv3 (Apache 2.0 until April 2021)
Facts checked
24 October 2026

What it is

Tempo stores traces and nothing else, and it stores them in a bucket. Spans arrive in OpenTelemetry (OTLP), Jaeger or Zipkin format, OTLP being the recommended one. A distributor checks them against per-tenant limits, the spans of each trace are grouped, and finished blocks are written to Amazon S3, Google Cloud Storage or Azure Blob Storage as Apache Parquet, a columnar format, so a query reads only the attributes it needs. Recent spans that are not yet in a block are served from memory. Because nothing but object storage is needed, Tempo can keep all traces instead of a small sample.

You can fetch a trace by its ID, which is how Grafana jumps to it from a log line or a metric exemplar, or search with TraceQL: { resource.service.name="frontend" } >> { status = error } finds traces in which a span of the frontend has a failing descendant. An optional metrics-generator turns spans into rate, error and duration metrics and service graphs and remote-writes them to Prometheus or Mimir. Tempo 3.0, released in May 2026, replaced the ingesters: in microservices mode the distributor now writes to a Kafka-compatible log, block-builders turn it into Parquet blocks, and live-stores answer queries for recent data. A single-process mode needs no Kafka.

Why teams pick it

  • Only object storage to run and pay for, which makes keeping 100% of traces affordable compared with an Elasticsearch or Cassandra cluster
  • Accepts OTLP, Jaeger and Zipkin, so existing instrumentation can point at it without changes
  • TraceQL can search span attributes and the shape of a trace (parent, child, descendant), and TraceQL metrics, generally available in 3.0, compute rates and percentiles straight from spans
  • Fits the rest of the Grafana stack: trace IDs link to Loki logs, exemplars link from Mimir or Prometheus metrics, and the metrics-generator builds service graphs

Watch out for

  • There is no index of span contents: searches scan Parquet columns over the time range, so wide searches over long ranges are slower than an ID lookup
  • The recommended production setup now needs a Kafka-compatible system between distributors and block-builders, one more stateful service to run
  • 3.0 removed the ingester, the compactor, the v2 block encoding and the OpenCensus receiver, so upgrading from 2.x is a migration, not a drop-in
  • AGPLv3 since April 2021; its docs warn that fetching extremely large traces, whose spans must all be collected into one result, can cause problems
Data model
Traces of spans with attributes
Query language
TraceQL, and lookup by trace ID
Client protocol
OTLP (recommended), Jaeger and Zipkin
Secondary indexes
No index of span contents; searches scan Parquet columns
How it scales
Microservices: distributors write to a Kafka-compatible log, block-builders make blocks
Storage format
Apache Parquet blocks in object storage
Ways to run it
Self-hosted, single process or microservices

Alternatives

What all distributed tracing have in common →Compare side by side →

How it fits with other technologies

TraceQL: select spans in braces, then pipe · text

# Traces where a frontend span has a failing descendant span
{ resource.service.name="frontend" } >> { status = error }

# Successful HTTP calls (&& must match within one span)
{ span.http.status_code >= 200 && span.http.status_code < 300 }

# Traces that took longer than 5 seconds end to end
{ trace:duration > 5s }

# Services with more than one error span in the same trace
{ status = error } | by(resource.service.name) | count() > 1

See it in a real stack

Self-hosted observability on the LGTM stack →
Live model
What you’re watchingServices emit logs, metrics and spans (three colours) to a collector, which routes each signal to Loki, Mimir or Tempo; all three write their data to object storage. Engineers’ dashboards and searches go through Grafana, which sends LogQL, PromQL or TraceQL to the matching store, and the answers come back from recent data and from the bucket.
Where it came from2020–2026

In 2020 Grafana Labs traced its own services with a heavily sampled system, and finding the one trace you needed was hard. Keeping every trace meant running a large Elasticsearch or Cassandra cluster to index them. Joe Elliott’s team asked a different question: “Why pay to index your traces AND your logs AND your metrics?” Logs and metric exemplars already carry trace IDs, so a trace could be found there and then fetched by ID from cheap storage.

Elliott made the first commit in January 2020, and Grafana Labs announced Tempo in October 2020 as a trace-ID lookup store “whose only dependency is object storage”. Tempo 1.0 shipped in June 2021, after the April 2021 move from Apache 2.0 to AGPLv3. Version 1.4 added the metrics-generator, which derives rate, error and duration metrics from spans.

Search grew from there. Tempo 2.0, in January 2023, made Parquet the default block format and introduced TraceQL, a query language for spans that the Parquet columns made fast enough to run. Tempo 3.0, in May 2026, split the read and write paths around a Kafka-compatible log, as Mimir had done in 3.0 the year before.

Why it’s built this way

No index, only object storage
Indexing traces was the expensive part of existing backends. Storing blocks in S3 or GCS and looking traces up by ID let Tempo keep every trace at low cost, with logs and exemplars doing the discovery.
Parquet instead of a custom block format
Search over a custom format meant reading whole traces. Parquet’s columns let a query read only the attributes it filters on; Grafana Labs reported about 10 times faster search, and TraceQL depends on it.
Accept every common tracing protocol
Teams already had Jaeger and Zipkin instrumentation. Tempo accepted those formats along with OTLP so nobody had to re-instrument to try it.
Kafka between ingestion and storage (3.0)
Tempo 3.0 separates the write path from the read path. With Kafka holding incoming spans durably, Tempo can run at a replication factor of 1, and block-builders and live-stores scale independently.

Timeline

  1. 2020

    First commit in January; announced in October

  2. 2021

    Relicensed to AGPLv3 in April; Tempo 1.0 in June

  3. 2022

    Tempo 1.4 adds the metrics-generator

  4. 2023

    Tempo 2.0 in January: TraceQL, Parquet blocks by default

  5. 2026

    Tempo 3.0 in May replaces ingesters with Kafka, block-builders and live-stores; 3.1 in September

Sources8 · facts checked 24 October 2026

Improve this page on GitHub