> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usedatabrain.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tenancy Model

> How DataBrain enforces tenant isolation: Workspace vs Datamart vs Data App vs Client Group, guest-token variables, Manage Metrics scope, and the master + client dashboards pattern.

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

| Name                   | Where                    | What it is                                                                                                                                             |
| ---------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `clientId`             | Guest-token JSON payload | Supplies the tenant value for the session. The only accepted spelling — `client_id` and `tenant_id` are rejected                                       |
| `'client_id_variable'` | Custom metric SQL        | A **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 SQL        | The 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:

```sql theme={"dark"}
SELECT * FROM orders WHERE client_id = 'client_id_variable'
```

<Warning>
  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.
</Warning>

### 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](/developer-docs/helpers/api-reference/import-dashboard) 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

| Setting                                 | Where                         | Scope                                     |
| --------------------------------------- | ----------------------------- | ----------------------------------------- |
| Client ID column mapping                | Datamart                      | Per Datamart                              |
| Data App API key                        | Data App                      | Per Data App                              |
| Whitelist Domains                       | Edited from Data App settings | Account-wide (one list for all Data Apps) |
| `clientId`, `rlsSettings`, `appFilters` | Guest token payload           | Per session                               |
| Manage Metrics toggle                   | Dashboard settings            | Per dashboard, shared across viewers      |
| Client Group membership                 | Workspace settings            | Per tenant grouping                       |

## Related

* [Guest Token](/developer-docs/helpers/api-reference/token)
* [Multi-Tenant Access Control](/developer-docs/multi-tenant-access-control)
* [Error Codes Reference](/developer-docs/reference/error-codes)
