Switching Jaeger Trace Storage Backend Without Changing Application Code
Learn how to move Jaeger trace storage from in‑memory to Cassandra or Elasticsearch by updating only the collector configuration, keeping your instrumented services unchanged.
13 Apr 2026, 03:36 UTC

Problem: Trace storage limits in development
When you first instrument a service with Jaeger, the simplest way to see traces is to run the all‑in‑one image with the in‑memory storage backend. This works fine for low traffic, but as soon as you increase load or want to retain traces for longer than a few minutes, the in‑memory store drops old spans and the UI shows gaps.
Thesis: Jaeger’s storage API lets you change the backend without touching your instrumented code
Jaeger separates trace collection, storage, and querying behind a pluggable spanStorage interface. The collector and query services only need to know which implementation to use; the application continues to send spans over HTTP/thrift/gRPC exactly as before.
Worked example: moving from in‑memory to Cassandra
- Prerequisites: a running Cassandra cluster (version 3.11 or later) reachable from the Jaeger collector pods, and permission to edit the Jaeger Operator custom resource or the collector ConfigMap.
- Update the collector configuration. If you are using the Jaeger Operator, patch the
Jaegercustom resource: - Apply the change and restart the collector. With the Operator, simply save the CR; the operator rolls out a new collector pod. With Docker Compose, run
docker compose up -d collector. - Verify the switch:
- Check the collector logs for a line like
Initializing Cassandra storageand no error messages. - Generate a few test requests to your instrumented service.
- Open the Jaeger UI (
http://jaeger-query:16686) and confirm that the new traces appear and are retained beyond the in‑memory timeout.
- Check the collector logs for a line like
spec:
storage:
type: cassandra
cassandra:
servers: cassandra-cluster.default.svc:9042
keyspace: jaeger_v1_dc1
If you run Jaeger via Docker Compose, edit the collector’s environment variable:
SPAN_STORAGE_TYPE=cassandra
CASSANDRA_SERVERS=cassandra-host:9042
CASSANDRA_KEYSPACE=jaeger_v1_dc1
Trade‑offs and limitations
- Data migration is manual: traces already stored in the in‑memory backend (or Cassandra) are not copied automatically when you switch to Elasticsearch. You must run an export/import process if you need historic data.
- Operational overhead differs: Cassandra requires node repair, compaction monitoring, and adequate disk bandwidth for high write throughput. Elasticsearch needs careful heap sizing, shard count planning, and monitoring of query latency spikes.
- Version compatibility: the storage plugin APIs are stable across Jaeger releases 1.30‑1.40, but always check the release notes for breaking changes when upgrading Jaeger itself.
Actionable closing
Start with the in‑memory backend for local development or low‑traffic staging. When trace volume grows, point the collector at a Cassandra or Elasticsearch cluster by changing only spanStorage.type (and the backend‑specific settings). Verify the switch via collector logs and the Jaeger UI, then monitor the chosen backend’s operational metrics. If you later need to move to another store, repeat the same configuration change—your instrumented services stay untouched.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.