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

# Environment Variables

> Complete environment variable reference for LangWatch self-hosting

LangWatch is configured through environment variables. How you set them depends on your deployment method:

* **Docker Compose**: Set in your `.env` file
* **Helm chart**: Set via `values.yaml` (the chart maps values to env vars automatically)
* **Raw Kubernetes**: Set directly in your Deployment manifests

<Tip>
  When using the Helm chart, you rarely need to set environment variables directly. The `values.yaml` file provides a structured way to configure everything. See the [Helm chart mapping table](#helm-chart-mapping) below.
</Tip>

## Core Configuration

| Variable         | Description                                                                     | Required | Default             |
| ---------------- | ------------------------------------------------------------------------------- | -------- | ------------------- |
| `DATABASE_URL`   | PostgreSQL connection string                                                    | Yes      | -                   |
| `CLICKHOUSE_URL` | ClickHouse HTTP connection string (e.g. `http://user:pass@host:8123/langwatch`) | Yes      | -                   |
| `REDIS_URL`      | Redis connection string                                                         | Yes      | -                   |
| `NODE_ENV`       | Environment (`production`, `development`)                                       | No       | `production`        |
| `BASE_HOST`      | Internal base URL for the application                                           | Yes      | -                   |
| `NEXTAUTH_URL`   | Public URL for authentication callbacks                                         | Yes      | Same as `BASE_HOST` |
| `START_WORKERS`  | Run workers in-process (`true`/`false`)                                         | No       | `false`             |

## Secrets

| Variable               | Description                                             | Required |
| ---------------------- | ------------------------------------------------------- | -------- |
| `API_TOKEN_JWT_SECRET` | JWT signing key for API tokens                          | Yes      |
| `CREDENTIALS_SECRET`   | Encryption key for stored API keys and credentials      | Yes      |
| `NEXTAUTH_SECRET`      | Session encryption key                                  | Yes      |
| `CRON_API_KEY`         | API key for authenticating internal cron job HTTP calls | Yes      |

<Warning>
  Never commit secrets to version control. In production, use a secrets manager (AWS Secrets Manager, HashiCorp Vault) or Kubernetes Secrets with `secretKeyRef` in the Helm chart.
</Warning>

## Authentication

| Variable            | Description                                                                                                                                                          | Default |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `NEXTAUTH_PROVIDER` | Auth provider: `email`, `google`, `github`, `gitlab`, `azure-ad`, `okta`, `auth0`. Anything else, or a provider whose credentials are missing, starts in email mode. | `email` |

### SSO Provider Variables

Each SSO provider requires specific variables. See [SSO Configuration](/docs/self-hosting/configuration/sso) for detailed setup guides.

**Auth0:**

| Variable              | Description                                             |
| --------------------- | ------------------------------------------------------- |
| `AUTH0_CLIENT_ID`     | Auth0 application client ID                             |
| `AUTH0_CLIENT_SECRET` | Auth0 application client secret                         |
| `AUTH0_ISSUER`        | Auth0 issuer URL (e.g. `https://your-tenant.auth0.com`) |

**Azure AD:**

| Variable                 | Description                        |
| ------------------------ | ---------------------------------- |
| `AZURE_AD_CLIENT_ID`     | Azure AD application client ID     |
| `AZURE_AD_CLIENT_SECRET` | Azure AD application client secret |
| `AZURE_AD_TENANT_ID`     | Azure AD tenant ID                 |

**GitHub:**

| Variable               | Description                    |
| ---------------------- | ------------------------------ |
| `GITHUB_CLIENT_ID`     | GitHub OAuth app client ID     |
| `GITHUB_CLIENT_SECRET` | GitHub OAuth app client secret |

**GitLab:**

| Variable               | Description                    |
| ---------------------- | ------------------------------ |
| `GITLAB_CLIENT_ID`     | GitLab OAuth app client ID     |
| `GITLAB_CLIENT_SECRET` | GitLab OAuth app client secret |

**Google:**

| Variable               | Description                |
| ---------------------- | -------------------------- |
| `GOOGLE_CLIENT_ID`     | Google OAuth client ID     |
| `GOOGLE_CLIENT_SECRET` | Google OAuth client secret |

**Okta:**

| Variable             | Description                    |
| -------------------- | ------------------------------ |
| `OKTA_CLIENT_ID`     | Okta application client ID     |
| `OKTA_CLIENT_SECRET` | Okta application client secret |
| `OKTA_ISSUER`        | Okta issuer URL                |

## Services

| Variable                | Description                  | Default                     |
| ----------------------- | ---------------------------- | --------------------------- |
| `LANGWATCH_NLP_SERVICE` | URL of the NLP service       | `http://langwatch-nlp:5561` |
| `LANGEVALS_ENDPOINT`    | URL of the LangEvals service | `http://langevals:5562`     |

## Object Storage (S3)

The dataplane S3 bucket is the general file-storage layer for all externalized byte content. Current consumers:

* **Stored objects**: externalized byte content (audio, image, video, document) extracted from incoming events and dataset uploads. Bytes are content-addressed under `{projectId}/{sha256}` and served back via `GET /api/files/:id`.
* **Dataset uploads**: persists rows uploaded through the dataset UI. Shares the same `S3_BUCKET_NAME` bucket.

When `S3_BUCKET_NAME` is set, all consumers use that bucket. When it is not set, stored-objects fall back to the local filesystem at `LANGWATCH_LOCAL_STORAGE_PATH`. That is fine for single-replica installs, **not** for horizontally-scaled deployments (see warning below).

| Variable                       | Description                                                      | Default                      |
| ------------------------------ | ---------------------------------------------------------------- | ---------------------------- |
| `S3_BUCKET_NAME`               | Dataplane bucket shared by datasets + stored-objects             | -                            |
| `S3_ENDPOINT`                  | Custom S3 endpoint (for MinIO, etc.)                             | -                            |
| `S3_ACCESS_KEY_ID`             | S3 access key ID                                                 | -                            |
| `S3_SECRET_ACCESS_KEY`         | S3 secret access key                                             | -                            |
| `S3_KEY_SALT`                  | Optional key salt for S3 object keys                             | -                            |
| `LANGWATCH_LOCAL_STORAGE_PATH` | Filesystem root used for stored-objects when no S3 is configured | `/var/lib/langwatch/objects` |

<Note>
  When running on AWS with IRSA (IAM Roles for Service Accounts), you don't need to set S3 access keys. The pod's service account assumes the IAM role automatically.
</Note>

<Warning>
  `LANGWATCH_LOCAL_STORAGE_PATH` is **single-replica only**. Multi-pod Kubernetes deployments must NOT rely on it: pods do not share a local filesystem, so a write from pod A is invisible to pod B and bytes vanish on every pod restart. Single-replica self-host installs (small footprints, hobbyist / air-gapped / pre-pilot deployments) can use it safely: the Helm chart refuses to render `localFilesystem.enabled=true` together with `replicaCount > 1` so the misconfiguration can't reach a cluster. Use `S3_BUCKET_NAME` (or the equivalent Helm `app.dataplane.enabled` toggle) for any horizontally-scaled deployment.
</Warning>

## Object Storage (Azure Blob)

Azure Blob Storage is an alternative to S3 for the same dataplane consumers (stored objects + dataset uploads). It is selected **only** by the explicit `STORED_OBJECTS_BACKEND=azure` toggle. Setting the `AZURE_BLOB_*` variables below by themselves has no effect. This is deliberate (issue #4133): deployment behavior must not depend on which env vars happen to be set, so a stray `AZURE_BLOB_ACCOUNT_KEY` left over from a decommissioned integration can never silently redirect writes.

Precedence, evaluated in this order: a per-project BYOC S3 bucket (if configured for that project) beats the azure toggle; the azure toggle beats `S3_BUCKET_NAME`; `S3_BUCKET_NAME` beats the local-filesystem fallback. This azure backend covers datasets too: the destination resolver is shared by both write paths.

| Variable                    | Description                                                                                                                                                                                       | Default                                       |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
| `STORED_OBJECTS_BACKEND`    | Explicit write-destination toggle: `azure`, or `s3` (the default when unset). `s3` selects nothing by itself. S3 is still chosen by `S3_BUCKET_NAME`, so the value only exists to say "not azure" | -                                             |
| `AZURE_BLOB_ACCOUNT_NAME`   | Azure Storage account name                                                                                                                                                                        | -                                             |
| `AZURE_BLOB_ACCOUNT_KEY`    | Azure Storage account key. Required only by `AZURE_BLOB_AUTH_MODE=sharedKey`                                                                                                                      | -                                             |
| `AZURE_BLOB_AUTH_MODE`      | How to authenticate: `sharedKey`, `workloadIdentity`, `managedIdentity`, or `azureCli`                                                                                                            | `sharedKey`                                   |
| `AZURE_BLOB_AUTHORITY_HOST` | Entra authority host. Required for sovereign clouds                                                                                                                                               | Public cloud                                  |
| `AZURE_BLOB_TOKEN_AUDIENCE` | Token audience override. Sovereign clouds only                                                                                                                                                    | `https://storage.azure.com`                   |
| `AZURE_BLOB_CONTAINER`      | Azure Blob container name                                                                                                                                                                         | -                                             |
| `AZURE_BLOB_ENDPOINT`       | Blob endpoint base URL. Optional on the Azure public cloud; required for sovereign clouds (`*.usgovcloudapi.net`, `*.chinacloudapi.cn`), private endpoints, and the Azurite emulator              | `https://{accountName}.blob.core.windows.net` |

<Warning>
  When `STORED_OBJECTS_BACKEND=azure` is set, `AZURE_BLOB_ACCOUNT_NAME` and `AZURE_BLOB_CONTAINER` are required, plus `AZURE_BLOB_ACCOUNT_KEY` when `AZURE_BLOB_AUTH_MODE` is `sharedKey` (the default). Under an identity mode the key must be absent (see below). An incomplete active Azure configuration fails loudly and never falls back to S3 or the local filesystem. Inactive Azure settings are validated only when an `azure-blob://` address is used, so they cannot break global or private-bucket S3 traffic. Set `AZURE_BLOB_ENDPOINT` (chart: `app.dataplane.providers.azureBlob.endpoint`) for sovereign clouds or private endpoints; it defaults to `https://{accountName}.blob.core.windows.net`. Per-project Azure BYOC is tracked separately (issue #6088).
</Warning>

### Migrating an existing installation

Do not switch `STORED_OBJECTS_BACKEND` before copying existing data. The migration task uses its own `OBJECT_STORAGE_MIGRATION_*` credentials, so source reads and destination writes do not depend on the app's active provider:

```bash theme={null}
pnpm run task migrateObjectStorage plan
pnpm run task migrateObjectStorage copy

# Stop all app and worker read/write traffic, drain GroupQueue, then:
OBJECT_STORAGE_MIGRATION_WRITES_PAUSED=1 \
OBJECT_STORAGE_MIGRATION_READS_PAUSED=1 \
  pnpm run task migrateObjectStorage finalize

# Switch STORED_OBJECTS_BACKEND and active credentials, then deploy while
# traffic remains paused.
pnpm run task migrateObjectStorage verify
```

`plan` is read-only. `copy` is resumable, verifies SHA-256 at the destination, and repairs a mismatched destination object. `finalize` refuses to run unless both reads and writes are explicitly paused, dataset uploads are idle, and GroupQueue has no pending, delayed, active, blocked, or staged durable references. Reads must remain paused because finalization publishes destination storage addresses before the target-provider deployment is active. It publishes newer ClickHouse stored-object rows only after the final verified copy; it does not rewrite or delete history. No phase deletes source bytes.

After `finalize` succeeds, update `STORED_OBJECTS_BACKEND` and the active provider credentials while traffic remains paused, deploy that configuration, run `verify`, then resume traffic. A global migration excludes projects with private S3 buckets; they remain on their tenant-owned S3 destination.

**Keep the source provider's read credentials configured through the rollback window.** Finalization rewrites stored-object addresses to the destination scheme, so a rollback that reverts `STORED_OBJECTS_BACKEND` *and* removes the destination provider's credentials leaves every rewritten address unreadable. The bytes still exist on both providers (no phase deletes them), but the deployment can no longer serve that scheme. Concretely:

* **S3 → Azure**: after cutover, keep `S3_BUCKET_NAME` + S3 credentials configured (Helm: `app.dataplane.legacyS3ReadBucket`) so pre-migration `s3://` history stays readable. If you roll back to S3, keep the `AZURE_BLOB_*` settings configured (Helm: `app.dataplane.legacyAzureRead: true`) so the finalized `azure-blob://` addresses stay readable.
* **Azure → S3**: the mirror image. Keep `AZURE_BLOB_*` (Helm: `legacyAzureRead`) after cutover, and keep the S3 settings if you roll back.

A rollback with the flag set is fully non-destructive: reads resolve per address scheme, and a reverse migration can later re-home the bytes. Also note: the plan reports rows addressed by a scheme outside both providers (for example `file://` from a local-storage era). Those rows are out of the migration's scope, stay on their current addresses, and remain readable as long as that scheme's backend stays configured.

| Migration variable                              | Description                                                                                               |
| ----------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `OBJECT_STORAGE_MIGRATION_SOURCE_PROVIDER`      | `s3` or `azure`                                                                                           |
| `OBJECT_STORAGE_MIGRATION_TARGET_PROVIDER`      | The other provider                                                                                        |
| `OBJECT_STORAGE_MIGRATION_WRITES_PAUSED`        | Must be `1` for `finalize`                                                                                |
| `OBJECT_STORAGE_MIGRATION_READS_PAUSED`         | Must be `1` for `finalize`                                                                                |
| `OBJECT_STORAGE_MIGRATION_S3_BUCKET`            | Global S3 source or destination bucket                                                                    |
| `OBJECT_STORAGE_MIGRATION_S3_ENDPOINT`          | Optional custom S3 endpoint                                                                               |
| `OBJECT_STORAGE_MIGRATION_S3_REGION`            | Optional S3 region. AWS uses its normal SDK region chain when omitted; custom endpoints default to `auto` |
| `OBJECT_STORAGE_MIGRATION_S3_ACCESS_KEY_ID`     | Optional explicit migration access key                                                                    |
| `OBJECT_STORAGE_MIGRATION_S3_SECRET_ACCESS_KEY` | Optional explicit migration secret key                                                                    |
| `OBJECT_STORAGE_MIGRATION_S3_SESSION_TOKEN`     | Optional temporary-session token                                                                          |
| `OBJECT_STORAGE_MIGRATION_AZURE_ACCOUNT_NAME`   | Azure source or destination account                                                                       |
| `OBJECT_STORAGE_MIGRATION_AZURE_CONTAINER`      | Azure source or destination container                                                                     |
| `OBJECT_STORAGE_MIGRATION_AZURE_ENDPOINT`       | Optional sovereign/private endpoint                                                                       |
| `OBJECT_STORAGE_MIGRATION_AZURE_AUTH_MODE`      | `sharedKey`, `workloadIdentity`, `managedIdentity`, or `azureCli`                                         |
| `OBJECT_STORAGE_MIGRATION_AZURE_ACCOUNT_KEY`    | Required only for `sharedKey`                                                                             |
| `OBJECT_STORAGE_MIGRATION_AZURE_AUTHORITY_HOST` | Optional sovereign authority host                                                                         |
| `OBJECT_STORAGE_MIGRATION_AZURE_TOKEN_AUDIENCE` | Optional sovereign token audience                                                                         |

### Authenticating without an account key

`AZURE_BLOB_AUTH_MODE` selects how the app proves who it is. It defaults to `sharedKey`, so existing installs are unaffected.

Many organisations set `allowSharedKeyAccess=false` on the storage account, frequently enforced through Azure Policy. On such an account the shared-key mode does not degrade: **every request is refused**. Use one of the identity modes instead:

| Mode               | Where it fits                       | Requires                                                                                                                                             |
| ------------------ | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sharedKey`        | Anywhere account keys are permitted | `AZURE_BLOB_ACCOUNT_KEY`                                                                                                                             |
| `workloadIdentity` | AKS. The enterprise path            | A ServiceAccount annotated with the identity's client id, and the pod label `azure.workload.identity/use: "true"`. Both are chart values (see below) |
| `managedIdentity`  | Azure VM, VMSS, App Service         | The identity assigned to the machine                                                                                                                 |
| `azureCli`         | A developer laptop                  | Being signed in with `az login`                                                                                                                      |

Whichever identity you use, grant it **Storage Blob Data Contributor** on the storage account or the specific container. The control-plane **Contributor** role does *not* grant data access. This is the single most common setup mistake, and it surfaces as a permission error rather than a sign-in error.

Three rules before you configure it:

* **There is no fallback.** If an identity mode is selected and the identity is missing or unauthorised, storage fails loudly and stays down until it is fixed. It never quietly reverts to an account key, because that would reverse your security decision at the moment you are least likely to notice.
* **An account key alongside an identity mode is rejected.** A key that would be silently ignored is worse than no key, since you would believe it was in use.
* **Bearer tokens require HTTPS.** A plaintext `AZURE_BLOB_ENDPOINT` is refused before any token is sent.

In the chart, set `app.dataplane.providers.azureBlob.authMode` and enable `global.serviceAccount` (`create: true` plus the `azure.workload.identity/client-id` annotation). The chart refuses to render `workloadIdentity` without a ServiceAccount, since the identity would have nothing to bind to. Federated Kubernetes identity is supported on **AKS only**, because the token injection depends on the Azure workload-identity webhook. On clusters without it, use `managedIdentity` or `sharedKey`.

On AKS, three things must line up or the token exchange fails with `AADSTS70021` before any storage call is made. The app surfaces that code and this remedy in the error, but they are easier to get right up front:

* The **federated identity credential's issuer** must match the cluster's OIDC issuer exactly, *including the trailing slash*. Read it with `az aks show --query oidcIssuerProfile.issuerUrl`. If the cluster is ever recreated the issuer changes and every federated credential silently stops working.
* Its **subject** must be `system:serviceaccount:<namespace>:<service-account-name>`, matched case-exactly against the ServiceAccount the chart creates.
* Its **audience** must be `api://AzureADTokenExchange`.

The pod label and the ServiceAccount annotation are both emitted by the chart; the federated credential itself is configured on the Azure side and is the piece the chart cannot do for you.

The ServiceAccount and the workload-identity label are applied to the app and the workers only. Cron pods call the app over HTTP and never touch storage themselves, so giving them a Blob-capable token would grant every cron image storage access it has no use for.

The same identity must be available to any out-of-band job that writes bytes, such as the dataset backfill task; run it with the same ServiceAccount as the app and workers.

## Email

Notification emails (alerts, invites, scheduled reports, password resets) are sent through one gateway, selected with `EMAIL_PROVIDER`.

| Variable             | Description                                                    | Default  |
| -------------------- | -------------------------------------------------------------- | -------- |
| `EMAIL_PROVIDER`     | Gateway to send through: `sendgrid`, `ses`, `smtp` or `resend` | inferred |
| `EMAIL_DEFAULT_FROM` | Default "from" address                                         | -        |

See [Email](/docs/self-hosting/configuration/email) for choosing a gateway and setting one up.

When `EMAIL_PROVIDER` is not set, the gateway is inferred from whichever credentials are present (`USE_AWS_SES` first, then `SENDGRID_API_KEY`), so existing installs keep working untouched. `smtp` and `resend` must always be named explicitly.

### SendGrid

| Variable           | Description      | Default |
| ------------------ | ---------------- | ------- |
| `SENDGRID_API_KEY` | SendGrid API key | -       |

### AWS SES

| Variable           | Description                                                        | Default                  |
| ------------------ | ------------------------------------------------------------------ | ------------------------ |
| `USE_AWS_SES`      | Set to `true` to send through SES                                  | `false`                  |
| `AWS_REGION`       | AWS region for SES                                                 | -                        |
| `AWS_SES_ENDPOINT` | Override the SES endpoint, for a VPC endpoint or an internal relay | public regional endpoint |

Credentials come from the standard AWS chain (instance role, IRSA, or `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`).

### SMTP

Use this for an internal relay, Azure Communication Services, Office 365, Google Workspace, Postmark, Mailgun, Brevo, or any other gateway that speaks SMTP.

| Variable        | Description                                                                                                | Default                               |
| --------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------- |
| `SMTP_URL`      | Full connection URL, e.g. `smtps://user:pass@relay.internal:465`. Takes precedence over the settings below | -                                     |
| `SMTP_HOST`     | Relay hostname                                                                                             | -                                     |
| `SMTP_PORT`     | Relay port                                                                                                 | `587`                                 |
| `SMTP_SECURE`   | `true` for implicit TLS, `false` for STARTTLS                                                              | `true` on port 465, otherwise `false` |
| `SMTP_USER`     | Username. Omit entirely for an unauthenticated internal relay                                              | -                                     |
| `SMTP_PASSWORD` | Password                                                                                                   | -                                     |

### Resend

| Variable         | Description    | Default |
| ---------------- | -------------- | ------- |
| `RESEND_API_KEY` | Resend API key | -       |

### Sending through an outbound proxy

Deployments whose only egress is a corporate HTTP proxy can set the standard `HTTPS_PROXY` (or `HTTP_PROXY`) and `NO_PROXY` variables. The `ses`, `resend` and `sendgrid` gateways all route their API calls through it; `NO_PROXY` entries are honoured, including leading-dot domain suffixes and `*`.

The `smtp` gateway ignores these variables on purpose, because an SMTP relay is normally an internal host that must be reached directly. Point it at your relay's real address, or use a vendor's SMTP endpoint if that is what the proxy allows out.

<Note>
  Neither the AWS SDK nor Node's HTTP client reads `HTTPS_PROXY` on its own, so LangWatch attaches the proxy to the SES and Resend clients itself. SendGrid's client is axios-based and reads the variables directly. Without this wiring, a proxied deployment fails with a `read ETIMEDOUT` reaching the provider.
</Note>

## Evaluator Providers

| Variable                          | Description                                      | Default |
| --------------------------------- | ------------------------------------------------ | ------- |
| `AZURE_OPENAI_EVALUATOR_ENABLED`  | Enable Azure OpenAI for evaluations              | `false` |
| `AZURE_OPENAI_EVALUATOR_ENDPOINT` | Azure OpenAI endpoint URL                        | -       |
| `AZURE_OPENAI_EVALUATOR_API_KEY`  | Azure OpenAI API key                             | -       |
| `GOOGLE_EVALUATOR_ENABLED`        | Enable Google AI for evaluations (PII detection) | `false` |
| `GOOGLE_CREDENTIALS_JSON`         | Google service account credentials JSON          | -       |

## Feature Flags

| Variable              | Description                                     | Default |
| --------------------- | ----------------------------------------------- | ------- |
| `SKIP_ENV_VALIDATION` | Skip environment variable validation on startup | `false` |
| `SKIP_PRISMA_MIGRATE` | Skip PostgreSQL migrations on startup           | `false` |

## Telemetry

| Variable              | Description                       | Default |
| --------------------- | --------------------------------- | ------- |
| `DISABLE_USAGE_STATS` | Disable anonymous usage analytics | `false` |
| `METRICS_API_KEY`     | API key for metrics collection    | -       |

## Langy (optional)

Langy, the automated AI engineer, runs as a separate agent pod that is off by default. Enabling it adds a `langyagent.chartManaged` toggle and a shared `LANGY_INTERNAL_SECRET` (plus optional `GITHUB_LANGY_*` and mirror-lane vars). Those are documented on their own page.

<Note>
  See [Langy environment variables](/docs/self-hosting/langy/environment-variables) for the full `LANGY_*` and `GITHUB_LANGY_*` reference, and [Setup](/docs/self-hosting/langy/setup) for the `langyagent.chartManaged` toggle and the `LANGY_INTERNAL_SECRET` secret.
</Note>

## Helm Chart Mapping

When using the Helm chart, configuration is set in `values.yaml` rather than environment variables directly. Here's how key values map:

| Helm Value                                                | Environment Variable                                                                                                                                                                                                                                             |
| --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `app.http.baseHost`                                       | `BASE_HOST`                                                                                                                                                                                                                                                      |
| `app.http.publicUrl`                                      | `NEXTAUTH_URL`                                                                                                                                                                                                                                                   |
| `app.nextAuth.provider`                                   | `NEXTAUTH_PROVIDER`                                                                                                                                                                                                                                              |
| `app.nextAuth.secret.value`                               | `NEXTAUTH_SECRET`                                                                                                                                                                                                                                                |
| `app.credentialsEncryptionKey.value`                      | `CREDENTIALS_SECRET`                                                                                                                                                                                                                                             |
| `app.cronApiKey.value`                                    | `CRON_API_KEY`                                                                                                                                                                                                                                                   |
| `app.features.skipEnvValidation`                          | `SKIP_ENV_VALIDATION`                                                                                                                                                                                                                                            |
| `app.email.provider`                                      | `EMAIL_PROVIDER`                                                                                                                                                                                                                                                 |
| `app.email.providers.sendgrid.apiKey.value`               | `SENDGRID_API_KEY`                                                                                                                                                                                                                                               |
| `app.email.providers.ses.region`                          | `AWS_REGION` (with `USE_AWS_SES=true`)                                                                                                                                                                                                                           |
| `app.email.providers.ses.endpoint`                        | `AWS_SES_ENDPOINT`                                                                                                                                                                                                                                               |
| `app.email.providers.smtp.url.value`                      | `SMTP_URL`                                                                                                                                                                                                                                                       |
| `app.email.providers.smtp.host`                           | `SMTP_HOST`                                                                                                                                                                                                                                                      |
| `app.email.providers.smtp.port`                           | `SMTP_PORT`                                                                                                                                                                                                                                                      |
| `app.email.providers.smtp.secure`                         | `SMTP_SECURE`                                                                                                                                                                                                                                                    |
| `app.email.providers.smtp.user`                           | `SMTP_USER`                                                                                                                                                                                                                                                      |
| `app.email.providers.smtp.password.value`                 | `SMTP_PASSWORD`                                                                                                                                                                                                                                                  |
| `app.email.providers.resend.apiKey.value`                 | `RESEND_API_KEY`                                                                                                                                                                                                                                                 |
| `app.evaluators.azureOpenAI.enabled`                      | `AZURE_OPENAI_EVALUATOR_ENABLED`                                                                                                                                                                                                                                 |
| `app.evaluators.azureOpenAI.endpoint.value`               | `AZURE_OPENAI_EVALUATOR_ENDPOINT`                                                                                                                                                                                                                                |
| `app.evaluators.azureOpenAI.apiKey.value`                 | `AZURE_OPENAI_EVALUATOR_API_KEY`                                                                                                                                                                                                                                 |
| `app.evaluators.google.enabled`                           | `GOOGLE_EVALUATOR_ENABLED`                                                                                                                                                                                                                                       |
| `app.evaluators.google.credentials.value`                 | `GOOGLE_CREDENTIALS_JSON`                                                                                                                                                                                                                                        |
| `app.telemetry.usage.enabled`                             | Inverse of `DISABLE_USAGE_STATS`                                                                                                                                                                                                                                 |
| `app.dataplane.enabled`                                   | `STORED_OBJECTS_BACKEND=s3` + `USE_S3_STORAGE` (provider: `awsS3`) or `STORED_OBJECTS_BACKEND=azure` (provider: `azureBlob`)                                                                                                                                     |
| `app.dataplane.bucket`                                    | `S3_BUCKET_NAME`                                                                                                                                                                                                                                                 |
| `app.dataplane.providers.azureBlob.accountName.value`     | `AZURE_BLOB_ACCOUNT_NAME`                                                                                                                                                                                                                                        |
| `app.dataplane.providers.azureBlob.accountKey.value`      | `AZURE_BLOB_ACCOUNT_KEY` (sharedKey mode only)                                                                                                                                                                                                                   |
| `app.dataplane.providers.azureBlob.authMode`              | `AZURE_BLOB_AUTH_MODE`                                                                                                                                                                                                                                           |
| `global.serviceAccount.create` / `.name` / `.annotations` | ServiceAccount the cloud identity binds to (also enables AWS IRSA)                                                                                                                                                                                               |
| `app.dataplane.providers.azureBlob.container.value`       | `AZURE_BLOB_CONTAINER`                                                                                                                                                                                                                                           |
| `app.dataplane.providers.azureBlob.endpoint.value`        | `AZURE_BLOB_ENDPOINT` (sovereign clouds, private endpoints, emulator)                                                                                                                                                                                            |
| `app.dataplane.providers.azureBlob.authorityHost.value`   | `AZURE_BLOB_AUTHORITY_HOST`. Required alongside a sovereign endpoint in a token-based mode                                                                                                                                                                       |
| `app.dataplane.providers.azureBlob.tokenAudience.value`   | `AZURE_BLOB_TOKEN_AUDIENCE`. Sovereign storage audience override                                                                                                                                                                                                 |
| `app.dataplane.legacyS3ReadBucket`                        | Keeps persisted `s3://` stored-object URIs and true legacy bucket/key consumers readable after moving writes to Azure. It does not route provider-derived dataset chunks or GroupQueue durable payloads; run the migration and drain GroupQueue before switching |
| `app.dataplane.legacyAzureRead`                           | Keeps `AZURE_BLOB_*` settings emitted after moving writes to S3 so persisted `azure-blob://` stored objects remain readable. It is not a dataset migration mechanism: dataset chunks require a verified copy before switching providers                          |
| `postgresql.external.connectionString.value`              | `DATABASE_URL`                                                                                                                                                                                                                                                   |
| `redis.external.connectionString.value`                   | `REDIS_URL`                                                                                                                                                                                                                                                      |
| `workers.enabled`                                         | Inverse of `START_WORKERS`                                                                                                                                                                                                                                       |

<Tip>
  For production, use `secretKeyRef` instead of inline values. This references a Kubernetes Secret:

  ```yaml theme={null}
  app:
    credentialsEncryptionKey:
      secretKeyRef:
        name: langwatch-secrets
        key: credentialsEncryptionKey
  ```
</Tip>
