This page is for engineering teams self-hosting their own Lightdash instance.
Warehouse workers
Process interactive and background warehouse queries on dedicated pods.
Pre-aggregate workers
Materialize pre-aggregates and serve queries from DuckDB.
Requirements
- Helm chart version 2.7.2 or later
- Lightdash version 0.2675.0 or later. Older images will fail with
MODULE_NOT_FOUND.
Upgrading the Helm chart alone does not change how Lightdash works. NATS features are entirely opt-in — your existing deployment will behave exactly the same until you explicitly enable the new Helm values described below.
Architecture
The Lightdash API publishes jobs to NATS JetStream. Worker pods consume messages from their stream and process them concurrently (default 100 concurrent jobs per pod).Enabling NATS
nats.enabled is set to true. This deploys a NATS StatefulSet and sets NATS_ENABLED=true on the backend, which means the backend will start routing queries through NATS. You should always enable at least a warehouse worker alongside NATS to process those queries — otherwise queries will be enqueued with no worker to pick them up.
Auto-configured environment variables
The chart automatically sets these environment variables in the shared ConfigMap — you do not need to set them manually:| Variable | Set when | Value |
|---|---|---|
NATS_ENABLED | nats.enabled: true | "true" |
NATS_URL | nats.enabled: true | nats://<release>-nats:4222 |
NATS JetStream configuration
JetStream supports two storage backends — we recommend memory store, but you can use file store depending on your needs.Memory store vs file store
| Memory store (recommended) | File store | |
|---|---|---|
| How it works | Messages are held in RAM | Messages are persisted to disk |
| Performance | Faster — no disk I/O overhead | Slower — writes go through disk |
| Persistence | Messages are lost if NATS restarts | Messages survive NATS restarts |
| Infrastructure | No PersistentVolumeClaim needed | Requires a PersistentVolumeClaim |
| When to use | Most deployments. Lightdash messages are small (just a query UUID) and are deleted once processed. | High message volume exceeding available RAM, or if you need messages to survive NATS pod restarts. |
Configuration reference
| Setting | Recommended | Description |
|---|---|---|
nats.config.jetstream.memoryStore.enabled | true | Enable memory-backed storage |
nats.config.jetstream.memoryStore.maxSize | 1Gi | Maximum memory for JetStream message storage |
nats.config.jetstream.fileStore.enabled | false | Enable disk-backed storage |
nats.config.cluster.enabled | false | Single-node NATS (no clustering) |
Pod disruption
NATS is a stateful component — if the NATS pod restarts, in-flight messages are lost (queries will be retried by users). The chart protects against unplanned eviction with:cluster-autoscaler.kubernetes.io/safe-to-evict: "false"annotationPodDisruptionBudgetwithmaxUnavailable: 0