Deploy Pyroscope
Deploy and Host Grafana Pyroscope for continuous profiling
Pyroscope
Just deployed
/data
Deploy and Host Grafana Pyroscope on Railway
Grafana Pyroscope is a continuous profiling backend — the P in LGTMP. It stores CPU, memory and lock profiles collected from running processes and renders them as flame graphs in Grafana, so you can see which functions actually consume a service's time and allocations rather than inferring it from traces and metrics.
About Hosting Grafana Pyroscope
Hosting Pyroscope means running one service in monolithic mode with a volume. A single port, 4040, serves both the OTLP profiles ingest that an OpenTelemetry Collector writes to and the query API that Grafana reads, so it needs no public domain — both sides reach it over Railway's private network.
The detail that matters is storage. Pyroscope 2.x runs two storage engines at once, and several of its directories default to paths relative to the working directory, which on Railway means the container filesystem rather than the volume. This template pins every one of them under the mount and sets a retention period for each engine, so profiles survive a redeploy and stop growing without bound.
Common Use Cases
- Finding which functions dominate CPU or allocations in a service that traces show is slow
- Comparing flame graphs across deploys to confirm an optimization actually landed
- Diagnosing memory growth and lock contention in long-running processes
- Completing an LGTM stack with the fourth signal, correlated with traces in the same Grafana
Dependencies for Grafana Pyroscope Hosting
- A Railway volume for profile storage
- An OpenTelemetry Collector with a
profilespipeline, to receive profiles and write them here - Grafana, to query them — the
grafana-pyroscope-datasourceships with Grafana core
Deployment Dependencies
- Grafana Pyroscope: https://grafana.com/docs/pyroscope/latest/
- OpenTelemetry profiling: https://opentelemetry.io/docs/specs/otel/profiles/
- OpenTelemetry Collector: https://opentelemetry.io/docs/collector/
- Grafana: https://grafana.com/docs/
Implementation Details
Mount a volume at /data and set RAILWAY_RUN_UID=0 — the volume is root-owned, so a non-root
process cannot write to it. PORT=4040 matters only as the health-check target; Pyroscope takes its
listen port from the config either way.
Point the collector and Grafana at the service. Unusually, this is the same value on both, because one port serves ingest and queries:
RAILWAY_PYROSCOPE_ENDPOINT="http://${{Pyroscope.RAILWAY_PRIVATE_DOMAIN}}:4040"
On the collector, profiles need an otlphttp exporter rather than otlp — Pyroscope's ingest is
HTTP, and the exporter appends the /v1development/profiles path itself. The signal is still alpha,
so the collector also needs a feature gate and a pipeline with no processors, since batch and
resource do not accept profiles:
exporters:
otlphttp/profiles:
endpoint: ${env:RAILWAY_PYROSCOPE_ENDPOINT}
tls:
insecure: true
service:
pipelines:
profiles:
receivers: [otlp]
exporters: [otlphttp/profiles]
### Required flag
# --feature-gates=+service.profilesSupport
Without that gate the collector refuses to start outright once a profiles pipeline exists, rather than skipping it.
Keep the service at one replica. It runs as a single node with a raft metastore and a filesystem object store on one volume; a second replica gets its own volume and diverges instead of clustering.
Why Deploy Grafana Pyroscope on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying Grafana Pyroscope on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.
Template Content
Pyroscope
jratienza65/otel-lgtm-railway
