---
title: "Deploy Langfuse v4"
description: "Self-host Langfuse on Railway: LLM tracing, evals and prompt management"
category: "Observability"
url: https://railway.com/deploy/langfuse-observability
---

# Deploy Langfuse v4

Self-host Langfuse on Railway: LLM tracing, evals and prompt management

**[Deploy Langfuse v4 on Railway](https://railway.com/template/langfuse-observability)**

- **Creator:** A3A
- **Category:** Observability
- **Total deploys:** 3

## Template content

### langfuse-worker https://cdn.jsdelivr.net/gh/selfhst/icons/svg/langfuse.svg

- **Image:** langfuse/langfuse-worker
- **Health check:** /api/health

### langfuse-web https://cdn.jsdelivr.net/gh/selfhst/icons/svg/langfuse.svg

- **Image:** langfuse/langfuse
- **Health check:** /api/public/health
- **Public domain:** Yes

### clickhouse https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/clickhouse.svg

- **Image:** clickhouse/clickhouse-server
- **Start command:** `/entrypoint.sh -- --logger.console=1 --logger.level=information`
- **Health check:** /ping

### Redis https://cdn.sanity.io/images/sy1jschh/production/0ce0bfdcfbdbf69662b1116671f97c2dd788b655-157x157.svg

- **Image:** redis:8.2.1
- **Start command:** `/bin/sh -c "rm -rf $RAILWAY_VOLUME_MOUNT_PATH/lost+found/ && exec docker-entrypoint.sh redis-server --requirepass $REDIS_PASSWORD --save 60 1 --dir $RAILWAY_VOLUME_MOUNT_PATH"`

### Postgres https://devicons.railway.app/i/postgresql.svg

- **Image:** ghcr.io/railwayapp-templates/postgres-ssl:18

## Buckets

- **langfuse**

## Documentation

![Langfuse logo](https://private-user-images.githubusercontent.com/48529566/601636492-5810ae13-15d6-4b60-afd2-927adc501861.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3ODU3ODY0MjMsIm5iZiI6MTc4NTc4NjEyMywicGF0aCI6Ii80ODUyOTU2Ni82MDE2MzY0OTItNTgxMGFlMTMtMTVkNi00YjYwLWFmZDItOTI3YWRjNTAxODYxLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjA4MDMlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwODAzVDE5NDIwM1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWFlMWVjNWZkMDZlOTk3MTM2N2QwNzUxMDI5YTY0MjNkMjRkMzIwMjI1MDUzNThmNzQ3YTg3ZGI3NmExZGZlYzcmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JnJlc3BvbnNlLWNvbnRlbnQtdHlwZT1pbWFnZSUyRnBuZyJ9._Wm50-VKROwfT-1MRXqfmdFDZ2cy6YioswzWet7ndLE)

# Deploy and Host Langfuse on Railway

Langfuse is the open-source LLM engineering platform: tracing, evaluations, prompt management, cost metrics and datasets in one MIT-licensed app. Teams shipping AI agents and RAG systems use it to see which prompt version produced an answer and what a chain cost in tokens. It is OpenTelemetry-native, so instrumenting an app is a decorator, not a rewrite, and tracing needs no LLM provider key.

Self-host Langfuse on Railway behind one public domain. `langfuse-web` serves the UI and OTLP endpoint; the private `langfuse-worker` (`4.3.1`, port `3030`) drains the queue. Managed **Postgres**/**Redis**, a pinned **ClickHouse** with a volume and a Railway **bucket** hold accounts, traces, queues and events.

![Langfuse Railway architecture](https://res.cloudinary.com/rroe4rtk/image/upload/v1785783362/0bd810b1-4bda-4b8d-91b5-a42fafe03245.png)

## Getting Started with Langfuse on Railway

Open the generated Railway domain once every service is green. Langfuse seeds no admin account, so **the first account created becomes the owner** — create it, then set `AUTH_DISABLE_SIGNUP=true` to close registration. Create an organization and a project, then open **Project Settings → API Keys** for a key pair; the `.env` snippet there should carry `https://${{RAILWAY_PUBLIC_DOMAIN}}`, and `localhost` means `NEXTAUTH_URL` is wrong. Send one trace and check the **Tracing** table — a trace landing there proves the whole path: web → Redis → bucket → worker → ClickHouse.

![Langfuse dashboard screenshot](https://res.cloudinary.com/rroe4rtk/image/upload/v1785784404/01-dashboard_llpfez.png)
![Langfuse Trace Detail](https://res.cloudinary.com/rroe4rtk/image/upload/v1785784417/03-trace-detail_lkqqbd.png)
![Langfuse Tracing](https://res.cloudinary.com/rroe4rtk/image/upload/v1785784417/02-tracing_vajphe.png)

## Sending Your First Trace to Self-Hosted Langfuse

Set `LANGFUSE_HOST` to `https://${{RAILWAY_PUBLIC_DOMAIN}}` plus your key pair; the Python OpenAI wrapper is an import swap:

```
from langfuse.openai import openai

openai.chat.completions.create(model="gpt-4o-mini",
    messages=[{"role": "user", "content": "hi"}])
```

## About Hosting Langfuse

Self-host when prompts cannot sit in a vendor account, or when volume makes per-unit cloud pricing the wrong shape.

- **OpenTelemetry tracing** — nested traces over LLM calls, retrievals, tool calls and agent steps.
- **Prompt management** — version and roll back prompts, fetched at runtime via a cached client.
- **Evaluations** — LLM-as-a-judge, code evaluators, annotation queues.
- **SDKs** — Python and JS/TS plus LangChain, LlamaIndex, the Vercel AI SDK and LiteLLM.

## Why Deploy Langfuse on Railway

Railway runs the whole five-service stack as one project:

- Pinned upstream images — no `latest` surprises on redeploy.
- ClickHouse with a volume and console logging preset.
- Managed object storage replaces MinIO — one fewer container.
- Health checks, restart policies and a Node heap ceiling preset.

## Common Use Cases

- **Debugging AI agents** — replay a failing run and find the tool call or prompt version behind it.
- **Controlling LLM spend** — attribute token cost to a user, feature or customer.
- **Regression-testing prompts** — score each prompt or model change against real traces before rollout.

## Dependencies for Langfuse

- **`langfuse-web`** — [`langfuse/langfuse`](https://hub.docker.com/r/langfuse/langfuse), port `3000`, health check `/api/public/health`. UI, API and OTLP endpoint; runs migrations at boot.
- **`langfuse-worker`** — [`langfuse/langfuse`](https://hub.docker.com/r/langfuse/langfuse-worker), port `3030`, health check `/api/health`, private. **Keep its tag identical to the web image.**
- **`clickhouse`** — `clickhouse/clickhouse-server`, ports `8123`/`9000`, volume at `/var/lib/clickhouse`. Langfuse v4 requires **&gt;= 25.12**, 26.4 recommended.
- **`Postgres`** — managed PostgreSQL 18 (**15+ required**): accounts, projects, keys, prompts, datasets.
- **`Redis`** — managed Redis 8.2.1 (**7+ required**): BullMQ queues and the prompt cache.
- **Object storage bucket** — Railway managed S3 storage: one bucket, three prefixes (`events/`, `media/`, `exports/`). Its single endpoint serves server writes and presigned browser uploads, replacing MinIO.

### Langfuse Environment Variables Reference

| Variable | Service | What it does |
|---|---|---|
| `NEXTAUTH_URL` | web | Public base URL; wrong values break login |
| `SALT` | web, worker | Hashes API keys; rotating invalidates them |
| `ENCRYPTION_KEY` | web, worker | Encrypts stored LLM secrets, 64 hex chars |

`SALT` and `ENCRYPTION_KEY` must be stable and identical on both; `NEXTAUTH_SECRET` is web-only.

### Deployment Dependencies

[langfuse/langfuse](https://github.com/langfuse/langfuse) (MIT core, `ee/` commercial); docs at [langfuse.com/self-hosting](https://langfuse.com/self-hosting). Pin both images to the same registry-verified tag — `v4.2.0` was tagged but never published.

## Hardware Requirements for Self-Hosting Langfuse

| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 vCPU per app container, 2 for ClickHouse | 4 vCPU each |
| RAM | 4 GB web, 4 GB worker, 8 GB ClickHouse | 16 GB ClickHouse |
| Storage | 5 GB ClickHouse volume | 20 GB+, by retention |
| Runtime | ClickHouse 25.12+, in the images | ClickHouse 26.4 |

Idle draw is ~1.0–1.6 GB per container. `NODE_OPTIONS=--max-old-space-size=3072` caps the Node heap; without it Node sizes it from the host's RAM and risks OOM.

## Self-Hosting Langfuse with Docker

Upstream ships a Compose file covering both apps and all four stores:

```
git clone https://github.com/langfuse/langfuse.git
cd langfuse
docker compose up -d
```

Or run the app container alone against existing stores:

```
docker run -d --name langfuse-web -p 3000:3000 \
  -e DATABASE_URL="postgresql://user:pass@postgres:5432/langfuse" \
  -e CLICKHOUSE_URL="http://clickhouse:8123" \
  -e CLICKHOUSE_MIGRATION_URL="clickhouse://clickhouse:9000" \
  -e CLICKHOUSE_USER="langfuse" -e CLICKHOUSE_PASSWORD="" \
  -e REDIS_CONNECTION_STRING="redis://:pass@redis:6379" \
  -e NEXTAUTH_URL="https://langfuse.example.com" \
  -e NEXTAUTH_SECRET="" -e SALT="" \
  -e ENCRYPTION_KEY="&lt;64 hex&gt;" langfuse/langfuse:4.3.1
```

Run the worker image with the same variables and `PORT=3030`.

## Langfuse vs LangSmith and Helicone

| | Langfuse | LangSmith | Helicone |
|---|---|---|---|
| Self-host | Full product, MIT | Enterprise only | OSS core |
| Instrumentation | SDK + OpenTelemetry | LangChain-native | Proxy |
| Prompt management | Versioned | Yes | Limited |

LangSmith suits all-LangChain stacks; Helicone wins on setup speed. Arize Phoenix, Braintrust and W&amp;B Weave overlap on evals.

## How Much Does Langfuse Cost to Self-Host?

Langfuse core is MIT-licensed and free to self-host with unlimited events and users; only the `ee/` directory is commercially licensed, and those terms survived ClickHouse's acquisition of Langfuse in January 2026. Langfuse Cloud runs from a free Hobby tier (50k units/month) through Core at $29/month and Pro at $199/month to Enterprise at $2,499/month. Self-hosting on Railway costs infrastructure only.

## Troubleshooting Self-Hosted Langfuse

**ClickHouse logs `Listen [0.0.0.0]:8123 failed: Address already in use`** → harmless. The image binds `::` dual-stack first, so later IPv4 binds return `EADDRINUSE`, on `9000`, `9004`, `9005` and `9009` too. Confirm with `Ready for connections.`

**ClickHouse logs are empty** → the image logs to files, not stdout. Use the start command `/entrypoint.sh -- --logger.console=1 --logger.level=information`; the default `trace` level floods Railway's log cap.

**`langfuse-web` logs `dial tcp ...:9000: connection refused`** → web runs the ClickHouse migrations at boot and Railway has no start ordering, so a joint redeploy races ClickHouse. It retries and self-heals.

**Browser media uploads fail** → point `LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT` at the bucket's public endpoint and keep `FORCE_PATH_STYLE=true`.

## FAQ

**What is Langfuse?**

An open-source, MIT-licensed platform for tracing, evaluating and managing prompts in AI apps. Every LLM call becomes a nested trace carrying tokens, cost and latency.

**Why does self-hosted Langfuse need ClickHouse, Postgres, Redis and object storage?**

Postgres stores accounts, projects, keys and prompts; ClickHouse is the OLAP store behind fast dashboards over millions of spans; Redis carries the ingestion queue and cache; the bucket holds raw events, media and exports.

**What are the default login credentials for self-hosted Langfuse?**

None. The first account registered becomes the owner, so create yours immediately, then set `AUTH_DISABLE_SIGNUP=true`.

**How do I send OpenTelemetry traces to self-hosted Langfuse on Railway?**

Point your OTLP HTTP exporter at `/api/public/otel/v1/traces` on your Railway domain, with HTTP Basic auth: public key as username, secret key as password.


## Similar templates

- [Pyroscope profiling](https://railway.com/deploy/pyroscope-profiling) — Protected continuous profiling with durable Pyroscope storage.
- [SigOnly](https://railway.com/deploy/sigonly) — Deploy SigNoz with a working demo app & config in one click
- [Unwrapped Spotify Music Stats](https://railway.com/deploy/wide-bold) — Unwrapped Spotify Music Stats, Estatísticas de músicas disponíveis

Open this page in a browser: https://railway.com/deploy/langfuse-observability
