Back to blog list

Dashboards as Code for Snowflake: What Production-Ready Means

Ship native customer-facing dashboards and self-serve reporting fast with Embeddable

Learn more

Contents

Delight users with lightning-fast, fully native embedded dashboards.

Learn more

TL;DR

  • Dashboards as code means dashboard definitions live in version-controlled files, not only in drag-and-drop configuration saved to a database.
  • Customer-facing Snowflake dashboards require tenant context enforcement at the query layer, not just UI-level filters. The critical production question is where your stack enforces that tenant A cannot see tenant B's data: Snowflake row access policies, semantic layer, or embedded runtime.
  • AI agents work better with dashboards as code because structured files are diffable, reviewable, and previewable before deployment, unlike opaque GUI state.
  • Environment promotion, rollback, and auditability are production requirements that most internal BI-as-code tools were not designed to provide.

What 'Dashboards as Code' Actually Means When Snowflake Is Your Warehouse

Connecting a business intelligence tool to a Snowflake account and dragging charts into a grid is not the same thing as dashboards as code. The gap between those two workflows matters enormously once you're shipping analytics to customers.

Dashboards as code for Snowflake means defining dashboard structure, components, and data connections as version-controlled files — YAML, JSON, Markdown, SQL, or component code, depending on the tool — that live in a code repository alongside the rest of the application. Rather than configuring dashboards through a graphical interface and storing state in a proprietary database, teams write declarative definitions that can be reviewed in pull requests, promoted across environments, rolled back on failure, and iterated on by AI agents. In a Snowflake context, this approach connects those component definitions to Snowflake as the query engine, with tooling ranging from analytics engineering workflows to customer-facing embedded analytics runtimes, each with different assumptions about where tenant isolation and access control are enforced.

Lightdash, for example, has built explicit dashboards-as-code support that sits on top of dbt models — letting analytics engineers version and review dashboard state alongside the semantic layer rather than through a separate GUI (Lightdash Docs). Rill takes a similar posture for metrics views, treating the Snowflake data warehouse as a live query source for declaratively defined dashboards. Teams often try to replicate this by wiring Snowflake into a conventional BI report for non-technical business users — and that can work well until deployment, rollback, or tenant separation becomes the core problem.

That's where the definitions diverge.

Why Customer-Facing Snowflake Analytics Has Different Production Requirements

A customer opens your product's analytics view and sees a revenue chart. The numbers look right. But they're actually pulled from another tenant's Snowflake rows — not a misconfigured RLS policy, just a UI filter that got passed the wrong context token.

The failure mode is easy to imagine, and it is exactly the kind of structural risk customer-facing analytics needs to prevent.

The gap between internal BI-as-code and customer-facing embedded analytics is not about dashboard quality. It's about where tenant context is enforced. Analytics-engineering tools like Lightdash — which has genuinely strong dashboards-as-code support, including downloadable chart definitions and a well-documented Git workflow (Lightdash Docs) — are excellent for analytics engineering teams who control who sees what at the application or IdP layer. That works when your users are trusted employees. It's a different story when your users are your customers, and "tenant A must never see tenant B's data" is a contractual guarantee, not a preference.

Enforcement has to live somewhere in the stack. Snowflake's native row access policies can bind tenant filtering directly to the data layer. A semantic or query layer can inject tenant context before SQL reaches Snowflake. An embedded analytics runtime can carry and validate that context on every request. What doesn't work: a dashboard filter that can be altered in the URL, or a front-end condition that wraps a query which is otherwise unconstrained.

UI filters are not a security boundary. The enforcement question is the production-readiness question.

Which Tool Category Fits Which Production Model?

Not all dashboards-as-code tools are solving the same problem. It is more useful to think in categories than rankings — the right tool depends almost entirely on where your dashboard lives and who's reading it.

CategoryToolsGood forWatch out for
Code-first internal BILightdash, Rill, EvidenceAnalytics engineering workflows, version-controlled metrics, internal stakeholder dashboardsMay require additional architecture for product-native embedding, tenant-aware runtime enforcement, and customer-facing access/audit requirements
Data appsHex, Streamlit in SnowflakeFlexible, code-driven exploration; tight Snowflake integration for internal teamsDeployment and access control tend to be session-level, not product-runtime-level
Embedded analytics platformsEmbeddable, Luzmo, GoodDataCustomer-facing analytics embedded natively in a product; governed runtime with role-aware accessMore opinionated about the embedding layer; less suited to pure internal analytics workflows

Lightdash has explicit dashboards-as-code documentation and supports Snowflake as a first-class connector — it's a genuinely strong choice for analytics engineering teams who want version-controlled metrics surfaced to internal users. Rill is worth noting for metric views built directly on Snowflake tables via its live connector (Rill v0.85 Release Notes), with local dashboard previews available during development.

The distinction that matters for customer-facing work isn't code control — most of these tools offer that. It's whether the runtime enforces tenant context at the query layer or leaves that to the application. These tools are not equivalent: they fit different production models. For internal analytics, enforcement often relies on trusted users, BI permissions, IdP groups, or warehouse roles. For customer-facing analytics, tenant scope usually needs to be enforced in the query path, not assumed at the user interface.

What AI Agents Can Safely Generate, and What the Runtime Must Own

Here's the real AI insight for this stack: dashboards as code gives agents something structured to edit.

A file-based component definition is diffable, reviewable, and previewable before it touches production. An agent editing a .embeddable.yml file or a Lightdash dashboard YAML produces an artifact you can inspect in a pull request, test against a staging environment, and roll back with a single revert. That's qualitatively different from an agent clicking through a GUI and mutating opaque state you can't audit or version.

But we've seen teams conflate "the agent generated it" with "the agent owns it." It doesn't. Governance cannot depend only on the generated dashboard file. Tenant context enforcement, row-level security rules, access policies, and environment promotion need to be enforced by the runtime or lower layers, because those are the things a bad dashboard file can't break if the runtime enforces them independently. The artifact is the input. The runtime is the contract.

The Production-Readiness Checklist for Snowflake-Backed Customer-Facing Dashboards

We've reviewed a lot of tooling decisions in this space, and the same gaps surface repeatedly. Use these criteria against any tool you're evaluating.

  • Tenant context is enforced at the query or runtime layer, not the UI. A filter in the dashboard component is not enforcement; it's decoration. If the underlying query can run without the tenant constraint, you have a data isolation gap.
  • Row-level security is wired into Snowflake row access policies, the semantic layer, or the embedded runtime. Any one of those is acceptable; UI-only filtering is not. Snowflake's row access policies let you attach policy logic directly to tables, a strong foundation when it's feasible.
  • RBAC and application-layer access control are both present and non-redundant. Snowflake RBAC governs warehouse-level permissions; your application layer governs what each customer can see inside your product. Both need to exist; neither replaces the other.
  • Warehouse cost and performance isolation are understood. Decide whether tenants share compute, use workload-based warehouses, or require dedicated isolation for high-volume customers.
  • Environment promotion and rollback are explicit paths, not manual copy-paste. A dashboard that lives in Git but has no promotion workflow is not governed; it's just version-controlled.
  • Auditability covers who saw what, not just who logged in. Query-level audit trails matter for enterprise customers and compliance reviews.
  • The dashboard can embed natively in your product UX. An iframed BI surface with mismatched fonts and no SSO is a product quality problem that customers notice immediately.

Frequently Asked Questions

What Is Dashboards as Code in a Snowflake Context?

Dashboards as code means defining dashboard structure, components, and data connections as version-controlled files — YAML, JSON, Markdown, SQL, or component code, depending on the tool — that live in a Git repository alongside your application code, with Snowflake serving as the query engine. Rather than configuring dashboards through a GUI and storing state in a proprietary database, teams write declarative definitions that can be reviewed in pull requests, promoted across environments, and iterated on by AI agents.

How Do You Enforce Tenant Isolation in Snowflake-Backed Customer-Facing Dashboards?

Tenant isolation must be enforced at the query layer, not just filtered in the UI. Options include Snowflake row access policies bound to tenant identifiers, semantic or query layer rules in dbt or Cube, or a governed embedded analytics runtime that injects tenant context into every query before it reaches Snowflake. UI-level filters alone are not sufficient for a contractual data isolation guarantee.

What Is the Difference Between Snowflake Row Access Policies and Application-Level Row-Level Security?

When correctly applied to the relevant tables or views, Snowflake row access policies enforce filtering inside the warehouse itself, so queries using those governed objects cannot return rows outside the permitted tenant scope (Snowflake Docs). Application-level RLS applies restrictions outside Snowflake, in the analytics runtime or semantic layer, which is more flexible but means enforcement depends entirely on the application passing correct context on every request.

Can Lightdash or Rill Be Used for Customer-Facing Embedded Analytics on Snowflake?

Lightdash and Rill can both be part of Snowflake-backed analytics workflows, and each has strong code-oriented capabilities. The key question for customer-facing embedded use is not simply whether they connect to Snowflake or support code-defined assets, but where tenant context, access policy, embedding, auditability, and environment promotion are enforced in your specific architecture.

What Does Environment Promotion Mean for a Dashboards-as-Code Workflow?

Environment promotion is the process of moving a dashboard definition from a staging or development environment to production in a controlled, reviewable way. In a dashboards-as-code workflow, this means the dashboard files go through a Git-based review and approval process before they're deployed, so you have a rollback path if a broken dashboard reaches production customers.

Related Reading