BI as code: how to version control dashboards, metrics, and semantic models
Max Musing
Max MusingFounder and CEO of Basedash · May 22, 2026

Max Musing
Max MusingFounder and CEO of Basedash · May 22, 2026

“BI as code” is the practice of defining dashboards, metrics, and semantic models in version-controlled text files instead of through point-and-click editing inside a BI tool. The point is to apply the same workflow engineers use for software (Git history, pull request review, environment promotion, automated tests) to the analytics layer, so that a metric change goes through the same scrutiny as a code change.
This guide is for analytics engineers, founders, and data leads choosing a BI stack and deciding how much of it to manage in Git. It defines what “BI as code” actually means in 2026, breaks BI into the four layers that need version control, compares how the major tools handle each layer, and gives a four-level maturity model you can map your team to. The goal is to help you pick a level that matches your team’s size and risk tolerance, not to argue that everyone needs full CI/CD for their dashboards.
The phrase gets used to mean three different things. Worth distinguishing them before going further.
Definitions as code. The metric definitions, semantic models, and SQL transformations that produce numbers live in text files. Changes to “what counts as MRR” go through a pull request. This is the most common interpretation and the one with the clearest engineering payoff.
Dashboards as code. The presentation layer (chart definitions, dashboard layouts, filters) is also defined in text. Changing a chart goes through a PR. This is much rarer and harder, because dashboards have visual state (positions, colors, sort order) that is annoying to express well in code.
Full BI as code. Definitions, dashboards, permissions, content folders, and lifecycle (dev to staging to prod promotion) all live in Git, and the BI tool is treated as a runtime that gets deployed to. Looker is the closest mainstream example. dbt + Cube + a thin viewer can get you there too.
Most teams who say “we do BI as code” mean the first one. Some teams have the second. Almost no one has the third end-to-end, and the ones who do have a dedicated platform team maintaining it.
Software has a clean abstraction: the source code is the source of truth, and the running program is built from it. Most BI tools have inverted that. The dashboard you see in the tool is the source of truth, and any “export” is a flattened representation of it.
A few specific reasons this is hard:
A modern BI tool’s Git story is largely about how cleanly it separates “definition” from “state.”
Pulling the BI stack apart helps clarify which layers you should version-control first.
The transformation layer that turns raw event tables and replicated SaaS data into clean, joinable models. This is the cleanest “as code” win in the entire stack. SQL files in Git, models built by a tool like dbt, SQLMesh, or Dataform, tests and lineage included. If you only do one thing in code, do this.
The layer that defines what revenue, active_customer, or weekly_active_user mean in business terms. Historically this lived inside the BI tool (LookML in Looker, datasets in Power BI, calculated fields in Tableau). The modern push is to move it to a standalone semantic layer (dbt’s MetricFlow, Cube, MetricQL) that any downstream tool can consume.
For a deeper take on where these definitions should live, see where to define business metrics: SQL views, dbt, semantic layers, or BI calculations.
The SQL (or generated equivalent) that powers a specific chart. Most BI tools store this inline with the chart. Some let you reference a saved query or a model from the semantic layer, which is what you want if you care about reuse. Increasingly, AI-native tools generate this on the fly, which adds a new wrinkle: do you version the prompt, the generated SQL, or both?
The presentation layer: chart definitions, layout, filters, and the dashboard object itself. This is the layer that benefits least from Git, because most of what changes is visual. It’s also the layer that most tools handle worst.
A useful rule: every layer “above” data models has diminishing returns from full version control. Most teams should be ruthless about putting layer 1 and 2 in Git and pragmatic about layer 4.
| Tool | Format | Git workflow | Diffable | Best for |
|---|---|---|---|---|
| Looker | LookML (text files) | Native Git integration | Yes | Teams that want a single source of truth across model and presentation |
| Power BI | Power BI Project (.pbip), TMDL for the model | Files designed for Git | Yes (TMDL is text) | Microsoft-shop teams with dedicated BI engineers |
| Tableau | .twb (XML) / .twbx (zipped) | Manual check-in | Partial; diffs are noisy | Visual reports where layout matters more than structure |
| dbt | YAML + SQL | Native | Yes | Warehouse modeling and metrics |
| Cube | YAML / JS data model | Native | Yes | Headless semantic layer feeding many consumers |
| Lightdash | Uses dbt models directly | Native (via dbt repo) | Yes | Teams already on dbt who want a code-first BI front end |
| Metabase | Serialization to YAML (Pro/Enterprise) | Export / import via CLI or API | Mostly yes | Open-source teams that want some Git workflow without rewriting their stack |
| Hex | Project history, optional Git sync for SQL / Python | Notebook-level versioning | Partial | Mixed SQL + notebook analytics |
| Sigma | Workbook version history, no Git sync | Tool-managed | No | Spreadsheet-style analysis where business users own the artifacts |
| Mode | Notebook + report version history | Tool-managed | Partial | Analyst-led reporting |
| ThoughtSpot | Scriptable Document Object (SDX), Git Branch | Native (per-object) | Yes | Search-driven BI with engineering ownership |
| Basedash | Skills as text (lightweight semantic layer), in-tool history for charts and dashboards | Tool-managed | Partial | AI-native teams who want metric definitions captured but don’t want to manage dashboards as code |
A few notes on the table:
git diff and understand what changed. Tableau’s XML and Power BI’s older .pbix both technically check in but produce noisy diffs..pbip with TMDL) are a significant improvement over .pbix and are now Microsoft’s recommended format for source-controlled Power BI development.Most BI version control discussions skip a step: not every team needs the same level. A useful frame is to think about four levels, each one adding more rigor and more overhead.
Anyone with edit access changes anything, in place. No history beyond the most recent state. A dashboard that worked yesterday and is broken today is debugged through Slack archaeology.
This is the default in spreadsheets and the worst-case state for any BI tool. It is unfortunately common in early-stage startups using free-tier tools.
The BI tool keeps automatic snapshots and lets you revert. There is no PR review, no branching, no environment promotion, but you can recover from accidental deletes.
Most modern BI tools (Sigma, Looker Studio, Tableau, Metabase, Power BI Service, Basedash) are at least level 1 out of the box. This is good enough for many teams under 20 people.
The BI tool can serialize objects to text. Someone occasionally exports the state and checks it into a repo, mostly for backup or audit purposes. Promotion between environments is manual.
This is where Metabase serialization, Power BI Project format used ad hoc, and most “we have a Git repo but it’s not really the source of truth” workflows sit. It gives you an audit trail without forcing change-management ceremony.
The Git repo is the canonical version of metric definitions and (sometimes) dashboards. Changes go through pull requests. CI runs lint and tests. A deploy step pushes the validated state to the BI tool.
This is the classic Looker workflow and the recommended Power BI Projects workflow. It is also what dbt + Cube + Lightdash teams converge on for the metric layer specifically.
Beyond level 3, the BI tool has multiple environments (dev, staging, prod). Branches deploy to dev workspaces. Merges to main deploy to staging. A separate promotion step pushes to prod. Lineage is tracked across the warehouse, semantic layer, and BI tool.
This is mostly an enterprise pattern. Looker + LookML projects, dbt + Cube + a strict deploy pipeline, and large internal data platforms all live here. Below roughly 30 analysts, level 4 is more overhead than it is worth.
The choice between levels is rarely a technical one. It is about who is allowed to break things and how loudly the team minds.
The right level depends mostly on team size and the cost of a wrong metric.
The mistake is going to level 3 or 4 before you’ve felt the pain of level 1. Code review on dashboards is a real cost. If you do not have an actual problem of “people accidentally broke our metrics,” skipping ahead just slows the team down.
A few patterns show up across teams that have made BI-as-code work.
revenue.yml should have a comment explaining why trial revenue is excluded. Future-you will not remember.There are real reasons to stay at level 1.
The deeper version of this point is that BI as code is a means, not an end. The actual goal is: when a number changes, can you explain why. If you can answer that without Git, you don’t need Git for it.
No. Looker was the first mainstream BI tool built around a code-first workflow, but Power BI Projects (TMDL), dbt + Cube + Lightdash, and ThoughtSpot’s SDX all support comparable Git workflows in 2026. Looker still has the deepest LookML ecosystem.
You can check in Tableau workbooks (.twb XML) and Power BI Project files (.pbip with TMDL), but diff quality varies. Power BI Projects produce reasonably readable diffs. Tableau’s XML diffs are noisy enough that most teams use Git only for backup, not for review.
Most teams in 2026 are moving definitions out of the BI tool and into either the warehouse (dbt models with metrics) or a standalone semantic layer (dbt MetricFlow, Cube). The advantage is that the same definition feeds multiple consumers (BI tool, reverse ETL, internal APIs, AI agents). See what is a semantic layer for a fuller treatment.
Partially. AI-native tools generate SQL per question, so “versioning the query” is less useful. What does fit into code is the AI’s context: metric definitions, business rules, naming conventions. Tools like Basedash expose this as Skills; ThoughtSpot calls them Worksheets; Power BI uses semantic model annotations. Treat that context as part of the semantic layer and put it through the same review as a dbt model change.
Not yet, for most startups. Get the warehouse models into dbt and into Git as soon as you have a warehouse worth modeling. Leave dashboards alone until either (a) the team is large enough that uncontrolled dashboard changes cause real fights, or (b) the dashboards are read by external customers or regulators and need an audit trail. Before that, in-tool history plus a few documented “official” metrics is usually enough.
Written by
Founder and CEO of Basedash
Max Musing is the founder and CEO of Basedash, an AI-native business intelligence platform designed to help teams explore analytics and build dashboards without writing SQL. His work focuses on applying large language models to structured data systems, improving query reliability, and building governed analytics workflows for production environments.
Basedash lets you build charts, dashboards, and reports in seconds using all your data.