Skip to main content
This is the checklist for running a production-grade, self-hosted Lightdash deployment with the official Helm chart (lightdash/helm-charts). The guide is intended for platform/devops engineers deploying their own Lightdash instance. The guide gives you 3-tiers of deployments with increasing configuration options.

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 Checklist

Tier 2: Scalable deployment

None of these steps are required but are recommended for running Lightdash beyond a PoC.

Operations

Workers and scaling

Infrastructure dependencies

Security and authentication

Tier 3: Optional features and observability

Enterprise features

Integrations (enable what you use)

Observability

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 workers
  • secrets.* — sensitive env vars, rendered into a Kubernetes Secret (or bring your own via existingSecret)
  • extraEnv / schedulerExtraEnv — raw env entries, including valueFrom.secretKeyRef
The full list of supported environment variables lives in the environment variables reference.

Core configuration

The chart’s essential first-boot values — SITE_URL and LIGHTDASH_SECRET are the two to get right before you start:
  • SITE_URL signs invite emails, OAuth redirect URIs, Slack unfurls, and delivery links — set the final https:// URL before first boot.
  • LIGHTDASH_SECRET signs session cookies and encrypts data at rest in Postgres. Set it and store it durably; losing it means losing access to encrypted data.
  • SECURE_COOKIES and TRUST_PROXY must both be "true" behind a TLS-terminating proxy, and COOKIES_MAX_AGE_HOURS sets session length — see Secure Lightdash with HTTPS.
  • Every variable is documented in the environment variables reference.
For secrets, prefer 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 calling SITE_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

Pin image.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 enable nats.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, the uuid-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 on GET /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), plus LIGHTDASH_CSP_ALLOWED_DOMAINS for any extra origins you load from.
  • CORS: leave disabled unless embedding; if embedding, LIGHTDASH_CORS_ENABLED: "true" with an explicit LIGHTDASH_CORS_ALLOWED_DOMAINS list — 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 / securityContext by default — add runAsNonRoot and drop capabilities per your Pod Security Standards baseline.
  • Soft delete for content recovery: SOFT_DELETE_ENABLED: "true" (plus SOFT_DELETE_RETENTION_DAYS, default 30).

Enterprise features

License key setup and validation is covered in enterprise license keys — the key is validated against https://api.keygen.sh on every server start, so allowlist that domain in your egress policy.

Enterprise feature flags

Enable the Enterprise features you use through configMap — 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_ENABLED with LIGHTDASH_IFRAME_EMBEDDING_DOMAINS.

AI Analyst

Set AI_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: json to your log platform; LIGHTDASH_LOG_LEVEL: audit adds 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.