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.
- What it is
- Distributed tracing
- Used for
- Observability
- 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
v2block 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
What Grafana Tempo uses
- Grafana Tempois queried with TraceQL fromGrafana
- Grafana Tempostores Parquet trace blocks inAmazon S3
- Grafana Tempocan store Parquet trace blocks inGoogle Cloud Storage
- Grafana Tempocan store Parquet trace blocks inAzure Blob Storage
- Grafana Tempobuffers incoming spans inApache Kafka
- Grafana Temporeceives spans over OTLP fromOpenTelemetry
- Grafana Temporemote-writes span metrics toPrometheus
What uses Grafana Tempo
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() > 1See it in a real stack
Self-hosted observability on the LGTM stack →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.
Timeline
- 2020
First commit in January; announced in October
- 2021
Relicensed to AGPLv3 in April; Tempo 1.0 in June
- 2022
Tempo 1.4 adds the metrics-generator
- 2023
Tempo 2.0 in January: TraceQL, Parquet blocks by default
- 2026
Tempo 3.0 in May replaces ingesters with Kafka, block-builders and live-stores; 3.1 in September
- GitHub: Joe Elliott’s first commit to grafana/tempo (January 2020)
- Grafana Labs blog: Announcing Grafana Tempo, a massively scalable distributed tracing system (October 2020)
- Grafana Labs: Grafana, Loki, and Tempo will be relicensed to AGPLv3 (April 2021)
- Grafana Tempo docs: Version 1.4 release notes (metrics-generator)
- Grafana Tempo docs: Version 2.0 release notes (TraceQL, Parquet as default)
- Grafana Labs blog: Open source at Grafana Labs in 2022 (Parquet, 10x search)
- Grafana Tempo docs: Version 3.0 release notes
- GitHub: grafana/tempo releases (1.0, 2.0, 3.0, 3.1 dates)
Sources8 · facts checked 24 October 2026
- Grafana Tempo docs: Architecture (distributor, Kafka, block-builder, live-store, Parquet, protocols)
- Grafana Tempo docs: Introduction (trace retrieval, large traces)
- Grafana Tempo docs: TraceQL
- Grafana Tempo docs: Construct a TraceQL query (examples, structural operators)
- Grafana Tempo docs: Version 3.0 release notes (breaking changes, TraceQL metrics GA)
- Grafana Labs blog: Announcing Grafana Tempo (October 2020)
- Grafana Labs: Grafana, Loki, and Tempo will be relicensed to AGPLv3 (April 2021)
- GitHub: grafana/tempo (AGPL-3.0, releases)