Deploy RudderStack
Customer data platform that collects app events into your warehouse
rudder-transformer
Just deployed
Just deployed
/var/lib/postgresql/data
statsd-exporter
Just deployed
rudder-server
Just deployed
/rudder-tmp
warehouse-db
Just deployed
/var/lib/postgresql/data
rudder-storage
Bucket
Just deployed
Deploy and Host RudderStack on Railway
Deploy RudderStack to collect clickstream events from your websites, apps and servers and land them in a data warehouse you own. RudderStack is an open-source, warehouse-first customer data platform and the best-known self-hosted Segment alternative: its HTTP API and SDKs speak the same identify / track / page / screen / group calls, so existing instrumentation keeps working once you change the endpoint and write key. Teams self-host it when analytics data is too sensitive or too high-volume to send through a vendor.
This template runs the whole open-source stack. rudder-server is the public gateway: it authenticates events against a write key, queues them in Postgres, hands each to rudder-transformer for destination-specific shaping, writes batched load files to the rudder-storage bucket, and loads them into warehouse-db, a second Postgres that becomes your event warehouse. statsd-exporter exposes the pipeline's metrics in Prometheus format. Only rudder-server gets a public domain.

Getting Started with RudderStack on Railway
There is no login screen and no admin account to create — RudderStack open source is a headless pipeline, configured entirely by this template's variables. When the deploy finishes, open the rudder-server URL at /health: a healthy deployment answers "server": "UP", "db": "UP", "acceptingEvents": "TRUE" and "backendConfigMode": "JSON", the last confirming it runs from this configuration and not a hosted control plane. Visit /docs for the HTTP API reference, rendered by the server itself in eleven languages.
Your write key is the RUDDER_WRITE_KEY variable on rudder-server, generated at deploy time. Send it as HTTP Basic auth with an empty password:
curl -u "$RUDDER_WRITE_KEY:" -X POST \
https://your-app.up.railway.app/v1/track \
-H 'Content-Type: application/json' \
-d '{"userId":"user-1","event":"Order Completed",
"properties":{"order_id":"ORD-1","revenue":249.5,"currency":"USD"}}'
A correct key returns 200 ok; a missing or wrong one returns 401. Within a few minutes the warehouse sync creates the rudder_events schema in warehouse-db and a table per event name — tracks, order_completed, identifies, users, pages — with properties flattened into typed columns. Query it from Railway's Postgres data panel to confirm the round trip, then point your SDKs at the same URL and key.



About Hosting RudderStack
A customer data platform sits between the places events happen and the places they are analysed. RudderStack inverts the usual model: the warehouse is the primary destination and every other tool is downstream of it. Self-hosted, events never leave your infrastructure and there is no per-event pricing.
Key features:
- Segment-compatible HTTP API and SDKs for web, iOS, Android, React Native, Node, Python, Go, Java and Ruby
- Warehouse-first loading into Postgres, Snowflake, BigQuery, Redshift and ClickHouse
- 200+ event-stream destinations, plus a JavaScript framework for transforming events in flight
- A durable retry layer, so a destination outage loses no events
The architecture mirrors how RudderStack splits work internally. rudder-server holds the gateway, processor, router and warehouse scheduler in one process — the shape upstream's own Helm chart deploys. Postgres is not the warehouse: it is the durable job queue, holding every event until every destination has accepted it. rudder-transformer is separate because destination logic changes far more often than the core server.
Why Deploy RudderStack on Railway
Railway removes the infrastructure work self-hosting a data pipeline usually implies.
- Both Postgres databases and the S3-compatible bucket are provisioned and wired up for you
- Private networking keeps the transformer, queue, warehouse and metrics off the internet
- Health checks on every service, and a volume for in-flight event batches
- Scaling without a Kubernetes manifest
- One TLS public domain for your SDKs
Common Use Cases
- Replacing Segment on a product that has outgrown per-MTU pricing, with no instrumentation rewrite
- Building a customer data warehouse where events sit beside billing and CRM tables
- Meeting data-residency rules by keeping events inside your own cloud account and region
- Fanning one event stream out to product analytics, a marketing tool, a webhook and the warehouse at once
Dependencies for RudderStack
- rudder-server — gridalpha/rudderstack-railway, a thin layer over
rudderlabs/rudder-server:latestthat renders the workspace configuration from variables at boot - rudder-transformer —
rudderstack/rudder-transformer:latest, destination transformations - Postgres —
ghcr.io/railwayapp-templates/postgres-ssl:18, the job queue - warehouse-db — the same image, as the event warehouse
- statsd-exporter —
prom/statsd-exporter:latest, Prometheus metrics - rudder-storage — object storage for staging and load files
Environment Variables Reference
| Variable | Purpose |
|---|---|
RUDDER_WRITE_KEY | The credential every SDK sends. Generated at deploy |
RUDDER_WAREHOUSE_NAMESPACE | Schema the event tables land in. Default rudder_events |
RUDDER_WAREHOUSE_SYNC_FREQUENCY | Minutes between warehouse loads. Default 5 |
RUDDER_WEBHOOK_URL | Set to also POST every event to your own HTTPS endpoint |
NUM_PROCS | Transformer worker processes. Raise with traffic |
Deployment Dependencies
Hardware Requirements for Self-Hosting RudderStack
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 vCPU in total | 4+ vCPU |
| RAM | 2 GB total | 4–8 GB |
| Storage | 5 GB per Postgres, 1 GB volume | Grows with retention and volume |
| Runtime | Go, Node 22 | Provided by the images |
Throughput is bounded by the job queue more than the gateway: if it backs up, give Postgres more CPU and RAM before scaling rudder-server.
Self-Hosting RudderStack
RudderStack open source has no self-hosted control plane, so the server reads its sources and destinations from a JSON workspace configuration file rather than an admin UI. A minimal local stack is three containers:
services:
db:
image: postgres:16-alpine
environment: [POSTGRES_USER=rudder, POSTGRES_PASSWORD=pw, POSTGRES_DB=jobsdb]
transformer:
image: rudderstack/rudder-transformer:latest
backend:
image: rudderlabs/rudder-server:latest
depends_on: [db, transformer]
ports: ["8080:8080"]
volumes: ["./workspaceConfig.json:/wc.json"]
environment:
- JOBS_DB_HOST=db
- JOBS_DB_USER=rudder
- JOBS_DB_PASSWORD=pw
- JOBS_DB_DB_NAME=jobsdb
- DEST_TRANSFORM_URL=http://transformer:9090
- RSERVER_BACKEND_CONFIG_CONFIG_FROM_FILE=true
- RSERVER_BACKEND_CONFIG_CONFIG_JSONPATH=/wc.json
Writing that configuration by hand is the awkward part — it needs matching source, destination and definition objects. The template's source repository generates it at boot from plain environment variables.
Is RudderStack Free to Self-Host?
RudderStack's server is released under the Elastic License 2.0, which permits running it for your own data at no cost; the paid product is RudderStack Cloud, priced per monthly tracked user. Self-hosting has no licence fee and no event cap — you pay only for the Railway resources the services use. The licence does not allow offering RudderStack itself to third parties as a managed service.
FAQ
What is RudderStack? An open-source customer data platform. It collects behavioural events from your websites, apps and servers through Segment-compatible SDKs, then routes them to your data warehouse and to analytics and marketing tools.
What does this Railway template deploy? Five services and a bucket: the rudder-server gateway on a public URL, rudder-transformer, a Postgres job queue, a second Postgres as the event warehouse, statsd-exporter for metrics, and object storage for staging files.
Why does it need two Postgres databases? They do different jobs. The first is rudder-server's durable job queue — every event lands there on arrival and is deleted only once every destination has accepted it, which is what makes retries safe. The second is your warehouse, holding the event tables you query.
Why is an object-storage bucket required? Warehouse loads go through files, not row-by-row inserts. rudder-server batches events into compressed load files in the bucket, then loads them one transaction per table, so a failed sync replays without duplicating rows.
How do I add a destination like Amplitude or a webhook?
Set RUDDER_WEBHOOK_URL to fan every event out to your own HTTPS endpoint. For the 200+ native destinations, fork the source repository and add the destination to workspaceConfig.template.json.
Template Content
rudder-transformer
rudderstack/rudder-transformer:lateststatsd-exporter
prom/statsd-exporter:latestrudder-server
gridalpha/rudderstack-railwaywarehouse-db
ghcr.io/railwayapp-templates/postgres-ssl:18rudder-storage
Bucket
