Deploy Langfuse on AWS EC2
The full v3 stack with Docker Compose — Postgres, ClickHouse, Redis and MinIO — behind an HTTPS reverse proxy. From an empty instance to your first traced project.
The full v3 stack with Docker Compose — Postgres, ClickHouse, Redis and MinIO — behind an HTTPS reverse proxy. From an empty instance to your first traced project.
Since v3, Langfuse is no longer a single container + Postgres. Traces now live in ClickHouse (a columnar OLAP database), the queue in Redis, and raw payloads in S3 storage — here, MinIO. Six services in total.
ClickHouse is required since v3. If it's missing, the web container crash-loops (it can't reach clickhouse:9000). We set it up in step 04.
Six containers, ClickHouse among them: be generous with RAM. Below 4 GB, startup fails silently.
Avoid t4g / Graviton (ARM64) instances: the official images target amd64, and ARM causes crash loops. Stick to t3.
Never expose 3005, 8123 or 9000 publicly — those are internal ports. Also point a DNS A record for langfuse.mondomaine.com at the instance's elastic IP before the HTTPS step.
Once connected over SSH, install Docker and the Compose plugin via the official script.
Recent Docker uses docker compose (with a space). Your docker-compose (with a hyphen) commands also work if you install the old v1 binary — this guide uses the plugin.
Create the folder and the file. Here's the full compose: Postgres, ClickHouse, Redis and MinIO, with healthchecks and ordered startup.
Key points: the clickhouse service and its chdata volume, healthchecks on db and clickhouse, and a conditional depends_on (condition: service_healthy) so web/worker wait for the databases to be ready.
Both web and worker read this .env. Start by generating the three secrets.
NEXTAUTH_URL must be the exact public HTTPS URL, otherwise login breaks (invalid OAuth redirects). And change the default passwords (minio, redis, clickhouse) before going to production.
On first startup, the worker applies the ClickHouse migrations — this can take one to two minutes. Follow docker compose logs -f web until you see the server listening on port 3000.
web listens internally on 3000 (mapped to 3005). We don't expose it to the world — the reverse proxy handles that in the next step.
Caddy handles HTTPS automatically (Let's Encrypt certificate, renewal included) — it's the simplest option. We add it to the same compose so it can reach web internally.
Then remove the ports: - "3005:3000" mapping from the web service (Caddy reaches it internally via web:3000), and restart: docker compose up -d.
Caddy fetches the certificate on its own at the first hit on https://langfuse.mondomaine.com. If you prefer Nginx + certbot, the principle is identical: proxy to web:3000.
Open your domain over HTTPS. The first account created is yours — then create an organization, a project, and grab the API keys.
To close signups once your account exists, add AUTH_DISABLE_SIGNUP=true to the .env and rerun docker compose up -d.
Almost always an unreachable ClickHouse. Check that the hostname is clickhouse (not localhost) and that CLICKHOUSE_MIGRATION_URL=clickhouse://clickhouse:9000. Containers reach each other by service name on the Docker network.
docker compose down -v deletes the volumes = total data loss. To just stop, use docker compose down without the -v.
A running stack is good; a stack you can restore is better. The single-node trap is that data lives across three heterogeneous systems: transactional state in Postgres, traces in ClickHouse, raw payloads in MinIO. Losing any one of them breaks consistency. So you back up all three — not just Postgres out of reflex. The Langfuse backups doc covers the approach for each component.
Simplest and most reliable: a compressed daily dump with rotation. Run it from the host, straight into the db container.
ClickHouse has its own native backup command that writes straight to an S3 bucket. It's far cleaner than tarring the chdata volume (which would require the container stopped). Caveat: restore must target an identical or compatible ClickHouse version.
If you stay on single-node Docker without external S3, the documented alternative is a volume snapshot (or a tar of chdata with the container stopped). The key point stands: don't mix a ClickHouse dump from one version with a binary from another major version.
Raw payloads (ingestion events) land in MinIO first, before processing. Replicate them to a real S3 bucket with the mc client or aws s3 sync. In fact, for production the docs flatly recommend swapping MinIO for native S3 — one backup concern removed.
An untested backup is not a backup. Spin up a throwaway instance, restore all three systems onto it, and confirm an existing trace shows up in the UI. That's the only test that counts.
The single-node from this guide holds up fine for a team at moderate volume. When it grows, two levers: scale the worker horizontally, and give ClickHouse more RAM. The scaling doc gives concrete thresholds.
ClickHouse scales mostly vertically: more RAM before more nodes. And Langfuse does not support multi-shard clusters — shard count stays at 1, you add replicas, not shards.
On a single machine you can already run several worker replicas: they share the Redis queue. web stays behind the reverse proxy.
The encryption config is clear: LLM API keys and integration secrets stored in Langfuse are encrypted with ENCRYPTION_KEY, and Langfuse API keys are hashed with SALT. Both values must be generated, kept secret, and above all stable — lose ENCRYPTION_KEY and you lose access to everything it encrypted.
To stay within a major version, pin the langfuse/langfuse:3 tag (and the worker at :3): migrations apply automatically on startup. For a major jump (v2 → v3), follow the dedicated migration guide — it's not a plain pull.
Before any upgrade: back up Postgres AND ClickHouse. A schema migration that runs halfway on an unbacked database is the worst case. The ClickHouse schema is not a stable contract — it changes between versions.
It's live. Next steps: wire a SDK into your agents, build cost dashboards, and set up backups (pg_dump for Postgres, snapshots for ClickHouse and MinIO).
Official Langfuse docs ↗