Langfuse v4: up to 165ร— faster ยท Read more
Self HostingClickhouse
Version: v4

ClickHouse

This is a deep dive into ClickHouse configuration. Follow one of the deployment guides to get started.

ClickHouse is the main OLAP storage solution within Langfuse for our Trace, Observation, and Score entities. It is optimized for high write throughput and fast analytical queries. This guide covers how to configure ClickHouse within Langfuse and what to keep in mind when (optionally) bringing your own ClickHouse.

Langfuse v3 supports ClickHouse versions >= 24.3. Langfuse v4 requires ClickHouse >= 25.12 (26.4 recommended) for lightweight updates, the JSON type, and full-text search โ€” see the v3 to v4 upgrade guide.

Official and Community Support

ClickHouse can be consumed as a managed service or self-managed on your own infrastructure. We distinguish between officially supported and community-supported deployment options:

  • Official: Maintained and tested by the Langfuse team. We prioritize bug reports for these options.
  • Community: Expected to work based on community usage. We do not systematically test these options; support is best-effort and fixes often depend on community contributions.

In either case, please report problems via GitHub issues โ€” pull requests that fix or improve support for community-supported options are highly welcome.

Configuration

Langfuse accepts the following environment variables to fine-tune your ClickHouse usage. They need to be provided for the Langfuse Web and Langfuse Worker containers.

VariableRequired / DefaultDescription
CLICKHOUSE_MIGRATION_URLRequiredMigration URL (TCP protocol) for the ClickHouse instance. Pattern: clickhouse://<hostname>:(9000/9440)
CLICKHOUSE_MIGRATION_SSLfalseSet to true to establish an SSL connection to ClickHouse for the database migration.
CLICKHOUSE_URLRequiredHostname of the ClickHouse instance. Pattern: http(s)://<hostname>:(8123/8443)
CLICKHOUSE_USERRequiredUsername of the ClickHouse database. Needs the grants listed under user permissions.
CLICKHOUSE_PASSWORDRequiredPassword of the ClickHouse user.
CLICKHOUSE_DBdefaultName of the ClickHouse database to use.
CLICKHOUSE_CLUSTER_ENABLEDtrueWhether to run ClickHouse commands ON CLUSTER. Set to false for single-container setups.
LANGFUSE_AUTO_CLICKHOUSE_MIGRATION_DISABLEDfalseWhether to disable automatic ClickHouse migrations.
CLICKHOUSE_READ_ONLY_URLOptional read-only endpoint used for public-API reads and selected UI/filter read queries. Falls back to CLICKHOUSE_URL when unset. Reuses CLICKHOUSE_USER, CLICKHOUSE_PASSWORD, and CLICKHOUSE_DB. Only useful on compute-compute separated clusters. See Scaling.

Langfuse uses default as the cluster name if CLICKHOUSE_CLUSTER_ENABLED is set to true. You can overwrite this by setting CLICKHOUSE_CLUSTER_NAME to a different value. In that case, the database migrations will not apply correctly as they cannot run dynamically for different clusters. You must set LANGFUSE_AUTO_CLICKHOUSE_MIGRATION_DISABLED = true and run ClickHouse migrations manually. Clone the Langfuse repository, adjust the cluster name in ./packages/shared/clickhouse/migrations/clustered/*.sql and run cd ./packages/shared && sh ./clickhouse/scripts/up.sh to manually apply the migrations.

Timezones

ClickHouse must run with its timezone set to UTC (the default). Langfuse does not support non-UTC ClickHouse timezones. Running ClickHouse with a different timezone (e.g. via the timezone server setting) will cause queries to return incorrect or empty results.

You can verify your ClickHouse timezone by running:

SELECT timezone()

This should return UTC. If it does not, update your ClickHouse server configuration to remove any custom timezone setting and restart the server.

The same requirement applies to Postgres โ€” all infrastructure components must use UTC. Please vote on this GitHub Discussion if you would like us to consider supporting other timezones.

User Permissions

The ClickHouse user specified in CLICKHOUSE_USER must have the following grants to allow Langfuse to operate correctly. Replace 'user' with your actual ClickHouse username and adjust the database name if you're using a different database than default.

Langfuse tables

Langfuse applies its ClickHouse schema migrations with the same user that it uses for reads and writes, so the user needs DDL grants in addition to SELECT and INSERT:

-- Read and write tracing data
GRANT SELECT, INSERT ON default.* TO 'user';

-- Update and delete rows: data retention, project and trace deletion, event updates
GRANT ALTER UPDATE, ALTER DELETE ON default.* TO 'user';

-- Apply schema migrations on startup
GRANT CREATE, DROP TABLE, DROP VIEW ON default.* TO 'user';
GRANT ALTER ADD COLUMN, ALTER MODIFY COLUMN, ALTER VIEW MODIFY QUERY ON default.* TO 'user';
GRANT ALTER ADD INDEX, ALTER DROP INDEX, ALTER MATERIALIZE INDEX ON default.* TO 'user';

System tables

Langfuse v4 reads a small set of ClickHouse system tables to schedule background work. Only the columns that Langfuse actually reads need to be granted:

-- Partition and part discovery: event propagation, historic backfill, deleted-mask cleaner
GRANT SELECT(database, table, name, partition, partition_id, active, rows) ON system.parts TO 'user';

-- Mutation backpressure for the deleted-mask cleaner
GRANT SELECT(database, table, is_done) ON system.mutations TO 'user';

-- Table engine detection for the historic backfill
GRANT SELECT(database, name, engine) ON system.tables TO 'user';

-- Progress tracking for long-running migration queries and v4 transition usage detection
GRANT SELECT ON system.processes TO 'user';
GRANT SELECT ON system.query_log* TO 'user';

The wildcard in system.query_log* also covers the rotated query_log_N tables that ClickHouse creates when the log table schema changes between versions.

Clustered deployments

With CLICKHOUSE_CLUSTER_ENABLED=true, Langfuse reads the system tables above through clusterAllReplicas() and runs DDL ON CLUSTER, which requires two additional grants:

-- Read system tables across all replicas through clusterAllReplicas()
GRANT READ ON REMOTE TO 'user';

-- Run ON CLUSTER queries. Required unless
-- access_control_improvements.on_cluster_queries_require_cluster_grant is
-- disabled on the server; it defaults to true.
GRANT CLUSTER ON *.* TO 'user';

Grants are local to the node they are created on, unless your cluster uses a replicated access storage backend. Create every grant on all nodes of the cluster, for example by adding ON CLUSTER:

GRANT ON CLUSTER default SELECT ON system.query_log* TO 'user';

Historic backfill scratch table

The v4 historic backfill freezes merges on its intermediate table while it copies data:

GRANT SYSTEM SYNC REPLICA, SYSTEM MERGES, ALTER SETTINGS ON default.observations_pid_tid_sorting TO 'user';

Which of the three is used depends on the table engine โ€” SYSTEM MERGES on self-managed MergeTree, ALTER SETTINGS on replicated and SharedMergeTree engines, SYSTEM SYNC REPLICA on replicated engines โ€” so granting all three keeps the backfill working on any deployment. The grants can be created before the table exists, i.e. before the backfill starts.

Lightweight updates

With CLICKHOUSE_USE_LIGHTWEIGHT_UPDATE=true, Langfuse issues native UPDATE statements instead of ALTER TABLE ... UPDATE mutations. ClickHouse rejects those unless enable_lightweight_update is enabled for the user:

CREATE SETTINGS PROFILE langfuse_lightweight_update SETTINGS enable_lightweight_update = 1 TO 'user';

Direct ClickHouse Access for Custom Tools

Self-hosted deployments give you control over the underlying ClickHouse database. You can query it directly for internal dashboards, audits, migrations, or one-off debugging.

For production integrations and custom applications, prefer the Public API, SDK query helpers, MCP server, or Blob Storage Export. These interfaces are the compatibility targets across Langfuse releases.

The ClickHouse schema is not a stable API contract. Major Langfuse upgrades, background migrations, and performance work such as Simplify Langfuse for Scale can change tables, columns, deduplication behavior, or join patterns at any time. Custom queries that read traces, observations, scores, or internal materialized views should be validated as part of every Langfuse upgrade.

If you do query ClickHouse directly:

  • Use a dedicated read-only user or a dedicated read-only compute group where available.
  • Keep direct analytical traffic away from the primary ingestion path. On ClickHouse Cloud or BYOC, use separate compute groups and configure CLICKHOUSE_READ_ONLY_URL for supported Langfuse read paths, especially Public API and filter/helper reads.
  • Always include project and time filters where possible. Langfuse tracing data is optimized around project and time access patterns including monthly partitioning.
  • Do not write directly to Langfuse tables. Use the Public API or SDKs for creating and updating Langfuse data.
  • If a missing API filter or field forces you to query ClickHouse directly, please open a GitHub issue with your use case; APIs are the preferred long-term extension point.

Custom Schema Changes

We recommend running Langfuse on the unmodified ClickHouse schema.

Langfuse's ClickHouse schema and migrations are designed, tested, and versioned as a unit with each release. Customizing the observations, events, or other table definitions moves that schema outside of what we test against โ€” which means keeping it compatible with future upgrades becomes your responsibility. We'll provide best-effort support for issues arising from custom schema changes.

If a missing column, index, or table setting makes you consider a custom schema change, please open a GitHub issue with your use case first; improvements to the standard schema benefit all deployments and are covered by our regular testing and upgrade process.

Deployment Options

This section covers different deployment options and provides example environment variables.

Cloud/BYOC (recommended)

ClickHouse Cloud is a scalable and fully managed deployment option for ClickHouse. You can provision it directly from ClickHouse or through one of the cloud provider marketplaces:

ClickHouse Cloud clusters will be provisioned outside your cloud environment and your VPC, but ClickHouse offers private links for AWS, GCP, and Azure.

If you need the operational model of ClickHouse Cloud while keeping the ClickHouse data plane in your own cloud account, consider ClickHouse BYOC. BYOC is a fully managed ClickHouse Cloud deployment on infrastructure in your cloud account and is designed for large-scale deployments with strict data residency, compliance, or VPC-boundary requirements.

We recommend ClickHouse Cloud or BYOC for larger Langfuse deployments because they provide cloud-native scaling primitives that are not available in the self-managed OSS ClickHouse setup used by Langfuse. ClickHouse Cloud and BYOC separate storage from compute through SharedMergeTree, which helps scale compute independently of stored data, reduces replica storage overhead, and avoids manual shard planning for growth. They also support compute-compute separation through warehouses, so you can isolate ingestion writes, supported Langfuse reads, analytical queries, or ad-hoc workloads on separate compute groups that share the same data but do not compete for the same CPU and memory. Langfuse can use this pattern via CLICKHOUSE_READ_ONLY_URL for public-API reads and selected UI/filter read traffic.

If you need assistance or want to talk to the ClickHouse team, you can reach out to them here.

Example Configuration

Set the following environment variables to connect to your ClickHouse instance:

CLICKHOUSE_URL=https://<identifier>.<region>.aws.clickhouse.cloud:8443
CLICKHOUSE_MIGRATION_URL=clickhouse://<identifier>.<region>.aws.clickhouse.cloud:9440
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=changeme
CLICKHOUSE_MIGRATION_SSL=true

Troubleshooting

  • 'error: driver: bad connection in line 0' during migration: If you see the previous error message during startup of your web container, ensure that the CLICKHOUSE_MIGRATION_SSL flag is set and that Langfuse Web can access your ClickHouse environment. Review the IP whitelisting if applicable and whether the instance has access to the Private Link.
  • Code: 80. DB::Exception: It's not initial query. ON CLUSTER is not allowed for Replicated database. (INCORRECT_QUERY) (on ClickHouse Cloud Azure): ClickHouse Cloud Azure does not seem to handle the ON CLUSTER and Replicated settings well. We recommend to set CLICKHOUSE_CLUSTER_ENABLED=false for now. This should not make any difference on performance or high availability.

ClickHouse Kubernetes Operator

The official ClickHouse Kubernetes Operator (GitHub) automates the deployment, configuration, and management of self-managed ClickHouse and ClickHouse Keeper clusters on Kubernetes, including upgrades, scaling, and high availability. It is the officially supported option for running self-managed ClickHouse on Kubernetes.

Follow the operator documentation to provision a cluster, then connect Langfuse to it using the environment variables described above. The same user permissions and timezone requirements apply. The Langfuse Helm chart uses the operator to deploy the bundled ClickHouse from chart version v2.0.0 onwards.

Bundled ClickHouse in the Langfuse Helm chart

The Langfuse Helm chart can deploy ClickHouse for you via clickhouse.deploy: true. From chart version v2.0.0 onwards it does so through the ClickHouse Kubernetes Operator, rendering a ClickHouseCluster and a KeeperCluster resource. The operator and cert-manager must be installed in the cluster before you install the chart; see the deployment guide.

This deployment option is community-supported. For an officially supported setup, use ClickHouse Cloud or BYOC, or manage the cluster with the operator yourself and connect Langfuse to it with clickhouse.deploy: false.

Chart v1.x deployed the bundled ClickHouse from a third-party sub-chart that cannot reach the ClickHouse version Langfuse v4 requires. If you still run chart v1.x with clickhouse.deploy: true, upgrade the chart to v2 before you upgrade Langfuse to v4.

Example Configuration

For a minimum production setup, we recommend the following values.yaml overrides:

clickhouse:
  deploy: true
  auth:
    username: default
    password: changeme # or point auth.existingSecret at a secret you manage
  cluster:
    replicas: 3
    storage:
      size: 100Gi # Start with a large volume to prevent early resizing. Alternatively, consider a blob storage-backed disk.
    resources:
      requests:
        cpu: "2"
        memory: 8Gi
      limits:
        memory: 16Gi
  keeper:
    replicas: 3
  • Shards: Shards are used for horizontally scaling ClickHouse. A single ClickHouse shard can handle multiple Terabytes of data. Today, Langfuse does not support a multi-shard cluster, and the chart always deploys a single shard. Please get in touch with us if you hit scaling limits of a single shard cluster, or consider ClickHouse Cloud/BYOC.
  • cluster.replicas: ClickHouse counts all instances towards the number of replicas, i.e. a replica count of 1 means no redundancy at all. We recommend a minimum of 3 replicas for production setups. The number of replicas cannot be increased at runtime without manual intervention or downtime.
  • cluster.resources: ClickHouse is CPU and memory intensive for analytical and highly concurrent requests. The chart defaults are sized for local experimentation; start from the minimum infrastructure requirements and scale up for larger deployments.
  • keeper.replicas: ClickHouse Keeper coordinates replication and requires an odd replica count. Use 3 for production high availability.
  • auth: The username and password Langfuse uses to connect. Overwrite these values according to your preferences, or mount them from a secret via auth.existingSecret.
  • Disk: The chart uses the default storage class unless you set cluster.storage.className. Ensure that the storage class has allowVolumeExpansion = true, as observability workloads tend to be very disk heavy. For cloud providers like AWS, GCP, and Azure this should be the default.

Langfuse assumes that certain parameters are set in the ClickHouse configurations. To perform our database migrations, the following values must be provided:

<!--
    Substitutions for parameters of replicated tables.
     Optional. If you don't use replicated tables, you could omit that.
     See https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/replication/#creating-replicated-tables
-->
<!--
    <macros>
        <shard>01</shard>
        <replica>example01-01-1</replica>
    </macros>
-->
<!--
    <default_replica_path>/clickhouse/tables/{database}/{table}</default_replica_path>
    <default_replica_name>{replica}</default_replica_name>
-->

macros and default_replica_* configuration is handled by the chart and the operator without any further configuration.

When clickhouse.deploy is true, the chart wires Langfuse to the bundled cluster automatically. For a ClickHouse you run yourself in the same cluster and namespace, set clickhouse.deploy: false and the following environment variables:

CLICKHOUSE_URL=http://<clickhouse-service>:8123
CLICKHOUSE_MIGRATION_URL=clickhouse://<clickhouse-service>:9000
CLICKHOUSE_USER=default
CLICKHOUSE_PASSWORD=changeme

Troubleshooting

  • NOT_ENOUGH_SPACE error: This error occurs when ClickHouse runs out of disk space. In Kubernetes environments, this typically means the persistent volume claims (PVCs) need to be expanded. Here's how to resolve it:

    1. Check current disk usage:

    # List the ClickHouse PVCs; their names depend on how ClickHouse was deployed
    kubectl get pvc
    
    # Check disk usage inside ClickHouse pods
    kubectl exec -it <clickhouse-pod-name> -- df -h /var/lib/clickhouse

    2. Expand the PVC (requires storage class with allowVolumeExpansion: true):

    # Edit the PVC directly
    kubectl edit pvc <clickhouse-pvc-name>
    
    # Or patch it in place; repeat for the PVC of every replica
    kubectl patch pvc <clickhouse-pvc-name> -p '{"spec":{"resources":{"requests":{"storage":"200Gi"}}}}'

    3. Monitor expansion progress:

    # Watch PVC status
    kubectl get pvc -w
    
    # Check if pods recognize the new space
    kubectl exec -it <clickhouse-pod-name> -- df -h /var/lib/clickhouse

    4. Restart StatefulSet:

    # Restart all pods individually to make use of the larger volumes
    kubectl rollout restart statefulset <clickhouse-statefulset-name>

    Prevention tips:

    • Set up monitoring alerts for disk usage (recommend alerting at 80% capacity)
    • Use storage classes with allowVolumeExpansion: true (default for most cloud providers)
    • Consider implementing automatic PVC expansion using tools like volume-autoscaler
    • For high-growth environments, consider using blob storage as disk for automatic scaling

Docker

You can run ClickHouse in a single Docker container for development purposes. As there is no redundancy, this is not recommended for production workloads.

Example Configuration

Start the container with

docker run --name clickhouse-server \
  -e CLICKHOUSE_DB=default \
  -e CLICKHOUSE_USER=clickhouse \
  -e CLICKHOUSE_PASSWORD=clickhouse \
  -d --ulimit nofile=262144:262144 \
  -p 8123:8123 \
  -p 9000:9000 \
  -p 9009:9009 \
  clickhouse/clickhouse-server

Set the following environment variables to connect to your ClickHouse instance:

CLICKHOUSE_URL=http://localhost:8123
CLICKHOUSE_MIGRATION_URL=clickhouse://localhost:9000
CLICKHOUSE_USER=clickhouse
CLICKHOUSE_PASSWORD=clickhouse
CLICKHOUSE_CLUSTER_ENABLED=false

Migrating to a New Instance

You may want to move Langfuse to a different ClickHouse instance, e.g. when switching providers or moving from a single-node to a clustered setup. We recommend the following approach:

  1. Point Langfuse to the new ClickHouse instance so that incoming data is captured there.
  2. Create a backup of the existing instance to blob storage and restore it into the new instance.

A zero-downtime switch where data is written to both instances concurrently is technically possible, but we have not tested it and it is not recommended by ClickHouse. Please reach out to Langfuse Support if you want to explore this option.

Refer to the ClickHouse migration guides for backup and restore instructions:

Encryption

ClickHouse supports disk encryption for data at rest, providing an additional layer of security for sensitive data.

Automatic Encryption with Blob Storage

When using blob storage as disk (AWS S3, Azure Blob Storage, Google Cloud Storage), data is automatically encrypted at rest using the cloud provider's default encryption:

  • AWS S3: Uses AES-256 encryption by default
  • Azure Blob Storage: Uses AES-256 encryption by default
  • Google Cloud Storage: Uses AES-256 encryption by default

Manual Disk Encryption

For local disk storage or additional encryption layers, ClickHouse supports configurable disk encryption using the AES_128_CTR algorithm.

Kubernetes Configuration

On Kubernetes, mount the following ClickHouse server configuration into /etc/clickhouse-server/config.d/:

<!-- encrypted_storage.xml -->
<clickhouse>
  <storage_configuration>
    <disks>
      <encrypted_disk>
        <type>encrypted</type>
        <disk>default</disk>
        <path>encrypted/</path>
        <algorithm>AES_128_CTR</algorithm>
        <key_hex id="0" from_env="CLICKHOUSE_ENCRYPTION_KEY"></key_hex>
      </encrypted_disk>
    </disks>
    <policies>
      <encrypted_policy>
        <volumes>
          <main>
            <disk>encrypted_disk</disk>
          </main>
        </volumes>
      </encrypted_policy>
    </policies>
  </storage_configuration>
  <merge_tree>
    <storage_policy>encrypted_policy</storage_policy>
  </merge_tree>
</clickhouse>

With the ClickHouse Kubernetes Operator, add the file to the configuration of your cluster resource. With the Langfuse Helm chart, pass the same settings via clickhouse.cluster.settings.

Provide the key to the ClickHouse pods through a CLICKHOUSE_ENCRYPTION_KEY environment variable that reads from a secret:

kubectl create secret generic clickhouse-encryption-key \
  --from-literal=key="00112233445566778899aabbccddeeff"

Blob Storage as Disk

ClickHouse supports blob storages (AWS S3, Azure Blob Storage, Google Cloud Storage) as disks. This is useful for auto-scaling storages that live outside the container orchestrator and increases availability und durability of the data. For a full overview of the feature, see the ClickHouse External Disks documentation.

Below, we give a config.xml example to use S3 and Azure Blob Storage as disks for ClickHouse Docker containers using Docker Compose. Keep in mind that metadata is still stored on local disk, i.e. you need to use a persistent volume for the ClickHouse container or risk losing access to your tables.

We recommend the following settings when using Blob Storage as a disk for your ClickHouse deployment:

  • Do not enable bucket versioning: ClickHouse will write and update many files within its merge processing. Having versioned buckets will retain the full history and quickly grow your storage consumption.
  • Do not enable lifecycle policies for deletion: Avoid deletion lifecycle policies as this may break ClickHouse's internal consistency model. Instead, delete data via the Langfuse application or using ClickHouse TTLs.
  • Enable lifecycle policies for aborted multi-part uploads: If ClickHouse attempts an upload, but aborts it before completion undesirable artifacts may remain.

This is being derived from this ClickHouse issue.

S3 Example

Create a config.xml file with the following contents in your local working directory:

<clickhouse>
    <merge_tree>
        <storage_policy>s3</storage_policy>
    </merge_tree>
    <storage_configuration>
        <disks>
            <s3>
                <type>object_storage</type>
                <object_storage_type>s3</object_storage_type>
                <metadata_type>local</metadata_type>
                <endpoint>https://s3.eu-central-1.amazonaws.com/example-bucket-name/data/</endpoint>
                <access_key_id>ACCESS_KEY</access_key_id>
                <secret_access_key>ACCESS_KEY_SECRET</secret_access_key>
            </s3>
        </disks>
        <policies>
            <s3>
                <volumes>
                    <main>
                        <disk>s3</disk>
                    </main>
                </volumes>
            </s3>
        </policies>
    </storage_configuration>
</clickhouse>

Replace the Access Key Id and Secret Access key with appropriate AWS credentials and change the bucket name within the endpoint element. Alternatively, you can replace the credentials with <use_environment_credentials>1</use_environment_credentials> to automatically retrieve AWS credentials from environment variables.

Now, you can start ClickHouse with the following Docker Compose file:

services:
  clickhouse:
    image: clickhouse/clickhouse-server
    user: "101:101"
    container_name: clickhouse
    hostname: clickhouse
    environment:
      CLICKHOUSE_DB: default
      CLICKHOUSE_USER: clickhouse
      CLICKHOUSE_PASSWORD: clickhouse
    volumes:
      - ./config.xml:/etc/clickhouse-server/config.d/s3disk.xml:ro
      - langfuse_clickhouse_data:/var/lib/clickhouse
      - langfuse_clickhouse_logs:/var/log/clickhouse-server
    ports:
      - "8123:8123"
      - "9000:9000"

volumes:
  langfuse_clickhouse_data:
    driver: local
  langfuse_clickhouse_logs:
    driver: local

Azure Blob Storage Example

Create a config.xml file with the following contents in your local working directory. The credentials below are the default Azurite credentials and considered public.

<clickhouse>
    <merge_tree>
        <storage_policy>blob_storage_disk</storage_policy>
    </merge_tree>
    <storage_configuration>
        <disks>
            <blob_storage_disk>
                <type>object_storage</type>
                <object_storage_type>azure_blob_storage</object_storage_type>
                <metadata_type>local</metadata_type>
                <storage_account_url>http://azurite:10000/devstoreaccount1</storage_account_url>
                <container_name>langfuse</container_name>
                <account_name>devstoreaccount1</account_name>
                <account_key>Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==</account_key>
            </blob_storage_disk>
        </disks>
        <policies>
            <blob_storage_disk>
                <volumes>
                    <main>
                        <disk>blob_storage_disk</disk>
                    </main>
                </volumes>
            </blob_storage_disk>
        </policies>
    </storage_configuration>
</clickhouse>

You can start ClickHouse together with an Azurite service using the following Docker Compose file:

services:
  clickhouse:
    image: clickhouse/clickhouse-server
    user: "101:101"
    container_name: clickhouse
    hostname: clickhouse
    environment:
      CLICKHOUSE_DB: default
      CLICKHOUSE_USER: clickhouse
      CLICKHOUSE_PASSWORD: clickhouse
    volumes:
      - ./config.xml:/etc/clickhouse-server/config.d/azuredisk.xml:ro
      - langfuse_clickhouse_data:/var/lib/clickhouse
      - langfuse_clickhouse_logs:/var/log/clickhouse-server
    ports:
      - "8123:8123"
      - "9000:9000"
    depends_on:
      - azurite

  azurite:
    image: mcr.microsoft.com/azure-storage/azurite
    container_name: azurite
    command: azurite-blob --blobHost 0.0.0.0
    ports:
      - "10000:10000"
    volumes:
      - langfuse_azurite_data:/data

volumes:
  langfuse_clickhouse_data:
    driver: local
  langfuse_clickhouse_logs:
    driver: local
  langfuse_azurite_data:
    driver: local

This will store ClickHouse data within the Azurite bucket.

FAQ

Is ClickHouse required for self-hosting Langfuse?

Yes, ClickHouse is currently a required component for self-hosting Langfuse. There is no alternative OLAP database supported at this time. Langfuse cannot be self-hosted without using ClickHouse as the main storage solution for traces, observations, and scores.

All self-hosted deployments must include a ClickHouse instance.

How do I manage ClickHouse storage growth?

Langfuse has a built-in Data Retention feature that automatically deletes traces, observations, scores, and media assets older than a configured number of days. This runs nightly and handles cleanup across both ClickHouse and blob storage. You do not need to set ClickHouse TTLs manually.

If ClickHouse disk usage keeps growing despite retention being configured, the cause is often system log tables (trace_log, text_log, opentelemetry_span_log, etc.) that ship without a TTL. See Scaling โ€บ ClickHouse system log tables for how to disable or cap them.

If you experience any issues when self-hosting Langfuse, please:

  1. Check out Troubleshooting & FAQ page.
  2. Use Ask AI to get instant answers to your questions.
  3. Ask the maintainers on GitHub Discussions.
  4. Create a bug report or feature request on GitHub.

Enterprise-grade support is available when self-hosting Langfuse. Learn more on our pricing page.


Was this page helpful?

Last edited