Self-hosted service
jaegertracing/jaeger avatar
jaegertracing/jaeger

Jaeger: a distributed tracing platform that now runs on the OpenTelemetry Collector

CNCF Jaeger, a Distributed Tracing Platform

23,251 stars3,139 forksGoApache-2.0

At a glance

What is it?
Jaeger is a CNCF graduated tracing backend for teams that need to store and query traces from OpenTelemetry SDKs. Version 2 rebuilt it on the OpenTelemetry Collector, which changes how it is configured and deployed.
Who is it for?
Adopt Jaeger if your services already emit OpenTelemetry traces and you want a self-hosted backend with a query UI, OTLP ingestion on 4317 and 4318, and a choice of storage plugins. Do not adopt it if you only need metrics or logs, or if you want a hosted service with no storage to operate.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Jaeger solves, and who ends up running it

A single request that crosses an API gateway, three services and a database produces log lines in five places. Correlating them by timestamp works until concurrency rises. Jaeger stores spans, the units of work a request is broken into, and reconstructs the full trace so you can see which hop consumed the time. The README describes it as a distributed tracing platform created by Uber Technologies and donated to the Cloud Native Computing Foundation, where it graduated in October 2019.

The audience is narrow but real: platform and backend engineers who run microservices and already emit OpenTelemetry data. Jaeger is a server, not an SDK. The README's architecture diagram puts the OpenTelemetry SDK inside the user application, sending over HTTP or gRPC to the Jaeger Collector, which writes to storage and answers the Query service, which the UI calls over HTTP. If you are not producing spans yet, Jaeger has nothing to show you.

It is also not a general observability suite. The repository topics list distributed-tracing, observability, opentelemetry and tracing. Metrics and logs are not what this project stores. Teams that pick it expecting one pane for everything will end up running a metrics system alongside it.

How Jaeger v2 is put together: collector components behind one binary

The most consequential fact about the current codebase is that Jaeger v2 is assembled from OpenTelemetry Collector components. The go.mod file requires a set of opentelemetry-collector-contrib modules at v0.160.0, including the spanmetrics connector, the Kafka exporter, the Prometheus exporter, and the basic auth, health check, pprof, sigv4 auth and storage extensions. That is why the README's version compatibility section says configuration compatibility is maintained between Jaeger releases and that deprecated Jaeger v1 CLI flags can disappear.

The data path in the README diagram is straightforward. The SDK sends spans over HTTP or gRPC to the Collector. The Collector writes to storage, and can also talk gRPC to a storage plugin, which in turn reaches the store. The Query service reads from storage or through the same plugin path, and the UI talks HTTP to Query. Two access modes, direct and plugin, are shown for the same storage, which matters because plugin-based backends are configured differently from native ones.

Storage is a plugin surface rather than a fixed choice. The repository keeps a ClickHouse driver (clickhouse-go/v2), an Elasticsearch client (go-elasticsearch/v9), a Cassandra driver (cassandra-gocql-driver/v2) and Badger in go.mod, and the README has a storage backend version support policy covering Elasticsearch, OpenSearch, Cassandra and ClickHouse. That policy is the part operators should read before choosing a database: for backends with an upstream lifecycle, Jaeger follows the vendor's end-of-life policy, and once upstream support ends it may drop CI coverage and stop fixing backend-specific issues for that version.

Installing Jaeger and opening the UI for the first time

The README's quick start is a single Docker command. It runs the all-in-one image, which the README says includes the UI, collector, query and in-memory storage.

bash
docker run --rm --name jaeger \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  jaegertracing/jaeger:latest

The three published ports are the whole contract. Port 16686 serves the UI, and the README says to access it at http://localhost:16686. Ports 4317 and 4318 are the OTLP receivers: gRPC on 4317 and HTTP on 4318. Any OpenTelemetry SDK pointed at those endpoints will have its spans accepted, with no Jaeger-specific exporter involved.

Because storage is in-memory in this mode, traces vanish when the container stops. That is fine for a first look and wrong for anything else. The README points to the Getting Started Guide for production deployments and more options, and the docs directory plus the docker-compose and examples directories in the repository are where those configurations live. The examples include hotrod, otel-demo, grafana-integration and reverse-proxy setups.

If you build from source instead, the toolchain matters. go.mod declares go 1.27.0, and the README's Go version policy says support for version N-1 is removed soon after a new Go minor release, with N becoming the minimum. The policy also notes that all importable code has moved to internal packages, so there is no promise of compatibility for anyone importing Jaeger as a library.

Where Jaeger is the wrong tool, and what the docs do not cover

The in-memory default is the first trap. It is presented in the quick start because it makes the UI reachable in seconds, but nothing in that command persists a trace. A team that treats the quick start as a deployment will lose data on every restart and will not notice until someone goes looking for yesterday's slow request.

Sampling is the second. The README diagram shows a gRPC arrow from the Collector back to the SDK labelled gRPC/sampling, so the collector can influence what gets recorded, but the README itself does not explain how to configure sampling. That detail lives in the documentation site, not in the repository front page.

The README is also silent on several operational questions an adopter will have. There is no rollback procedure documented for a storage schema change, no guidance on sizing storage for a given span volume, and no retention configuration shown. The storage policy tells you which backend versions are supported, not how much disk they will need.

Finally, the v2 rewrite is a migration cost, not a free upgrade. Because Jaeger now uses many OpenTelemetry Collector components, configuration options and v1 CLI flags can be deprecated, and the README's own example of a deprecation notice is a line reading (deprecated, will be removed after yyyy-mm-dd or in release vX.Y.Z, whichever is later). Anyone with a tuned v1 deployment should expect to translate configuration, and should read CONTRIBUTING.md for the deprecation rules before assuming a flag will keep working.

Jaeger against Tempo, Zipkin and plain OpenTelemetry Collector

The nearest comparison is Grafana Tempo. Tempo is built around object storage and looks traces up by ID, which keeps cost low but makes arbitrary attribute search a different exercise. Jaeger's README shows a Query service reading from a storage plugin and an index-backed store, and its supported backends are Elasticsearch, OpenSearch, Cassandra and ClickHouse, all of which can answer attribute queries. If you need to ask "show me every trace where this customer ID appears", the Jaeger model is the one that answers it without a separate index pipeline.

Zipkin is the older alternative and a different bet. It has its own data model and its own instrumentation history, while Jaeger's current ingestion path is OTLP on 4317 and 4318. If your services already emit OpenTelemetry, Jaeger accepts that data directly; a Zipkin-based setup usually means a translation layer.

The third option is to skip Jaeger entirely and run the upstream OpenTelemetry Collector with a tracing backend of your choice. That is a real option, and Jaeger v2 narrows the gap by embedding Collector components. The difference is what you get on top: the Query service and the Jaeger UI on port 16686, plus the storage plugin abstraction and the backend support policy. If you do not want that UI or those storage integrations, the Collector alone is less to operate.

Maintenance cadence, licence and upgrade costs

The repository is not archived and the last push was on 2026-09-18. Releases are frequent: v2.21.0 on 2026-09-14, v2.20.0 on 2026-07-20 and v2.19.0 on 2026-06-03, which is roughly a minor release every six to eight weeks. Upgrades therefore arrive often, and the README's compatibility section exists precisely because of that pace.

The stated deprecation policy is the number to plan around. A deprecated configuration option gets a grace period of at least 3 months or two minor version bumps, whichever is later, from the first release containing the notice, before it can be deleted. With a cadence near two months per minor release, two minor bumps and three months land close together, so a deprecation notice is realistically about one quarter of warning. Teams that pin versions and upgrade on their own schedule should read the release notes for every skipped version.

The licence is Apache-2.0, which is permissive and includes an explicit patent grant. The repository carries a NOTICE file alongside LICENSE, and the Makefile has a target list that checks tracked .go, .js, .ts, .yaml and Dockerfile files for copyright and SPDX headers. If you vendor or fork Jaeger, keep NOTICE and the per-file headers intact. That is a description of the repository's own practice, not legal advice.

Go version support is a smaller but recurring cost for anyone building from source. The README states that support for Go version N-1 is removed soon after a new Go minor release, and that removing support for an unsupported Go version is not treated as a breaking change.

Editorial conclusion

Adopt Jaeger if your services already emit OpenTelemetry traces and you want a self-hosted backend with a query UI, OTLP ingestion on 4317 and 4318, and a choice of storage plugins. Do not adopt it if you only need metrics or logs, or if you want a hosted service with no storage to operate. Before committing, verify which storage backend you will run against the policy in the README, confirm your Go toolchain if you build from source (go.mod declares go 1.27.0), and read the deprecation notice format in CONTRIBUTING.md so you know how much warning a removed configuration option gets.

Frequently asked questions

How do I install Jaeger?

The README's quick start runs the all-in-one image with a single docker run command, publishing ports 16686 for the UI and 4317 and 4318 for OTLP over gRPC and HTTP. For production deployments the README points to the Getting Started Guide.

How do I use the Jaeger UI?

The README says to access the UI at http://localhost:16686 after starting the all-in-one container, which includes the UI, collector, query and in-memory storage. In that mode traces are held in memory, so they are lost when the container stops.

How do I use Jaeger with OpenTelemetry?

The README's architecture diagram shows the OpenTelemetry SDK sending spans over HTTP or gRPC to the Jaeger Collector, and the quick start exposes OTLP on port 4317 for gRPC and 4318 for HTTP. No Jaeger-specific exporter is needed for ingestion.

How do I install Jaeger in Kubernetes?

The repository contains a docker-compose directory and an examples directory with setups such as hotrod, otel-demo and grafana-integration, but the README itself does not give Kubernetes install steps and defers production deployment to the Getting Started Guide.

How do I access the Jaeger UI?

With the quick start container running, the UI is at http://localhost:16686, which is the port the README publishes alongside 4317 and 4318. The UI talks HTTP to the Jaeger Query service, which reads from storage.

Official sources

  1. jaegertracing/jaeger on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jaegertracing-jaeger.svg)](https://hysenlabs.com/projects/jaegertracing-jaeger)