Tier 1: Evaluation Deployment
Follow the self-hosting guide (or docker compose for a local spin-up) for a minimum production setup suitable for evaluating Lightdash. Prerequisites- External PostgreSQL —
postgresql.enabled: falseeven for a PoC; a small managed instance is fine, no HA or backup requirements yet - S3-compatible object storage — required regardless; Lightdash fails to start without it
- Enterprise license key if you’re evaluating Enterprise features — needs outbound access to
https://api.keygen.sh
- Deploy with the self-hosting guide
- Pin an image version - pin
image.tagto the latest version - Set
SITE_URLto your finalhttps://URL before first boot - Generate a strong
LIGHTDASH_SECRETand store it somewhere durable - losing it means losing access to encrypted data SECURE_COOKIESandTRUST_PROXYboth"true"behind your TLS-terminating load balancer- Headless browser enabled (the chart default) - image previews, PDF exports, Slack unfurls
- HTTPS end-to-end via your ingress or load balancer
- AI Analyst — model provider key +
pgvectorin Postgres
Tier 2: Scalable deployment
None of these steps are required but are recommended for running Lightdash beyond a PoC.Operations
- Choose upgrade strategy — pinned image tag, at least monthly cadence
Workers and scaling
- Data apps — sandboxes runtime, apps bucket, and a separate preview origin
- Dedicated workers -
scheduler.enabled: trueto enable scalable scheduled deliveries - NATS + warehouse workers -
nats.enabled: trueandwarehouseNatsWorker.enabled: truefor handling large volumes of warehouse queries - ≥ 2 backend replicas with pod anti-affinity and a pod disruption budget
- Size resource requests
Infrastructure dependencies
- Postgres HA, backups and point-in-time recovery on the external database from Tier 1, plus the
pgvectorextension if you use Enterprise AI features - Bucket strategy and lifecycle rules - a dedicated bucket per purpose, with a 1-day lifecycle delete on the results bucket
- SMTP email
- Email deliverability - transactional provider, SPF/DKIM on the sender domain
- Load balancer settings - timeout ≥ 300s, health check on
/api/v1/health, request body limit ≥LIGHTDASH_MAX_PAYLOAD
Security and authentication
- SSO (Okta / Azure AD / Google / generic OIDC) with password authentication disabled
- Account linking and personal access token policy
- CSP enforcement and explicit CORS
Tier 3: Optional features and observability
Enterprise features
- Pre-aggregations — pre-aggregate NATS workers + a dedicated S3 bucket
- SCIM provisioning from your IdP
- Results caching, embedding, service accounts, custom roles
Integrations (enable what you use)
- Slack — scheduled deliveries, unfurls, AI agents in Slack
- GitHub or GitLab — dbt repo write-back
- Google Sheets sync
Observability
- Prometheus metrics enabled, and scraped on every pod
- Structured JSON logging shipped to your log platform
- Alerts on HTTP error rate/latency, queue depth, and Postgres pool saturation
Architecture: what you’re deploying
The chart wires up environment variables for you in three buckets:
configMap.*— non-sensitive env vars, applied to backend and all workerssecrets.*— sensitive env vars, rendered into a Kubernetes Secret (or bring your own viaexistingSecret)extraEnv/schedulerExtraEnv— raw env entries, includingvalueFrom.secretKeyRef
Core configuration
The chart’s essential first-boot values —SITE_URL and LIGHTDASH_SECRET are the two to get right before you start:
SITE_URLsigns invite emails, OAuth redirect URIs, Slack unfurls, and delivery links — set the finalhttps://URL before first boot.LIGHTDASH_SECRETsigns session cookies and encrypts data at rest in Postgres. Set it and store it durably; losing it means losing access to encrypted data.SECURE_COOKIESandTRUST_PROXYmust both be"true"behind a TLS-terminating proxy, andCOOKIES_MAX_AGE_HOURSsets session length — see Secure Lightdash with HTTPS.- Every variable is documented in the environment variables reference.
existingSecret populated by External Secrets Operator or a CSI driver so credentials stay out of Helm values and git.
Headless browser
Enabled by default in the chart — keep it on, and tune the browserless timeouts and memory guards for large dashboards. The browser renders dashboards by callingSITE_URL, so it must reach that URL from inside the cluster (use INTERNAL_LIGHTDASH_HOST if it can’t). See Headless browser for the container and backend variables, and Resource recommendations for sizing.
Upgrades and operations
Pinimage.tag, upgrade at least monthly, rehearse each upgrade in a UAT instance that mirrors production, and enable the migration job for multi-replica deployments. Full versioning policy, upgrade mechanics, the migration job, and rollback are in Upgrading Lightdash.
Scheduler worker
Run a dedicated scheduler worker so a heavy dashboard export can’t starve the API — see Scheduler worker. For async warehouse queries, see the NATS workers overview and warehouse workers, including the critical rule: never enablenats.enabled without warehouseNatsWorker.enabled.
Sizing and availability
Size per-component resource requests and run 2+ backend replicas with pod anti-affinity and a pod disruption budget — the full component table and availability settings are in Resource recommendations.PostgreSQL
Run external managed Postgres with high availability, backups, theuuid-ossp and pgvector extensions, and a connection budget — setup and production guidance are in Configure Lightdash to use an external database.
Object storage
Use a dedicated bucket per purpose with lifecycle rules, blocked public access, and scoped credentials — setup and the full bucket strategy are in Configure Lightdash to use external object storage.Email deliverability
Env vars are in the SMTP reference. Best practice on top:- Use a transactional provider (SES, Postmark, SendGrid) — Lightdash Cloud sends through Postmark.
- Set up SPF/DKIM for the sender domain so scheduled deliveries don’t land in spam.
Load balancer and networking
HTTPS end-to-end, a load-balancer timeout ≥ 300s, a health check onGET /api/v1/health, and a request body limit ≥ LIGHTDASH_MAX_PAYLOAD — covered in Secure Lightdash with HTTPS.
Authentication policy
Enterprise deployments should be SSO-only, with password authentication disabled and account linking enabled — per-provider setup is in use SSO login for self-hosted Lightdash. Also set a personal access token policy (PAT_ALLOWED_ORG_ROLES, PAT_MAX_EXPIRATION_TIME_IN_DAYS, or DISABLE_PAT), and keep ALLOW_MULTIPLE_ORGS: "false" (default) for a single-company instance.
Security hardening
- CSP enforcement:
LIGHTDASH_CSP_REPORT_ONLY: "false"(default is report-only; enforce in production), plusLIGHTDASH_CSP_ALLOWED_DOMAINSfor any extra origins you load from. - CORS: leave disabled unless embedding; if embedding,
LIGHTDASH_CORS_ENABLED: "true"with an explicitLIGHTDASH_CORS_ALLOWED_DOMAINSlist — never*. - Egress policy: Lightdash needs your warehouse, S3, SMTP,
api.keygen.sh(license), your IdP, and any AI provider endpoints — everything else can be blocked. - NetworkPolicies: the chart only ships one for NATS (keep
nats.networkPolicy.enabled: true, the default); add your own default-deny + allow rules for backend ↔ postgres/browserless/S3 if your cluster uses them. - Pod security: the chart sets no
podSecurityContext/securityContextby default — addrunAsNonRootand drop capabilities per your Pod Security Standards baseline. - Soft delete for content recovery:
SOFT_DELETE_ENABLED: "true"(plusSOFT_DELETE_RETENTION_DAYS, default 30).
Enterprise features
License key setup and validation is covered in enterprise license keys — the key is validated againsthttps://api.keygen.sh on every server start, so allowlist that domain in your egress policy.
Enterprise feature flags
Enable the Enterprise features you use throughconfigMap — each is documented in the environment variables reference:
- Caching:
RESULTS_CACHE_ENABLED,AUTOCOMPLETE_CACHE_ENABLED,CACHE_STALE_TIME_SECONDS. - Governance:
SERVICE_ACCOUNT_ENABLED,CUSTOM_ROLES_ENABLED. - Embedding:
EMBEDDING_ENABLEDwithLIGHTDASH_IFRAME_EMBEDDING_DOMAINS.
AI Analyst
SetAI_COPILOT_ENABLED: "true", choose AI_DEFAULT_PROVIDER (openai, azure, anthropic, openrouter, or bedrock) with the matching API key, and AI_EMBEDDING_ENABLED: "true" for verified answers (requires pgvector). Provider variables, LLM-gateway routing, and guardrails such as AI_COPILOT_MAX_QUERY_LIMIT and AI_COPILOT_ALLOWED_PROJECT_UUID are in the environment variables reference. For the MCP endpoint, see Configure MCP for Lightdash.
Data apps
Serve app previews from a separate domain (APP_RUNTIME_PREVIEW_ORIGIN) so untrusted app content never shares an origin with your Lightdash session cookies, and use a persistent apps bucket with no delete lifecycle. Sandbox providers and their security model are in sandboxes; configuration in self-hosting data apps.
Observability
Enable Prometheus metrics and structured JSON logging on every pod, and scrape them from your monitoring stack:- Metrics and alerting guidance: Prometheus metrics. Scrape port 9090 on all pods labelled
app.kubernetes.io/name=lightdash(the chart ships no ServiceMonitor/PodMonitoring — create one; Lightdash Cloud scrapes at a 30s interval). If you run NATS, its Prometheus exporter is on port 7777 (nats.promExporter.enabled: true). - Log configuration: Configure logging. Ship
LIGHTDASH_LOG_FORMAT: jsonto your log platform;LIGHTDASH_LOG_LEVEL: auditadds an audit trail of user actions. - Alert on HTTP p95/error rate (
http_server_request_duration_seconds), queue depth / scheduler job failures, Postgres pool saturation, and event-loop lag.