Railway

Deploy Jaeger

See where a request spent its time across all your services

Deploy Jaeger

jaeger-index-cleaner

gridalpha/jaeger-railway

Just deployed

Just deployed

jaeger-collector

gridalpha/jaeger-railway

Just deployed

Just deployed

Just deployed

/usr/share/opensearch/data

jaeger-snapshots

Bucket

Just deployed

Deploy and Host Jaeger on Railway

Jaeger is the CNCF-graduated distributed tracing platform that answers what a dashboard cannot: where did this request actually spend its time? Instrumented services emit OpenTelemetry spans, Jaeger stitches them into one trace, and the UI draws it as a timeline of every hop — the API gateway, the gRPC calls it fanned out, the database query underneath, and the span that returned the error.

Self-host Jaeger on Railway with a real production topology rather than the single-container demo. This template deploys Jaeger v2 split into its two documented roles — a collector that receives spans and a query service serving the UI and API — backed by a persistent OpenSearch index, fronted by a Caddy gateway supplying the HTTP basic authentication the UI ships without, and paired with an index cleaner that enforces a retention window. Applications send OTLP to the collector's authenticated endpoint; you read the results through the gateway.

Jaeger collector, query and OpenSearch services on Railway

Getting Started with Jaeger on Railway

After deploying, open the gateway service's public URL. The browser prompts for HTTP basic credentials: the username is admin and the password is the generated JAEGER_UI_PASSWORD on the gateway service, copied from its Variables tab. Behind the prompt is the Jaeger UI, empty until something sends it spans, so the first useful action is pointing an application at the collector. Take the jaeger-collector service's public domain and its OTLP_USERNAME / OTLP_PASSWORD pair, then configure any OpenTelemetry SDK or Collector to export there. These variables are all a typical instrumented app needs:

OTEL_EXPORTER_OTLP_ENDPOINT=https://your-collector.up.railway.app
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Basic 
OTEL_SERVICE_NAME=checkout-api

Send a request through your app, return to the UI, pick your service in the Search sidebar and click Find Traces. A result opens the timeline view; the Monitor tab charts latency percentiles and request rates from the same data. The collector also has a TCP proxy on port 4317 for OTLP/gRPC, taking the same credentials.

Jaeger trace search listing twenty checkout-api traces

Jaeger timeline of a failed checkout across six services

Jaeger Monitor tab charting checkout-api latency and request rate

About Hosting Jaeger

Jaeger solves the problem logs and metrics leave open: a slow or broken request crosses several services and no one service's telemetry explains it. A trace carries one identifier across every hop, so the timeline shows which call was slow, which failed, and what ran underneath. Teams self-host it to keep telemetry in-house, or because per-span SaaS pricing stops making sense at volume.

Key capabilities:

  • Trace search and timeline view — filter by service, operation, tag, duration or error, then read the waterfall
  • Service Performance Monitoring — latency percentiles and request and error rates per operation, derived from the spans
  • Trace comparison — diff two traces structurally to see what changed
  • OpenTelemetry-native ingest — OTLP over gRPC and HTTP
  • Remote sampling and trace archiving — clients fetch their sampling rate from the collector; pinned traces outlive retention

The architecture separates the write path from the read path. jaeger-collector terminates OTLP, batches spans and writes them into OpenSearch; it is the only service your applications reach. jaeger-query reads the same indices to serve the UI and query API, and stays on the private network. opensearch is the trace store — a single node with a persistent volume and daily snapshots to a Railway object storage bucket. gateway supplies the authentication Jaeger lacks, and jaeger-index-cleaner deletes rotated span indices past the retention window.

Why Deploy Jaeger on Railway

Railway removes the infrastructure work a self-hosted tracing backend usually implies:

  • The storage tier, both Jaeger roles and the gateway deploy in one click
  • Private networking keeps OpenSearch and the query service off the internet
  • A persistent volume and managed object storage give traces durability
  • Scaling is a slider, not a cluster rebuild
  • HTTPS endpoints and a TCP proxy for OTLP/gRPC are provisioned for you

Common Use Cases

  • Debugging latency in a microservice architecture — find the downstream call behind a slow checkout instead of guessing from dashboards
  • Root-causing production errors — jump from an error span to the query, retry or timeout that caused it
  • Validating a refactor — compare traces before and after to confirm the call graph changed as intended
  • Giving an OpenTelemetry rollout a home — a backend your SDKs point at on day one

Dependencies for Jaeger

  • jaegertracing/jaeger:2.20.0 — the Jaeger v2 binary, deployed twice: as the collector and as the query service
  • opensearchproject/opensearch:3 — the trace store, one of the two backends Jaeger recommends for production
  • caddy:2-alpine — the authenticating reverse proxy in front of the UI
  • alpine — the retention worker, plus a Railway object storage bucket for snapshots
  • Source repositories: gridalpha/jaeger-railway and gridalpha/opensearch-railway

Environment Variables Reference

VariableServicePurpose
OTLP_USERNAME / OTLP_PASSWORDjaeger-collectorCredentials applications send with every span batch
JAEGER_UI_USERNAME / JAEGER_UI_PASSWORDgatewayBrowser sign-in for the Jaeger UI
OPENSEARCH_URLcollector, query, cleanerPrivate address of the trace store
RETENTION_DAYSjaeger-index-cleanerDays of span indices kept before deletion

Deployment Dependencies

Hardware Requirements for Self-Hosting Jaeger

ResourceMinimumRecommended
CPU2 vCPU across all services4+ vCPU
RAM4 GB (OpenSearch needs most of it)8 GB or more
Storage5 GB volume20 GB+, sized to trace volume × retention
RuntimeLinux containerLinux container

OpenSearch dominates the footprint; the Jaeger roles and gateway are light Go processes. Storage is the number to watch — traces are kept seven days by default, so raise the volume or lower RETENTION_DAYS on the index cleaner as ingest grows.

Self-Hosting Jaeger with Docker

For a local trial, Jaeger's all-in-one image keeps traces in memory:

docker run --rm -p 16686:16686 -p 4317:4317 -p 4318:4318 \
  jaegertracing/jaeger:2.20.0

A production install replaces memory with a real backend and splits the roles. Jaeger v2 is configured by a YAML file passed with --config; each role runs the same binary:

docker run -v $PWD/collector.yaml:/etc/jaeger/config.yaml \
  jaegertracing/jaeger:2.20.0 --config /etc/jaeger/config.yaml

Verify a deployment by posting an empty OTLP payload:

curl -u "otlp:$OTLP_PASSWORD" -X POST \
  https://your-collector.up.railway.app/v1/traces \
  -H 'content-type: application/json' -d '{"resourceSpans":[]}'

How Much Does Jaeger Cost to Self-Host?

Jaeger is free and open source under Apache 2.0, with no paid tier, seat limits or per-span billing — the project is CNCF-graduated and community-governed. OpenSearch and Caddy are Apache 2.0 too. The only cost is infrastructure, usage-based on Railway across the five services and the volume. Retention is the main lever on that bill.

FAQ

What is Jaeger? Jaeger is an open-source distributed tracing system, built at Uber and now a graduated CNCF project. It collects spans from instrumented applications, assembles them into end-to-end traces, and lets you search and visualise them.

What does this Railway template deploy? Five services: a Jaeger collector for OTLP ingest, a Jaeger query service with the UI, a single-node OpenSearch trace store on a persistent volume, a Caddy gateway providing basic authentication, and a retention worker that prunes old indices.

Why does the template include OpenSearch instead of storing traces in memory? Jaeger's in-memory store loses everything on restart and cannot be searched beyond a small buffer. OpenSearch is one of the two backends Jaeger recommends for production, and it is what makes trace search, the Monitor tab and retention work.

How do I send traces to self-hosted Jaeger from my application? Set OTEL_EXPORTER_OTLP_ENDPOINT to the collector's public URL and add an Authorization: Basic header with its credentials. Any OpenTelemetry SDK, the OpenTelemetry Collector and most service meshes export this way.

Is the Jaeger UI protected? Yes. Jaeger itself has no authentication, so this template never exposes the query service directly — a Caddy gateway with HTTP basic authentication is the only public entry point to the UI, and the OTLP endpoints require credentials of their own. Anonymous requests are rejected on both.


Template Content

jaeger-index-cleaner

gridalpha/jaeger-railway

jaeger-collector

gridalpha/jaeger-railway

jaeger-snapshots

Bucket

More templates in this category

View Template
Pyroscope profiling
Protected continuous profiling with durable Pyroscope storage.

Anton Orel
1
View Template
SigOnly
Deploy SigNoz with a working demo app & config in one click

zoeyjones
22
View Template
Unwrapped Spotify Music Stats
Unwrapped Spotify Music Stats, Estatísticas de músicas disponíveis

Jorge Henrique
1