Complete GuideEmbedded Analytics ArchitectureBy SumboardOctober 20, 2026

Semantic Layer for Embedded Analytics: One Definition Across Many Tenants

Run a semantic layer in a multi-tenant analytics product with one shared definition per metric, customer changes as declared extensions, and versioned definition changes that protect existing dashboards.

8 min read
Semantic Layer for Embedded Analytics: One Definition Across Many Tenants

A semantic layer gives a product one definition for each metric and builds queries from that definition. Inside a multi-tenant analytics product, running one well means three jobs at once: keep one shared definition per metric across all customers, let customers extend it without copying it, and change a definition without silently changing the numbers on dashboards customers have already built.

For an introduction, see the semantic layer glossary entry.

Why One Definition per Metric Matters More When Customers See the Number

Thoughtworks places the semantic layer in the Trial ring of its Technology Radar and describes the problem it addresses plainly: without one, "metric definitions quietly diverge". Uber built its uMetric platform because several versions of the same business metric existed across teams, and people "tend to draw different conclusions based on the version of the metric they consumed".

dbt, Databricks and Snowflake each ship shared metric definitions:

A shared definition also needs an owner. In dbt Labs' 2026 survey of 363 respondents, "ambiguous data ownership remains a challenge for 41% of respondents". Thoughtworks recommends starting with a single domain instead of an enterprise-wide rollout.

Three Ways to Give Tenants Their Own Model

Products can combine these three model arrangements:

ArrangementHow platforms implement itFits whenWhat it costs you
One shared model, tenant filter on rowsPower BI single model with row-level security; Looker access filtersEvery customer measures the same thingsCustomers share one set of metrics; in Looker, an access filter has to be added to every Explore that needs it
Shared base, per-tenant extensionsCube extends, LookML refinements, Omni shared extensions, GoodData workspace hierarchyCustomers need some measures or fields of their ownYou manage the extension mechanism and test parent changes against extensions
Separate model per tenantCube per-tenant data models; Power BI dynamic bindingA tenant's data or contract really differsSchema updates have to be run for some or all tenants

Microsoft's own guidance on the first arrangement says a single model with row-level security "can be convenient for ISVs that have relatively few customers and small to medium-sized semantic models". For separate models, Microsoft lists "updating the semantic model schema for some or all tenants" as an operation the provider has to manage. In Power BI, dynamic binding lets you connect the same report to different semantic models depending on the user's credentials, so one report can serve every tenant's model.

In Cube, context_to_app_id gives each tenant its own compiled data model, but the documentation notes that it "scopes multitenancy to data model compilation only"; query queues and caching need their own settings.

Let Customers Extend a Definition Without Copying It

Copying a metric for one customer creates two definitions of the same metric, the problem Uber described.

The extension mechanisms in the table keep the parent definition in one place:

Let tenants manage their own extensions, whether private to one tenant or shared by several. Routing every customer change through the provider makes the service too expensive to run (SIGMOD, 2009).

Decide which parts of the shared model customers may change. Microsoft's architecture guidance for multi-tenant solutions says "avoid deploying features or a configuration that only applies to a single tenant", and suggests feature flags for temporary differences. Applied to metrics, we recommend this rule: a customer can add a measure of their own, but a customer-specific version of a shared metric belongs behind a declared, named extension, not in a one-off copy.

Enforce Tenant Isolation Separately From the Definitions

A shared definition decides how a number is calculated. It does not decide whose rows it runs on, and the two controls fail separately. Cube places tenant row filters in query_rewrite, which it describes as "a security hook to check your query just before it gets processed". Looker's documentation for access filters warns: "Please do not forget to add access_filter to every Explore that needs it." An Explore without one is unfiltered. AI query agents given approved metric definitions without an access policy still exposed restricted data in a synthetic benchmark (2026 preprint). How the tenant boundary is enforced across the whole request is covered in multi-tenant analytics architecture and row-level security.

Version Metric Definitions Like an API

Treat a dashboard built on a metric like code that calls an API. Google's API design guidance gives the rule for what may change underneath such code: APIs "must not change visible behavior or semantics in ways that are likely to break reasonable user code", and even "changing the default value is considered breaking". A new formula for "active customer" changes semantics in that sense, even though nothing was renamed.

The default policy we recommend for a semantic layer:

Change to a definitionOur default
Remove or rename a metric or dimensionTreat as breaking
Change a metric's formulaTreat as breaking, unless it is a documented fix of a calculation bug
Change a default filter, time grain or currencyTreat as breaking
Change a field's typeTreat as breaking
Add a new metric or dimensionTreat as non-breaking
Add a new optional filterTreat as non-breaking

Data modeling tools provide controls for these breaking changes:

Across ten open-source database applications and more than 160,000 revisions, "80% of the schema changes happened in 20-30% of the tables", and schema changes forced significant changes in the code that used them. Put versioning effort first on the metrics that change often and that many dashboards use.

Roll a Definition Change Out Tenant by Tenant

Stripe automatically pins each account to the latest available API version when the user makes their first request. The account moves to a new version when it chooses to, and Stripe uses version change modules to keep older API versions out of core code paths.

To roll out a metric definition, use the expand, migrate and contract sequence that Danilo Sato describes as parallel change on Martin Fowler's site:

  1. Expand. Publish the new definition next to the old one, under a new version, and pin existing dashboards to the version they were built on.
  2. Migrate. Move tenants across one at a time, after checking the numbers on their dashboards under both versions. Microsoft's guidance is to "allow customers to temporarily but not permanently opt out".
  3. Contract. Set a deprecation date on the old version, warn on anything still using it, then remove it.

The same Microsoft page adds a requirement for all three steps: "You need to know which version of infrastructure, software, or feature each tenant uses." For metrics, that means a record of which definition version each tenant's dashboards resolve to.

A Checklist Before You Ship a Semantic Layer to Customers

  1. Every customer-facing metric has one definition and a named owner.
  2. Tenants extend definitions; they do not copy them. Customer-specific measures live in declared extensions that inherit the shared parent.
  3. The tenant row filter is applied on every entry point, including exports, scheduled reports and AI questions, and is tested separately from the definitions.
  4. Breaking changes are defined in writing: formula, default filter, time grain, type, removal and rename.
  5. A breaking change ships as a new version with a migration window and a deprecation date.
  6. Each tenant's version is recorded, so you can answer which customers still use the old definition.
  7. Rollout goes tenant by tenant, with a before-and-after comparison of the numbers on that tenant's dashboards.
  8. The layer's changes are checked automatically against the previous state before release.

If you are comparing vendors instead of building, the same list becomes your questions, together with what each vendor puts in writing about its own versioning policy.

Where Sumboard Stands

Sumboard already lets you set locale, timezone and language on the Organization, the Dashboard and for each Tenant at runtime, and keeps no copy of your data beyond cached results. A semantic model shared by typed and clicked questions is in progress.

If you are evaluating an embedded analytics platform, use the checklist above as your list of questions.

Where to go next

Frequently asked questions

What does a semantic layer do in embedded analytics?▾
It holds one definition for each metric, such as revenue or active users, and turns the charts, exports and questions that go through it into queries built from that definition. In an embedded product, we recommend one definition shared by every customer, with a separate access policy keeping each customer's query on their own rows.
Should each tenant get its own semantic model?▾
Usually, no. Start with one shared model and a tenant filter, add per-tenant extensions where customers need their own measures or fields, and keep fully separate models for tenants whose data or contract really differs. Separate models give you flexibility, but schema updates then have to be run for some or all tenants.
How do you let a customer customize a metric without breaking the shared definition?▾
Let the customer extend the shared definition instead of copying it. Cube extends, LookML refinements, Omni shared extensions and GoodData child workspaces all keep the parent definition in one place. In Omni and GoodData, a change to the parent reaches the extensions; a LookML refinement can override settings of the original, so test refinements when the parent changes.
When is a change to a metric definition a breaking change?▾
When it changes what an existing name returns. We recommend treating removing or renaming a field, changing a metric's formula, and changing a default filter or time grain as breaking, except a documented fix of a calculation bug, and shipping them as a new version with a migration window. We treat adding a new metric or dimension as non-breaking.