> ## Documentation Index
> Fetch the complete documentation index at: https://docs.controlplane.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Langfuse

> Deploy the full Langfuse LLM observability stack on Control Plane. Covers object storage prerequisites, secret generation, accessing the UI, sending traces, LLM connections, and backup recommendations.

## Overview

Langfuse is an open-source LLM observability and evaluation platform. This template deploys the full Langfuse stack on Control Plane — UI, background worker, and all required data stores — ready to receive traces from any LLM application.

### Architecture

* **Langfuse Web** — Next.js application serving the UI and public API. Autoscales between 2 and 5 replicas.
* **Langfuse Worker** — Background processor for trace ingestion, automated evaluations, and third-party integrations.
* **PostgreSQL** — Stores all configuration data: users, projects, API keys, prompts, datasets, and evaluation configs.
* **Redis** — BullMQ ingestion queue and short-lived cache for API keys and prompts.
* **ClickHouse** — Columnar store for all traces, observations, and scores. Powers all dashboard queries. Data files are written directly to object storage.
* **Object Storage** — AWS S3 or GCS. Shared between ClickHouse (data files) and Langfuse (raw event buffer and media uploads) using separate key prefixes (`clickhouse/`, `events/`, `media/`).

### What Gets Created

* **Standard Langfuse Web Workload** — The Next.js UI and public API with autoscaling enabled.
* **Standard Langfuse Worker Workload** — Background trace ingestion and evaluation processor.
* **Stateful PostgreSQL Workload** — Single-replica Postgres with a persistent volume set.
* **Stateful Redis Workload** — Single-replica Redis for the BullMQ queue and cache.
* **Stateful ClickHouse Workload** — Single-node ClickHouse with a persistent volume set for local metadata.
* **Volume Sets** — One persistent volume set each for PostgreSQL and ClickHouse.
* **Identity & Policy** — An identity bound to all workloads with `reveal` access to all secrets, and cloud storage access for the object store.
* **Secrets** — Opaque secrets for all component credentials and Langfuse auth keys.

<Note>
  This template does not create a GVC. You must deploy it into an existing GVC.
</Note>

## Prerequisites

Object storage must be configured before deploying. Both ClickHouse and Langfuse use the same bucket with separate key prefixes — create the bucket and credentials as described below, then fill in the `objectStore` section of `values.yaml`.

### AWS S3

<Steps>
  <Step title="Create a bucket">
    Create an S3 bucket. Set `objectStore.aws.bucket` to its name and `objectStore.aws.region` to its region.
  </Step>

  <Step title="Set up a Cloud Account">
    If you do not have one, [create a Cloud Account](https://docs.controlplane.com/guides/create-cloud-account). Set `objectStore.aws.cloudAccountName` to its name.
  </Step>

  <Step title="Create an IAM policy">
    Create an IAM policy with the following JSON (replace `YOUR_BUCKET_NAME`) and set `objectStore.aws.policyName` to its name:

    ```json theme={null}
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "s3:GetObject",
                    "s3:PutObject",
                    "s3:DeleteObject",
                    "s3:ListBucket",
                    "s3:GetObjectVersion",
                    "s3:DeleteObjectVersion"
                ],
                "Resource": [
                    "arn:aws:s3:::YOUR_BUCKET_NAME",
                    "arn:aws:s3:::YOUR_BUCKET_NAME/*"
                ]
            }
        ]
    }
    ```
  </Step>
</Steps>

### GCS

<Note>
  GCS uses S3-compatible HMAC authentication for this template. A Control Plane Cloud Account is not required.
</Note>

<Steps>
  <Step title="Create a bucket">
    Create a GCS bucket. Set `objectStore.gcp.bucket` to its name.
  </Step>

  <Step title="Create a service account and HMAC key">
    In the GCP console, go to **Settings → Interoperability** and click **Create a key for a service account → Create new account**. Name the service account, assign the `Storage Object Admin` role, and click **Done**. Copy the provided HMAC access key and secret into `objectStore.gcp.accessKeyId` and `objectStore.gcp.secretAccessKey`.

    Or use the CLI:

    ```bash theme={null}
    gcloud config set project YOUR_PROJECT_ID

    gcloud storage buckets create gs://YOUR_BUCKET_NAME

    gcloud iam service-accounts create langfuse-storage

    gcloud projects add-iam-policy-binding $(gcloud config get-value project) \
      --member="serviceAccount:langfuse-storage@$(gcloud config get-value project).iam.gserviceaccount.com" \
      --role="roles/storage.objectAdmin"

    gsutil hmac create langfuse-storage@$(gcloud config get-value project).iam.gserviceaccount.com
    ```
  </Step>
</Steps>

### Installation

Once object storage is ready, install using your preferred method:

<CardGroup cols={2}>
  <Card title="UI" href="/template-catalog/install-manage/ui" icon="laptop">
    Browse, install, and manage templates visually
  </Card>

  <Card title="CLI" href="/template-catalog/install-manage/cli" icon="terminal">
    Manage templates from your terminal
  </Card>

  <Card title="Terraform" href="/template-catalog/install-manage/terraform" icon={<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M77.941 44.5v36.836L46.324 62.918V26.082zm0 0" fill="#5c4ee5"/><path d="M81.41 81.336l31.633-18.418V26.082L81.41 44.5zm0 0" fill="#4040b2"/><path d="M11.242 42.36L42.86 60.776V23.941L11.242 5.523zm0 0M77.941 85.375L46.324 66.957v36.82l31.617 18.418zm0 0" fill="#5c4ee5"/></g></svg>}>
    Declare templates in your Terraform configurations
  </Card>

  <Card
    title="Pulumi"
    href="/template-catalog/install-manage/pulumi"
    icon={<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" id="Pulumi-Icon--Streamline-Svg-Logos" height="24" width="24">
    <desc>
        Pulumi Icon Streamline Icon: https://streamlinehq.com
    </desc>
    <path fill="#f26e7e" d="M4.683025 13.3318c0.869125 -0.5018 0.870575 -2.1264 0.003225 -3.62865s-2.27504 -2.313275 -3.1441725 -1.811475C0.672945 8.3935 0.6715 10.0181 1.53885 11.52035c0.86735 1.502275 2.27505 2.313275 3.144175 1.81145Zm0.0052 3.2167c0.86735 1.502275 0.865925 3.126875 -0.003225 3.628675 -0.86915 0.5018 -2.2768275 -0.309225 -3.144175 -1.81145 -0.8673525 -1.50225 -0.8659075 -3.126875 0.003225 -3.628675 0.8691325 -0.5018 2.276825 0.309225 3.144175 1.81145Zm5.922875 3.4243c0.86735 1.50225 0.8659 3.126775 -0.003225 3.62875 -0.869125 0.501775 -2.27685 -0.309325 -3.1442 -1.81155 -0.867325 -1.50225 -0.865875 -3.12685 0.00325 -3.628675 0.869125 -0.5018 2.276825 0.309225 3.144175 1.811475Zm-0.001925 -6.845275c0.86735 1.50225 0.8659 3.12685 -0.003225 3.628675 -0.869125 0.5018 -2.276825 -0.309225 -3.144175 -1.811475 -0.86735 -1.50225 -0.8659 -3.12685 0.003225 -3.62865 0.869125 -0.501825 2.276825 0.3092 3.144175 1.81145Z" stroke-width="0.25"></path>
    <path fill="#8a3391" d="M22.45775 11.524125c0.86725 -1.502225 0.865925 -3.12685 -0.003225 -3.62865 -0.869125 -0.501825 -2.276825 0.3092 -3.144175 1.811475 -0.86735 1.50225 -0.8659 3.126825 0.003225 3.62865 0.869125 0.501825 2.276825 -0.3092 3.144175 -1.811475Zm0.000175 3.2151c0.869075 0.5018 0.870625 2.1264 0.003225 3.62865 -0.86735 1.50225 -2.27505 2.313275 -3.144175 1.81145 -0.869125 -0.5018 -0.870575 -2.126425 -0.003225 -3.62865 0.86735 -1.50225 2.27505 -2.313275 3.144175 -1.81145ZM16.536225 18.157875c0.86915 0.501825 0.8706 2.126425 0.00325 3.628675 -0.86735 1.502125 -2.275075 2.313225 -3.1442 1.81145 -0.869125 -0.50175 -0.870575 -2.126425 -0.003225 -3.62865 0.867375 -1.502275 2.27505 -2.3133 3.144175 -1.811475Zm-0.003325 -6.843775c0.869125 0.5018 0.870575 2.126425 0.003225 3.628675s-2.27505 2.313275 -3.1442 1.811475c-0.869125 -0.501825 -0.870575 -2.126425 -0.003225 -3.628675 0.86735 -1.502275 2.27505 -2.313275 3.1442 -1.811475Z" stroke-width="0.25"></path>
    <path fill="#f7bf2a" d="M15.138225 2.06721c0 1.003615 -1.40625 1.817215 -3.14095 1.817215 -1.7347 0 -3.14095 -0.8136 -3.14095 -1.817215C8.856325 1.06359 10.262575 0.25 11.997275 0.25c1.7347 0 3.14095 0.81359 3.14095 1.81721ZM9.2166 5.482375c0 1.003625 -1.40625 1.8172 -3.14095 1.8172 -1.7347 0 -3.14095 -0.813575 -3.14095 -1.8172s1.40625 -1.817225 3.14095 -1.817225c1.7347 0 3.14095 0.8136 3.14095 1.817225Zm8.71005 1.8172c1.7347 0 3.14095 -0.813575 3.14095 -1.8172s-1.40625 -1.817225 -3.14095 -1.817225c-1.7347 0 -3.14095 0.8136 -3.14095 1.817225s1.40625 1.8172 3.14095 1.8172Zm-2.788425 1.605625c0 1.003625 -1.40625 1.8172 -3.14095 1.8172 -1.7347 0 -3.14095 -0.813575 -3.14095 -1.8172 0 -1.0036 1.40625 -1.8172 3.14095 -1.8172 1.7347 0 3.14095 0.8136 3.14095 1.8172Z" stroke-width="0.25"></path>
    </svg>}
  >
    Declare templates in your Pulumi programs
  </Card>
</CardGroup>

## Configuration

The default `values.yaml` for this template:

```yaml theme={null}
# Object store - used by both ClickHouse (data files) and Langfuse (raw event buffer + media)
# Both services share the same bucket using separate key prefixes
objectStore:
  provider: aws # Options: aws, gcp
  aws:
    bucket: my-langfuse-bucket
    region: us-east-1
    cloudAccountName: my-cloudaccount
    policyName: my-custom-policy
  gcp:
    bucket: my-langfuse-bucket
    accessKeyId: my-gcs-key        # GCS HMAC key ID
    secretAccessKey: my-gcs-secret # GCS HMAC secret key

# Langfuse application
langfuse:
  web:
    image: langfuse/langfuse:3
    minReplicas: 2  # Keep at 2+ for zero-downtime rolling deploys
    maxReplicas: 5
    resources:
      minCpu: 500m
      maxCpu: 1000m
      minMemory: 1Gi
      maxMemory: 2Gi

  worker:
    image: langfuse/langfuse-worker:3
    replicas: 1
    resources:
      minCpu: 250m
      maxCpu: 500m
      minMemory: 512Mi
      maxMemory: 1Gi

  auth:
    nextAuthSecret: ""    # Required: openssl rand -base64 32
    encryptionKey: ""     # Required: openssl rand -hex 32 (must be exactly 64 hex characters)
    salt: ""              # Required: openssl rand -base64 32

  firewall:
    inboundAllowCIDR:
      - 0.0.0.0/0  # Restrict to specific IPs in production

# PostgreSQL - stores users, projects, API keys, prompts, datasets, eval configs
postgres:
  image: postgres:18
  resources:
    minCpu: 250m
    maxCpu: 1
    minMemory: 512Mi
    maxMemory: 1Gi
  config:
    username: langfuse
    password: mypassword
    database: langfuse
  volumeset:
    capacity: 10 # initial capacity in GiB (minimum is 10)

# Redis - BullMQ ingestion queue and API key/prompt cache
redis:
  image: redis:7.4
  resources:
    minCpu: 100m
    maxCpu: 400m
    minMemory: 256Mi
    maxMemory: 512Mi
  auth:
    password: mypassword

# ClickHouse - stores all traces, observations, and scores; powers dashboards
# Data files are stored in the object store above; volumeset holds local metadata only
clickhouse:
  image: clickhouse/clickhouse-server:25.10
  resources:
    minCpu: 1
    maxCpu: 2
    minMemory: 2Gi
    maxMemory: 4Gi
  config:
    password: mypassword
    database: langfuse
  volumeset:
    capacity: 10 # initial capacity in GiB (minimum is 10)
```

### Required Auth Secrets

Three auth values must be generated and set in `values.yaml` before deploying:

```bash theme={null}
# nextAuthSecret and salt — any base64 string
openssl rand -base64 32

# encryptionKey — must be exactly 64 hex characters (32 bytes)
openssl rand -hex 32
```

<Warning>
  `encryptionKey` encrypts LLM API keys and other sensitive project data stored in PostgreSQL. It must be generated with `openssl rand -hex 32` — a base64 value will fail validation on startup. Run each command separately and copy the output into the corresponding field.
</Warning>

### Passwords

Change all component passwords before deploying to production:

* `postgres.config.password` — PostgreSQL admin password
* `redis.auth.password` — Redis password
* `clickhouse.config.password` — ClickHouse password

### Firewall

The Langfuse web UI and API are publicly accessible by default (`0.0.0.0/0`). To restrict access to specific IP ranges, update `langfuse.firewall.inboundAllowCIDR`:

```yaml theme={null}
langfuse:
  firewall:
    inboundAllowCIDR:
      - 203.0.113.0/24  # restrict to your office or application IPs
```

### Object Store

Both ClickHouse and Langfuse share one bucket with separate key prefixes:

| Prefix        | Used by                                           |
| ------------- | ------------------------------------------------- |
| `clickhouse/` | ClickHouse data files (tables, parts, metadata)   |
| `events/`     | Langfuse raw event ingestion buffer               |
| `media/`      | Langfuse media uploads (screenshots, attachments) |

Set `objectStore.provider` to `aws` or `gcp` and fill in the corresponding block. Leave the unused provider block empty.

## Accessing Langfuse

Once deployed, the Langfuse UI is accessible via the Control Plane external endpoint for the `{release-name}-langfuse-web` workload. Navigate to the endpoint in your browser to create an account and log in.

### Sending Traces via API

After creating a project and generating API keys (**Settings → API Keys**), send traces using the public API:

```bash theme={null}
curl -X POST https://YOUR_LANGFUSE_ENDPOINT/api/public/traces \
  -H "Content-Type: application/json" \
  -u "YOUR_PUBLIC_KEY:YOUR_SECRET_KEY" \
  -d '{
    "name": "my-first-trace",
    "input": "Hello",
    "output": "Hello back"
  }'
```

Or integrate using the [Langfuse SDK](https://langfuse.com/docs/sdk) for Python, TypeScript, and other languages.

### LLM Connections (Playground and Evaluations)

The Langfuse playground and LLM-as-a-Judge evaluations require LLM API keys configured through the UI. These keys are stored encrypted in PostgreSQL using your `encryptionKey`.

To configure:

1. In the Langfuse UI, go to **Settings → LLM API Keys** (for the playground) or **Evaluation → Set up default model** (for automated evals).
2. Click **Add LLM Connection**, choose your provider (OpenAI, Anthropic, etc.), and enter your API key.

## Backups

<CardGroup cols={1}>
  <Card title="PostgreSQL" icon="database">
    Stores all critical config: users, projects, API keys, prompts, datasets, and eval configs. **Most important to back up.** Enable snapshot policies on the PostgreSQL volume set via the Control Plane console — snapshots capture the full disk state and restore quickly.
  </Card>

  <Card title="ClickHouse" icon="table-columns">
    Data files are stored directly in your object store (S3 or GCS) and are inherently durable — the volume set only holds local metadata. A full restore is performed by redeploying and pointing ClickHouse at the existing bucket.
  </Card>

  <Card title="Redis" icon="bolt">
    Holds only the transient BullMQ ingestion queue and short-lived cache. Backup is not required.
  </Card>
</CardGroup>

## External References

<CardGroup cols={2}>
  <Card title="Langfuse Documentation" href="https://langfuse.com/docs" icon="book">
    Full Langfuse product documentation
  </Card>

  <Card title="Langfuse SDK Reference" href="https://langfuse.com/docs/sdk" icon="code">
    Python, TypeScript, and other language SDK guides
  </Card>

  <Card title="Langfuse Self-Hosting Guide" href="https://langfuse.com/docs/deployment/self-host" icon="server">
    Self-hosting architecture and configuration reference
  </Card>

  <Card title="Create a Cloud Account" href="https://docs.controlplane.com/guides/create-cloud-account" icon="cloud">
    Set up a Control Plane Cloud Account for S3 access
  </Card>
</CardGroup>
