Skip to main content
This is the single reference for how DataBrain enforces tenant isolation and metric visibility when you embed dashboards in a multi-tenant application.

Concepts, top-down

  • Workspace — outermost container. Holds Data Sources, Datamarts, Data Apps, Dashboards, Metrics. Members and permissions are Workspace-scoped. Most teams run one Workspace.
  • Data Source — connection to your warehouse. Credentials live here.
  • Datamart — logical selection of tables, columns, relationships, and joins on top of a Data Source. This is where the Client ID column for tenant isolation is set, and where the semantic layer lives.
  • Data App — the unit of embedding. Carries the API key that authenticates guest-token minting and the reference to its Datamart. One Data App per embedding surface — you do not need a Data App per tenant.
  • Client Group — a logical grouping of end-tenants that share a dashboard structure.
  • Manage Metrics — a per-dashboard toggle that lets users pick which metrics appear. See the gotcha below before relying on it.

The tenant identifier: three names, three places

NameWhereWhat it is
clientIdGuest-token JSON payloadSupplies the tenant value for the session. The only accepted spelling — client_id and tenant_id are rejected
'client_id_variable'Custom metric SQLA bare quoted token (no curly braces) substituted with the session’s tenant value at query time, e.g. WHERE client_column = 'client_id_variable'
{{DATABASE_NAME}}Custom metric SQLThe only curly-brace tenancy variable — resolves to the tenant’s database/schema for database-per-tenant setups

Tenant-isolation strategies

1. Row-per-tenant (client_id column)

All tenants share tables; every table has a tenant column. Configure the Datamart’s Client ID column mapping. How the filter is applied depends on the metric type:
  • Builder (visual/dataset) metrics: DataBrain auto-injects the tenant filter into the query. Do not add your own.
  • Custom SQL metrics: the filter is not auto-injected. You must write it yourself:
SELECT * FROM orders WHERE client_id = 'client_id_variable'
A custom SQL metric that omits the tenant filter runs unscoped and returns every tenant’s rows. Always include 'client_id_variable' in custom SQL when your Datamart uses table-level tenancy.

2. Schema- or database-per-tenant

Each tenant has its own schema/database. Reference it in metric SQL via {{DATABASE_NAME}}, which resolves from the guest token’s clientId through the Datamart mapping.

Anti-pattern: hard-coded tenant IDs

Never save a literal tenant id in metric SQL (WHERE client_id = 'acme') — for example by saving a metric while previewing as a specific client. That literal ships to every viewer and has caused real cross-tenant data leaks. If a metric must be scoped to one tenant on purpose, use RLS or an App Filter in the guest token instead.

Manage Metrics scope — the important gotcha

Manage Metrics visibility is per-dashboard, not per-viewer. If Customer A unchecks a metric on a shared dashboard, it disappears for Customer B too. That is by design — do not use Manage Metrics for per-tenant metric visibility. Use the pattern below instead.

Master + client dashboards pattern

For “each customer picks their own metric subset from a shared library”:
  1. Create one master dashboard with every metric in the library.
  2. For each customer (or Client Group), create a client dashboard derived from the master — its own layout and visible-metric subset.
  3. Embed the client dashboard per tenant with that tenant’s clientId in the guest token.
Client dashboards can be provisioned programmatically — via the Import Dashboard API or the MCP server’s create_embed tool (which can clone a templateDashboardId per client). Note that import/clone is a copy operation: later edits to the master do not propagate to already-created client dashboards.

Row-level security (RLS)

RLS (params.rlsSettings in the guest token) is an additional per-session constraint on top of tenant isolation — for example region = 'NA' for one user. It is enforced server-side and invisible to the end user. Do not use RLS as a substitute for the Datamart’s Client ID mapping.

Client selector

Embedded dashboards never render a client selector — the tenant is fixed by the guest token’s clientId. The client/database dropdown you see inside the DataBrain app is for workspace members previewing data as different clients; it is not part of the embed.

Where each setting lives

SettingWhereScope
Client ID column mappingDatamartPer Datamart
Data App API keyData AppPer Data App
Whitelist DomainsEdited from Data App settingsAccount-wide (one list for all Data Apps)
clientId, rlsSettings, appFiltersGuest token payloadPer session
Manage Metrics toggleDashboard settingsPer dashboard, shared across viewers
Client Group membershipWorkspace settingsPer tenant grouping