---
title: "S3 / Blob Storage Configuration (Self-Hosted)"
sidebarTitle: Blob Storage (S3)
description: "Configure S3 or S3-compatible blob storage for self-hosted Langfuse. Store raw events, multi-modal inputs, and batch exports with AWS S3, MinIO, or compatible services."
label: "Version: v4"
---

# S3 / Blob Storage

This is a deep dive into the configuration of S3. Follow one of the [deployment guides](/self-hosting#deployment-options) to get started.

Langfuse uses S3 or another S3-compatible blob storage (referred to as S3 going forward) to store raw events, multi-modal inputs, batch exports, and other files.
In addition, we have dedicated implementations for [Azure Blob Storage](#azure-blob-storage), [Google Cloud Storage](#google-cloud-storage), and [OCI Object Storage](#oci-object-storage).
You can use a managed service on AWS, or CloudFlare, or host it yourself using MinIO.
We use it as a scalable and durable storage solution for large files with strong read-after-write guarantees.
This guide covers how to configure S3 within Langfuse and how to connect your own S3-compatible storage.

## Official and Community Support [#support]

Langfuse works with a wide range of blob storage providers.
We distinguish between officially supported and community-supported options:

| Option                                            | Support Level |
| ------------------------------------------------- | ------------- |
| [Amazon S3](#amazon-s3)                           | Official      |
| [Google Cloud Storage](#google-cloud-storage)     | Official      |
| [Azure Blob Storage](#azure-blob-storage)         | Official      |
| [MinIO / AIStor](#minio)                          | Official      |
| [Cloudflare R2](#cloudflare-r2)                   | Official      |
| [OCI Object Storage](#oci-object-storage)         | Community     |
| [Tigris](#tigris)                                 | Community     |
| [Other S3-compatible providers](#other-providers) | Community     |

For Google Cloud Storage, we recommend the [native integration](#google-cloud-storage); the [S3 interoperability mode](#google-cloud-storage-compatibility-mode) has known limitations.

- **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](/issues) — pull requests that fix or improve support for community-supported options are highly welcome.

## Configuration

Langfuse has multiple use-cases for S3 and allows you to configure them individually.
That way, you can use separate buckets for each case, or combine information in a single bucket using prefixes.

### Mandatory Configuration

Langfuse needs an S3 bucket to upload raw event information.
The following environment variables are mandatory for every deployment.
They need to be provided for the Langfuse Web and Langfuse Worker containers.

| Variable                                     | Required / Default | Description                                                                                                           |
| -------------------------------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `LANGFUSE_S3_EVENT_UPLOAD_BUCKET`            | Required           | Name of the bucket in which event information should be uploaded.                                                     |
| `LANGFUSE_S3_EVENT_UPLOAD_PREFIX`            | `""`               | Prefix to store events within a subpath of the bucket. Defaults to the bucket root. If provided, must end with a `/`. |
| `LANGFUSE_S3_EVENT_UPLOAD_REGION`            |                    | Region in which the bucket resides.                                                                                   |
| `LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT`          |                    | Endpoint to use to upload events.                                                                                     |
| `LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID`     |                    | Access key for the bucket. Must have List, Get, and Put permissions.                                                  |
| `LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY` |                    | Secret access key for the bucket.                                                                                     |
| `LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE`  |                    | Whether to force path style on requests. Required for MinIO.                                                          |

### Optional Configuration

Langfuse also uses S3 for batch exports, multi-modal tracing, and multi-modal datasets.
Those use-cases are opt-in and can be configured separately.
Use the following information to enable them.
Langfuse uses the credentials to generate short-lived, pre-signed URLs that allow SDKs to upload media assets or to download batch exports.

#### Multi-Modal Tracing and Datasets

| Variable                                        | Required / Default | Description                                                                                                          |
| ----------------------------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------- |
| `LANGFUSE_S3_MEDIA_UPLOAD_BUCKET`               | Required           | Name of the bucket in which media files should be uploaded.                                                          |
| `LANGFUSE_S3_MEDIA_UPLOAD_PREFIX`               | `""`               | Prefix to store media within a subpath of the bucket. Defaults to the bucket root. If provided, must end with a `/`. |
| `LANGFUSE_S3_MEDIA_UPLOAD_REGION`               |                    | Region in which the bucket resides.                                                                                  |
| `LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT`             |                    | Browser- and SDK-reachable endpoint used to upload and download media files.                                         |
| `LANGFUSE_S3_MEDIA_UPLOAD_INTERNAL_ENDPOINT`    |                    | Optional endpoint that the Langfuse server can use to read media from object storage.                                |
| `LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID`        |                    | Access key for the bucket. Must have List, Get, and Put permissions.                                                 |
| `LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY`    |                    | Secret access key for the bucket.                                                                                    |
| `LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE`     |                    | Whether to force path style on requests. Required for MinIO.                                                         |
| `LANGFUSE_S3_MEDIA_MAX_CONTENT_LENGTH`          | `1_000_000_000`    | Maximum file size in bytes that is allowed for upload. Default is 1GB.                                               |
| `LANGFUSE_S3_MEDIA_DOWNLOAD_URL_EXPIRY_SECONDS` | `3600`             | Presigned download URL expiry in seconds. Defaults to 1h.                                                            |

#### Batch Exports

Langfuse allows you to export table data via batch exports.
We upload intermediate results to S3 and provide a presigned URL for users to download their exports in CSV or JSON format.
To configure batch exports in your environment, configure the following environment variables:

| Variable                                     | Required / Default | Description                                                                                                                                                                        |
| -------------------------------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `LANGFUSE_S3_BATCH_EXPORT_ENABLED`           | `false`            | Whether to enable Langfuse S3 batch exports. This must be set to `true` to enable batch exports.                                                                                   |
| `LANGFUSE_S3_BATCH_EXPORT_BUCKET`            | Required           | Name of the bucket in which batch exports should be uploaded.                                                                                                                      |
| `LANGFUSE_S3_BATCH_EXPORT_PREFIX`            | `""`               | Prefix to store batch exports within a subpath of the bucket. Defaults to the bucket root. If provided, must end with a `/`.                                                       |
| `LANGFUSE_S3_BATCH_EXPORT_REGION`            |                    | Region in which the bucket resides.                                                                                                                                                |
| `LANGFUSE_S3_BATCH_EXPORT_ENDPOINT`          |                    | Endpoint to use to upload batch exports.                                                                                                                                           |
| `LANGFUSE_S3_BATCH_EXPORT_ACCESS_KEY_ID`     |                    | Access key for the bucket. Must have List, Get, and Put permissions.                                                                                                               |
| `LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY` |                    | Secret access key for the bucket.                                                                                                                                                  |
| `LANGFUSE_S3_BATCH_EXPORT_FORCE_PATH_STYLE`  |                    | Whether to force path style on requests. Required for MinIO.                                                                                                                       |
| `LANGFUSE_S3_BATCH_EXPORT_EXTERNAL_ENDPOINT` |                    | Optional external endpoint for generating presigned URLs. If not provided, the main endpoint is used. Useful, if langfuse traffic to the blobstorage should remain within the VPC. |
| `BATCH_EXPORT_PAGE_SIZE`                     | `500`              | Optional page size for streaming exports to S3 to avoid memory issues. The page size can be adjusted if needed to optimize performance.                                            |
| `BATCH_EXPORT_ROW_LIMIT`                     | `1_500_000`        | Maximum amount of rows that can be exported in a single batch export.                                                                                                              |

#### S3 Compatibility

The following settings apply to all S3 use-cases (events, media, batch exports) and help with S3-compatible stores that are not fully compatible with the AWS S3 API.

| Variable                                        | Required / Default | Description                                                                                                                                                                                                                                                                          |
| ----------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `LANGFUSE_S3_DELETE_OBJECTS_CHECKSUM_ALGORITHM` |                    | Checksum algorithm for S3 DeleteObjects requests: `MD5`, `CRC32`, `CRC32C`, `CRC64NVME`, `SHA1`, or `SHA256`. If unset, the AWS SDK default (`CRC32`) is used. Set to `MD5` if your storage provider rejects deletions with a `MissingContentMD5` error (e.g. older MinIO versions). |

## Multi-modal LLM-as-a-Judge [#multi-modal-llm-as-a-judge]

Self-hosted Langfuse sends media used by [LLM-as-a-Judge evaluators](/docs/evaluation/evaluation-methods/llm-as-a-judge#multi-modal-evaluation) inline by default. Each attachment is limited to 20 MB by default.

Set `LANGFUSE_EVALUATOR_MEDIA_TRANSPORT` on both the web and worker containers to change this behavior:

- `inline`: The Langfuse worker downloads each attachment from object storage and sends its bytes with the model request. This is the default for self-hosted deployments.
- `url`: The Langfuse worker creates a short-lived signed URL without downloading the attachment. The model provider downloads the attachment and must be able to reach `LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT`.
- `disabled`: Leave Langfuse media references as text instead of sending attachments.

Use `LANGFUSE_EVALUATOR_MEDIA_INLINE_MAX_BYTES` to change the per-attachment inline size limit in bytes. See the [environment variable reference](/self-hosting/configuration#llm-as-a-judge-media) for details.

## Deployment Options

This section covers different deployment options and provides example environment variables.
We will focus on the EVENT_UPLOAD case, as the other cases are similar.

### Amazon S3 [#amazon-s3]

[Amazon S3](https://aws.amazon.com/s3/) is a globally available object storage.
Langfuse uses the AWS SDK internally to connect to blob storages, as most providers provide an S3-compatible interface.

If Langfuse is running on an AWS instance, we recommend to use an IAM role on the Langfuse container to access S3.
Otherwise, create an IAM user and generate an Access Key pair for Langfuse.
Ensure that both entities have the necessary permissions to access the bucket:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": ["s3:PutObject", "s3:ListBucket", "s3:GetObject"],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::<my-bucket-name>/*",
        "arn:aws:s3:::<my-bucket-name>"
      ],
      "Sid": "EventBucketAccess"
    }
  ]
}
```

The same IAM role or user also works for the project-level [Blob Storage Export integration](/docs/api-and-data-platform/features/export-to-blob-storage#set-up-an-export). On self-hosted deployments, leave **Access Key ID** and **Secret Access Key** blank in that integration's AWS S3 settings to use the IAM role instead of static credentials. This fallback only applies to the AWS S3 provider; it is not available on Langfuse Cloud or for Azure Blob Storage / S3 Compatible Storage.

To use the [Data Retention](/docs/data-retention) feature in a self-hosted environment, you need to grant `s3:DeleteObject` to the Langfuse IAM role on all buckets.
Note that Langfuse only issues delete statements on the API.
If you use versioned buckets, delete markers and non-current versions need to be removed manually or with a lifecycle rule.

#### Using AWS KMS Encryption [#using-aws-kms-encryption]

Amazon S3 provides server-side encryption (SSE) options to encrypt your data at rest.
Langfuse supports AWS KMS encryption for all S3 interactions through the following environment variables:

| Variable                                  | Required / Default | Description                                                                                                         |
| ----------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `LANGFUSE_S3_EVENT_UPLOAD_SSE`            |                    | Server-side encryption algorithm to use. Set to `aws:kms` to use AWS KMS or `AES256` to use server-side encryption. |
| `LANGFUSE_S3_EVENT_UPLOAD_SSE_KMS_KEY_ID` |                    | ID of the KMS key to use for encryption. Required when `LANGFUSE_S3_EVENT_UPLOAD_SSE` is set to `aws:kms`.          |
| `LANGFUSE_S3_MEDIA_UPLOAD_SSE`            |                    | Server-side encryption algorithm to use. Set to `aws:kms` to use AWS KMS or `AES256` to use server-side encryption. |
| `LANGFUSE_S3_MEDIA_UPLOAD_SSE_KMS_KEY_ID` |                    | ID of the KMS key to use for encryption. Required when `LANGFUSE_S3_MEDIA_UPLOAD_SSE` is set to `aws:kms`.          |
| `LANGFUSE_S3_BATCH_EXPORT_SSE`            |                    | Server-side encryption algorithm to use. Set to `aws:kms` to use AWS KMS or `AES256` to use server-side encryption. |
| `LANGFUSE_S3_BATCH_EXPORT_SSE_KMS_KEY_ID` |                    | ID of the KMS key to use for encryption. Required when `LANGFUSE_S3_BATCH_EXPORT_SSE` is set to `aws:kms`.          |

When using AWS KMS for encryption, ensure your IAM role or user has the necessary permissions to use the specified KMS key:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": ["kms:GenerateDataKey", "kms:Decrypt"],
      "Effect": "Allow",
      "Resource": "arn:aws:kms:region:account-id:key/key-id",
      "Sid": "AllowUseOfKMSKey"
    }
  ]
}
```

#### Example Configuration

Set the following environment variables if you authenticate using an IAM role:

```yaml
LANGFUSE_S3_EVENT_UPLOAD_BUCKET=my-bucket-name
```

If you authenticate using an Access Key pair:

```yaml
LANGFUSE_S3_EVENT_UPLOAD_BUCKET=my-bucket-name
LANGFUSE_S3_EVENT_UPLOAD_REGION=my-bucket-region
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
```

### MinIO / AIStor [#minio]

[MinIO](https://min.io/) and its commercial distribution [AIStor](https://www.min.io/product/aistor) are object storage servers that are compatible with the S3 API.
They are a popular choice for on-premise deployments and local development.
Langfuse uses MinIO for local development and as a default in our [Docker Compose](/self-hosting/deployment/docker-compose) deployment option. The [Kubernetes (Helm)](/self-hosting/deployment/kubernetes-helm) chart bundled MinIO up to chart version `v1.x` and bundles SeaweedFS from chart `v2.0.0` onwards.

#### Example Configuration

Start a local MinIO container with Docker using:

```bash
docker run --name minio \
  -p 9000:9000 \
  -p 9001:9001 \
  -e MINIO_ROOT_USER=minio \
  -e MINIO_ROOT_PASSWORD=miniosecret \
  minio/minio server /data --console-address ":9001"
```

Navigate to `http://localhost:9001` to access the MinIO console and create a bucket named `langfuse`.
Now, you can start Langfuse using the following environment variables:

```yaml
LANGFUSE_S3_EVENT_UPLOAD_BUCKET=langfuse
LANGFUSE_S3_EVENT_UPLOAD_REGION=us-east-1
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID=minio
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=miniosecret
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT=http://minio:9000
LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE=true
LANGFUSE_S3_EVENT_UPLOAD_PREFIX=events/
```

This example setup uses an ephemeral volume, i.e. on restarts MinIO will discard all event data.
Please follow the MinIO documentation or use a cloud provider managed blob store for persistent data storage.

MinIO versions before `RELEASE.2025-02-03` reject S3 DeleteObjects requests with a `MissingContentMD5` error, which breaks data retention and deletion jobs.
If you cannot upgrade MinIO, set `LANGFUSE_S3_DELETE_OBJECTS_CHECKSUM_ALGORITHM=MD5` to send the legacy `Content-MD5` header instead.

#### Configuring Minio for Media Uploads [#minio-media-uploads]

To enable multi-modal tracing and multi-modal datasets, presigned URLs allow SDK clients and browsers outside the Docker network to directly upload and download media assets. Therefore, the `LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT` must resolve to the Docker host's address.

**Development Environment:** When running `docker compose` locally, set `LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT` to `http://localhost:9090` to ensure presigned URLs correctly loop back to the local instance.

**Production Environment:** In a production environment, configure `LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT` with a publicly accessible hostname or IP address that is reachable by your SDK clients and browsers.

If the Langfuse web and worker containers cannot reach this public endpoint, set `LANGFUSE_S3_MEDIA_UPLOAD_INTERNAL_ENDPOINT` to a server-reachable object storage address. The default Docker Compose setup uses `http://minio:9000` internally while clients use `http://localhost:9090`.

### Cloudflare R2 [#cloudflare-r2]

[Cloudflare R2](https://www.cloudflare.com/developer-platform/products/r2/) is globally available, S3 compatible object storage by Cloudflare.
Create a new bucket within the Cloudflare UI and generate an Access Key pair.
Ensure that the Access Key pair has the necessary permissions to access the bucket.

#### Example Configuration

Set the following environment variables to connect Langfuse with your Cloudflare R2 bucket:

```yaml
LANGFUSE_S3_EVENT_UPLOAD_BUCKET=my-bucket-name
LANGFUSE_S3_EVENT_UPLOAD_REGION=auto
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID=<access-key-id>
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=<secret-access-key>
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT=https://${ACCOUNT_ID}.r2.cloudflarestorage.com
```

### Azure Blob Storage [#azure-blob-storage]

[Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs/) is a globally available object storage by Microsoft Azure.
It does not offer an S3-compatible API and requires slightly different configurations.
To use our dedicated Azure Blob Storage setup, follow the configuration steps below.

#### Example Configuration

You will need an Azure Blob Storage container and a static account key with the necessary permissions.

Set the following environment variables to connect Langfuse with your Azure Blob Storage container.
This example uses sample credentials from [Azurite](https://github.com/Azure/Azurite).

```yaml
# Special flag to enable the Azure Blob Storage interface
LANGFUSE_USE_AZURE_BLOB=true

LANGFUSE_S3_EVENT_UPLOAD_BUCKET=langfuse # Container name - If it does not exists, Langfuse will attempt to create it
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID=devstoreaccount1 # ABS Account
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw== # ABS Account Key
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT=http://localhost:10000/devstoreaccount1 # URL, e.g. `https://${account}.blob.core.windows.net`
```

### Google Cloud Storage (Native) [#google-cloud-storage]

[Google Cloud Storage](https://cloud.google.com/storage) is a globally available object storage by Google Cloud.
To configure the native Google Cloud Storage integration, create a new bucket within Google Cloud Storage.
Configure the following settings to use the bucket with Langfuse.

#### Example Configuration

Set the following environment variables to connect Langfuse with your Google Cloud Storage bucket:

```yaml
LANGFUSE_USE_GOOGLE_CLOUD_STORAGE=true

LANGFUSE_S3_EVENT_UPLOAD_BUCKET=langfuse # Bucket name
LANGFUSE_GOOGLE_CLOUD_STORAGE_CREDENTIALS=<json-credentials OR path-to-credentials.json> # JSON key or path to JSON key file. Optional. Will fallback to environment credentials
LANGFUSE_S3_EVENT_UPLOAD_PREFIX=events/ # Optional prefix to store events within a subpath of the bucket
GOOGLE_CLOUD_UNIVERSE_DOMAIN=googleapis.com # Optional. Google Cloud universe domain. Defaults to `googleapis.com`
```

By default, the native integration connects to the public Google Cloud universe (`googleapis.com`).
To target a sovereign or private Google Cloud universe (for example, a Google Distributed Cloud or government deployment), set `GOOGLE_CLOUD_UNIVERSE_DOMAIN` to your universe's domain.
The value applies across all authentication methods (JSON credentials, key file, and environment credentials).

### Google Cloud Storage (Compatibility Mode) [#google-cloud-storage-compatibility-mode]

[Google Cloud Storage](https://cloud.google.com/storage) is a globally available object storage by Google Cloud.
It offers S3-compatibility through its interoperability interface.
To get started, create a new bucket within Google Cloud Storage.
Navigate to `Settings > Interoperability` to create a service account HMAC key.
Ensure that the HMAC key has the necessary permissions to access the bucket.

Please note that GCS does not implement all functions of the S3 API.
We are aware of issues around DeleteObject requests that may cause errors in your application.
This will have no effect on most operations within Langfuse, but may limit your ability to delete data.

#### Example Configuration

Set the following environment variables to connect Langfuse with your Google Cloud Storage bucket:

```yaml
LANGFUSE_S3_EVENT_UPLOAD_BUCKET=my-bucket-name
LANGFUSE_S3_EVENT_UPLOAD_REGION=auto
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID=<HMAC Access Key>
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=<HMAC Secret Key>
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT=https://storage.googleapis.com
LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE=true
LANGFUSE_S3_EVENT_UPLOAD_PREFIX=events/
```

### OCI Object Storage (Native) [#oci-object-storage]

[OCI Object Storage](https://www.oracle.com/cloud/storage/object-storage/) is a globally available object storage by Oracle Cloud Infrastructure.
Langfuse provides a native OCI Object Storage integration using the OCI SDK, which supports multiple IAM authentication methods suitable for different deployment environments.

To enable the native OCI integration, set `LANGFUSE_USE_OCI_NATIVE_OBJECT_STORAGE=true` and choose an authentication method via `LANGFUSE_OCI_AUTH_TYPE`.

| Variable                                 | Required / Default | Description                                                                                                                     |
| ---------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `LANGFUSE_USE_OCI_NATIVE_OBJECT_STORAGE` | `false`            | Set to `true` to enable the native OCI Object Storage integration.                                                              |
| `LANGFUSE_OCI_AUTH_TYPE`                 | Required           | Authentication method. One of: `workload_identity`, `instance_principal`, `resource_principal`, `oci_profile`, `session_token`. |
| `LANGFUSE_OCI_CONFIG_FILE`               |                    | Path to the OCI config file. Required for `oci_profile` and `session_token` auth types.                                         |
| `LANGFUSE_OCI_CONFIG_PROFILE`            |                    | OCI config profile name. Used with `oci_profile` and `session_token` auth types.                                                |

The standard `LANGFUSE_S3_*` environment variables (bucket, region, endpoint, prefix, force path style) are reused for OCI Object Storage. Do not set `*_ACCESS_KEY_ID` / `*_SECRET_ACCESS_KEY` when using the native OCI auth methods.

#### Authentication Methods

| Auth Type            | Use Case                                                                                                |
| -------------------- | ------------------------------------------------------------------------------------------------------- |
| `instance_principal` | Running on OCI Compute with IAM dynamic group policies. Recommended for production on OCI.              |
| `workload_identity`  | Running on OKE (Oracle Kubernetes Engine) with OCI Workload Identity configured.                        |
| `resource_principal` | Running inside an OCI managed service or runtime that injects Resource Principal environment variables. |
| `oci_profile`        | Local development using an OCI config file with a named profile.                                        |
| `session_token`      | Short-lived user authentication via `oci session authenticate`. Suited for interactive/dev use.         |

#### Example Configuration (Instance Principal)

For production deployments on OCI Compute with IAM dynamic group policies:

```yaml
LANGFUSE_USE_OCI_NATIVE_OBJECT_STORAGE=true
LANGFUSE_OCI_AUTH_TYPE=instance_principal

LANGFUSE_S3_EVENT_UPLOAD_BUCKET=langfuse-bucket
LANGFUSE_S3_EVENT_UPLOAD_REGION=us-chicago-1
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT=https://objectstorage.us-chicago-1.oraclecloud.com
LANGFUSE_S3_EVENT_UPLOAD_PREFIX=events/
```

### Tigris [#tigris]

[Tigris](https://www.tigrisdata.com/) is S3-compatible object storage with zero egress fees and a free tier (5 GB).
Create a bucket and access key pair from the [Tigris Dashboard](https://console.tigris.dev/).
Access keys are prefixed with `tid_` and secrets with `tsec_`.

#### Example Configuration

Set the following environment variables to connect Langfuse with your Tigris bucket:

```yaml
LANGFUSE_S3_EVENT_UPLOAD_BUCKET=langfuse
LANGFUSE_S3_EVENT_UPLOAD_REGION=auto
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID=tid_YOUR_ACCESS_KEY
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=tsec_YOUR_SECRET_KEY
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT=https://t3.storage.dev
```

Tigris uses virtual-hosted-style addressing by default. Do not set `LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE` to `true`.

### Other Providers [#other-providers]

Langfuse supports any S3-compatible storage provider.
Please refer to the provider's documentation on how to create a bucket and generate Access Key pairs.
Ensure that the Access Key pair has the necessary permissions to access the bucket.
If you believe that other providers should be documented here, please open an [issue](https://github.com/langfuse/langfuse-docs/issues)
or a [pull request](https://github.com/langfuse/langfuse-docs/pulls) to contribute to this documentation.

## Bucket Lifecycle Policies

Langfuse uploads raw event data to the event upload bucket on every ingestion request.
Over time, this data accumulates and increases storage costs.
It is recommended to configure a bucket lifecycle (expiration) policy to automatically delete objects after a defined number of days.

Langfuse re-reads raw events from the bucket to retry failed ingestion jobs, for replay/disaster recovery, and — on the legacy `/api/public/ingestion` path — to combine incremental events sent for the same record. Size your lifecycle expiration to cover these needs (30 days on Langfuse Cloud). OpenTelemetry ingestion is self-contained (each span is a single complete event), so it does not depend on this retention for assembling records.

This retention window is not a way to update data. Traces and observations are immutable once ingested; see [How to update traces, observations, and scores?](/faq/all/tracing-data-updates) for details.

Configure a lifecycle expiration rule for your storage provider:

- **Amazon S3** — Create an S3 Lifecycle expiration rule that deletes objects after N days. See [Managing the lifecycle of objects](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html).
- **MinIO** — Use `mc ilm rule add --expire-days` to set an expiration rule. See [mc ilm rule add](https://min.io/docs/minio/linux/reference/minio-mc/mc-ilm-rule-add.html).
- **Cloudflare R2** — Configure object lifecycle expiration rules via the R2 dashboard or API. See [Object lifecycles](https://developers.cloudflare.com/r2/buckets/object-lifecycles/).
- **Tigris** — Configure object lifecycle expiration rules via the Tigris Dashboard or AWS CLI. See [Object Lifecycle](https://www.tigrisdata.com/docs/objects/object-lifecycle/).
- **Azure Blob Storage** — Create a lifecycle management policy with a delete action. See [Configure a lifecycle management policy](https://learn.microsoft.com/en-us/azure/storage/blobs/lifecycle-management-policy-configure).
- **Google Cloud Storage** — Use Object Lifecycle Management with a Delete action and an age condition. See [Object Lifecycle Management](https://cloud.google.com/storage/docs/lifecycle).
- **OCI Object Storage** — Create a lifecycle policy rule with an object age-based delete action. See [Using Object Lifecycle Management](https://docs.oracle.com/en-us/iaas/Content/Object/Tasks/usinglifecyclepolicies.htm).

<Callout type="info">

Langfuse tracks uploaded event files in a ClickHouse table called `blob_storage_file_log`.
If you have configured a bucket lifecycle policy, it can be helpful to also set a matching TTL on this table to keep it small and speed up processing.

```sql
ALTER TABLE blob_storage_file_log MODIFY TTL created_at + INTERVAL <DAYS> DAY DELETE;
```

Where `<DAYS>` matches the configured bucket lifecycle expiration period.

</Callout>

## Endpoint validation (SSRF defense) [#endpoint-validation]

In addition to the platform-level `LANGFUSE_S3_*` buckets configured via environment variables, project members can configure a blob storage **integration** in the Langfuse UI (Project Settings → Integrations → Blob Storage Export). Because that endpoint is user-supplied, Langfuse validates the host it points at — both when the integration is saved and again every time a connection is opened — to prevent the worker from being pointed at internal services (cloud metadata endpoints, link-local addresses, private RFC1918 / ULA ranges, NAT64/6to4 transition ranges) or being redirected there via DNS rebinding.

Validation behavior:

- **Save-time**: the endpoint hostname is resolved and rejected if any resolved IP falls into a private, link-local, loopback, or special-use range.
- **Connection-time**: the S3 SDK's HTTP handler and the Azure SDK's request policy re-validate the resolved IP just before each request, so a hostname whose DNS answer changes after save is still blocked.
- **Cloud**: validation is strict and cannot be relaxed.
- **Self-hosted**: validation activates when at least one of the allowlist environment variables below is configured. This keeps backward compatibility with internal MinIO and Azurite deployments on private networks. The default will become strict in a future major release.
- The _integration_ offers three providers: **AWS S3**, **S3 Compatible Storage**, and **Azure Blob Storage**. There is no native **GCS** or **OCI** client, so neither can be selected directly. Google Cloud Storage still works as an export target through **S3 Compatible Storage**: create an HMAC key as described under [Compatibility Mode](#google-cloud-storage-compatibility-mode), then set the endpoint to `https://storage.googleapis.com`. That host is validated like any other S3-compatible endpoint. The native object storage integrations configured via environment variables are unaffected.

### Self-hosted allowlist environment variables

Set these on both the Langfuse Web and Worker containers if your internal blob storage endpoint resolves to a private address.

| Variable                                                 | Required / Default | Description                                                                                                            |
| -------------------------------------------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| `LANGFUSE_BLOB_STORAGE_ENDPOINT_WHITELISTED_HOST`        |                    | Comma-separated list of hostnames that bypass the IP-range check. Example: `minio.internal,storage.svc.cluster.local`. |
| `LANGFUSE_BLOB_STORAGE_ENDPOINT_WHITELISTED_IPS`         |                    | Comma-separated list of individual IPs to allow. Example: `10.0.0.5,fd00::1`.                                          |
| `LANGFUSE_BLOB_STORAGE_ENDPOINT_WHITELISTED_IP_SEGMENTS` |                    | Comma-separated list of CIDR ranges to allow. Example: `10.0.0.0/8,192.168.0.0/16`.                                    |

These mirror the existing `LANGFUSE_LLM_CONNECTION_WHITELISTED_*` variables used for user-configured LLM connections — see [Hardening → Outbound URL allowlists](/self-hosting/configuration/hardening#outbound-url-allowlists).

Azure container names must be 3–63 characters and contain only lowercase letters, digits, and hyphens. Names that don't meet this constraint are rejected at submission time.

---

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

1. Check out [Troubleshooting & FAQ](/self-hosting/troubleshooting-and-faq) page.
2. Use [Ask AI](/ask-ai) to get instant answers to your questions.
3. Ask the maintainers on [GitHub Discussions](/gh-support).
4. Create a bug report or feature request on [GitHub](/issues).

  Enterprise-grade support is available when self-hosting Langfuse. Learn more on
  our [pricing page](/pricing-self-host).

<!-- agent-instructions -->

---

## Agent Instructions

This page is part of the [Langfuse](https://langfuse.com) documentation, published as plain Markdown for AI agents. Every page is available as Markdown by appending `.md` to its URL, or by sending an `Accept: text/markdown` header. This page: `https://langfuse.com/self-hosting/deployment/infrastructure/blobstorage.md`.

### Querying these docs

If the answer is not on this page, query the documentation instead of guessing:

- **Semantic search** across all Langfuse docs, returning an answer with the relevant pages and excerpts. Ask a specific, self-contained question:

  ```bash
  curl -sG "https://langfuse.com/api/search-docs" --data-urlencode "query=How do I trace a LangGraph agent?"
  ```

- **Index of every page**: <https://langfuse.com/llms.txt>, with per-section indexes [llms-docs.txt](https://langfuse.com/llms-docs.txt), [llms-integrations.txt](https://langfuse.com/llms-integrations.txt), and [llms-self-hosting.txt](https://langfuse.com/llms-self-hosting.txt).

### Before writing Langfuse code

- **Install the [Langfuse Agent Skill](https://langfuse.com/docs/api-and-data-platform/features/agent-skill).** It encodes Langfuse's own best practices for instrumentation, prompt management, and evaluation, and materially improves results.
- **Read [What does a good trace look like?](https://langfuse.com/docs/observability/best-practices.md)** before instrumenting an application.
- **Verify endpoints, parameters, and response fields** against the [API reference](https://api.reference.langfuse.com) instead of inferring them from code examples.
- **Use the [Langfuse CLI](https://langfuse.com/docs/api-and-data-platform/features/cli)** (`npx langfuse-cli api <resource> <action>`) to read or write traces, prompts, datasets, and scores from the terminal.

Found an error in these docs? Please open an issue at <https://github.com/langfuse/langfuse-docs/issues>.
