Skip to main content
This page is for self-hosted Lightdash. Lightdash Cloud is fully managed by Lightdash and has a different data-processing profile.

Summary

  • Warehouse credentials, dbt or Lightdash YAML definitions, generated SQL, query results, dashboard and chart definitions, and underlying warehouse data are processed inside your deployment. None of these are sent to Lightdash through product telemetry.
  • Product telemetry is enabled by default and points at Lightdash’s RudderStack endpoint (https://analytics.lightdash.com) using a built-in write key. It can be disabled with a single environment variable, or redirected to your own RudderStack instance.
  • Enterprise Edition validates its license key against Keygen on every server start. The request contains the license key only — no warehouse credentials, no query text, no business data. See License validation request for the exact payload.
  • Optional integrations (SSO, SMTP, Slack, GitHub, object storage, AI providers, MCP, sandbox providers, Sentry, and the organization roadmap) talk directly to the endpoints you configure. They are not proxied through Lightdash Cloud.
Everything below is grounded in the current Lightdash source code and applies to a standard self-hosted deployment on the official Helm chart or Docker Compose.

Three telemetry configurations

Telemetry means the RudderStack event stream emitted by the Lightdash backend and browser. The three supported configurations map to three environment-variable combinations.

Configuration 1: default Lightdash telemetry

If you set none of the RUDDERSTACK_* variables, Lightdash uses a built-in write key and its own RudderStack endpoint:
  • Endpoint: https://analytics.lightdash.com
  • Write key: built into the release
  • Enabled by default: yes, on every fresh install
  • Applies to: the backend, the scheduler, and the browser (the frontend loads its RudderStack config from the backend’s /api/v1/health response)
If you do nothing, telemetry is on and points at Lightdash.

Configuration 2: disable outbound RudderStack telemetry

Set one variable on every Lightdash container:
When this is true the backend clears both the write key and the data plane URL, no matter what RUDDERSTACK_WRITE_KEY or RUDDERSTACK_DATA_PLANE_URL are set to. That means:
  • The backend LightdashAnalytics.track(), identify(), and group() calls short-circuit and send nothing.
  • The /api/v1/health response returns an empty rudder block, so the browser skips rudder-sdk-js initialization and emits no client-side events.
  • RUDDERSTACK_ANALYTICS_DISABLED=true takes precedence over RUDDERSTACK_WRITE_KEY and RUDDERSTACK_DATA_PLANE_URL.
Set the variable on every process that runs Lightdash code:
  • The backend container (lightdash-headless / lightdash)
  • The scheduler container (scheduler.enabled: true)
  • Any NATS worker containers (warehouseNatsWorker, preAggregateWorker)
Disabling RudderStack telemetry does not change product functionality. Nothing in the query, dashboard, AI, or admin surface depends on it. Prometheus metrics, in-product Usage Analytics dashboards, audit logs, query tags in your warehouse, and the optional usage event stream all keep working — they are independent systems (see Related systems).

Configuration 3: send telemetry to your own RudderStack

Point Lightdash at a RudderStack source you control:
  • The backend uses these values in place of the built-in ones.
  • The browser reads them from /api/v1/health and initializes rudder-sdk-js against your endpoint.
  • Events go to your RudderStack destination instead of Lightdash’s. Lightdash never sees them.
  • If RUDDERSTACK_ANALYTICS_DISABLED=true is also set, disable wins — no events are sent anywhere.
This is a redirection of the same event stream — it is not the same thing as audit logs, Prometheus metrics, warehouse query tags, or the in-product Usage Analytics dashboards. Those systems are independent (see Related systems).

Telemetry payload

The backend emits RudderStack events through LightdashAnalytics.track(). Every event carries a common context.app block and the event’s own properties.

Common context on every event

All telemetry events carry the following installation context: The user identifier is either the Lightdash userId (a UUID), the anonymous ID (00000000-0000-0000-0000-000000000000) when the user has enabled tracking anonymization, or the constant string "embed" for embedded viewers.

Event categories

Telemetry is not fully anonymous. Events carry stable identifiers (organizationId, projectId, userId, chart/dashboard/space UUIDs) and, for some events, human-readable resource metadata: chart and dashboard titles and descriptions, scheduler names, warehouse type, dbt connection type, and short errorMessage strings from server-side failures. Do not assume every event is anonymous.

User-level tracking anonymization

Users can toggle Anonymize my usage data in their profile. When on:
  • The is_tracking_anonymized: true flag is set on the user record and included in identify/update events.
  • The user.updated, user.verified, and user.deleted events drop email, firstName, and lastName.
  • The userId and resource identifiers (organizationId, projectId, chart/dashboard UUIDs) are still sent — anonymization operates at the user-name/email level, not at the identifier level.
This is a user-scoped setting. It does not disable telemetry, and it does not scrub identifiers or resource metadata from non-user events. To stop telemetry leaving the deployment, use RUDDERSTACK_ANALYTICS_DISABLED=true.

Not sent through RudderStack telemetry

Verified against the current backend source. RudderStack telemetry never contains:
  • Warehouse credentials or authentication secrets. Connection strings, keys, and tokens live in LIGHTDASH_SECRET-encrypted rows in Postgres and are never included in event payloads.
  • dbt project files or complete semantic-layer definitions. Warehouse type and dbtConnectionType are included; the manifest, .yml model files, and metric definitions are not.
  • Generated SQL or SQL Runner query text. Query events carry an ID, structural counts, timings, and warehouse type — never the SQL string.
  • Query results, row values, or warehouse records. Query events carry totalRowCount and columnsCount — never row data.
  • Complete dashboard or chart definitions. Create/update events carry structural counts (metrics, dimensions, filters, series types), the chart type, and the chart or dashboard title and description. They do not carry the full config JSON, tile layout, or filter values.
  • AI prompt text, conversation text, or model responses. ai.usage events carry token counts, provider, model, feature, and IDs (aiAgentId, threadId, promptId, organizationId, projectId). They do not carry prompt or completion text.
  • Integration credentials or application secrets. OAuth tokens, Slack bot tokens, GitHub app credentials, SMTP passwords, LIGHTDASH_LICENSE_KEY, LIGHTDASH_SECRET, and AI-provider API keys are never sent.
Exceptions and potentially sensitive metadata that is sent:
  • Chart, dashboard, space, and scheduler titles and descriptions on create/update events.
  • Explore name (exploreName) and virtual view ID on query events.
  • User email, first name, last name on user identify/update events — unless the user has enabled tracking anonymization.
  • Short server-side error messages on error events (typed exception messages, not stack traces of user data).
  • Stable UUIDs for organizations, projects, users, charts, dashboards, spaces, schedulers, queries, and AI agents.

Enterprise license validation

Enterprise Edition (LIGHTDASH_LICENSE_KEY set) validates the license against Keygen at server start and periodically thereafter.

License validation request

  • Endpoint: POST https://api.keygen.sh/v1/accounts/1ae7d3a8-4665-44e4-989d-9de54c84761a/licenses/actions/validate-key
  • Timing: on server start and roughly once every 24 hours from the process cache
  • Initiator: the Lightdash backend and any process that instantiates LicenseClient (backend, scheduler, workers)
  • Request headers: Content-Type: application/json, Accept: application/json
  • Request body:
  • Response: validity, human-readable detail, and a status code. No code or configuration is pulled during validation.
The request contains the license key only. It does not contain warehouse credentials, dbt project data, query text, query results, chart or dashboard definitions, or any organization business data. Keygen is the only Lightdash-operated external service required for Enterprise features. If you also enable the optional organization roadmap, the backend additionally calls https://roadmap.lightdash.com — see the egress matrix below. For full license setup steps and troubleshooting, see Enterprise features and licensing. These systems are commonly conflated with RudderStack telemetry. They are independent, and each continues to work when RUDDERSTACK_ANALYTICS_DISABLED=true.

Egress matrix

Every default and optional outbound destination from a self-hosted Lightdash deployment. “Required” means the deployment fails without the destination for the feature it enables; “Optional” means the destination is only reached when the feature is turned on.
Community Edition (no LIGHTDASH_LICENSE_KEY) does not call api.keygen.sh or roadmap.lightdash.com. Every other row is identical.

Security-review checklist

1

Disable Lightdash-hosted telemetry (optional)

Set RUDDERSTACK_ANALYTICS_DISABLED=true on every Lightdash container (backend, scheduler, NATS workers). See Configuration 2.
2

Or, redirect telemetry to your own RudderStack

Set RUDDERSTACK_WRITE_KEY and RUDDERSTACK_DATA_PLANE_URL on every Lightdash container. Confirm the browser picks up the new endpoint by inspecting GET /api/v1/health — the rudder block should show your write key and data plane URL. See Configuration 3.
3

Allow-list the domains you actually need

  • api.keygen.sh — Enterprise Edition only, required.
  • roadmap.lightdash.com — only if you enable the organization roadmap.
  • analytics.lightdash.com — only if you leave default telemetry on.
  • Your warehouse endpoint, S3 endpoint, IdP, SMTP host, AI provider endpoints, Slack, GitHub, and sandbox provider endpoints — whichever features you use.
Everything else can be blocked. See the production deployment checklist for a starting egress policy.
4

Keep optional integrations internal

  • AI providers: point ANTHROPIC_BASE_URL, OPENAI_BASE_URL, or BEDROCK_BASE_URL at an internal LLM gateway.
  • Sandboxes: set SANDBOX_PROVIDER=aws-lambda-microvms or azure-container-apps to keep sandbox execution inside your cloud account.
  • Sentry: leave SENTRY_BE_DSN and SENTRY_FE_DSN unset, or point them at your own Sentry instance.
  • GitHub: connect a GHES or self-hosted GitLab instead of GitHub.com.
  • MCP: register only internal MCP endpoints.
  • Google Sheets, Slack, dbt Cloud: leave disabled.
5

Verify the effective configuration

  • GET /api/v1/health returns the effective rudder and sentry config the frontend will use.
  • Backend startup logs record whether Sentry initialized and whether license validation succeeded.
  • Run a network capture or eBPF/Cilium egress log against the backend, scheduler, and worker pods to confirm the observed destinations match the allow-list.
  • Query the Instance health page in Lightdash for the running configuration snapshot.

Further reading