The full answer
Choose the isolation model by what each tenant needs, then enforce it in the platform, not in each query. For most SaaS analytics, keep shared tables with a tenant_id on every row and attach a row filter that the platform applies to every query; give large or regulated customers their own schema or catalog. Map users to tenants in one table, test the boundary continuously, and never rely on a dashboard's WHERE clause for security.
1. Three isolation models
| Model | How | Fits |
|---|---|---|
| Shared tables + row filter | One table, tenant_id column, a filter function applied at query time | Many small tenants; easiest to operate and change |
| Schema or catalog per tenant | Same tables copied per tenant, grants per schema | Large tenants, custom retention, contractual separation |
| Separate workspace or account | Fully separate platform | Strict regulation or data residency |
With 2,000 tenants, a schema each means 2,000 copies of every table and every pipeline change applied 2,000 times. A common answer is shared tables for most, with the option to move a large customer to its own catalog.
2. Enforce it in the platform
CREATE FUNCTION gov.tenant_filter(t STRING)
RETURN EXISTS (
SELECT 1 FROM gov.user_tenants u
WHERE u.user_email = current_user() AND u.tenant_id = t
) OR is_account_group_member('platform_admins');
ALTER TABLE analytics.orders SET ROW FILTER gov.tenant_filter ON (tenant_id);
- Every query, from a dashboard, a notebook or an API, gets the filter. A forgotten
WHEREcannot leak data. - Keep the function simple and fast: it runs for every query. Where a lookup is slow, give each tenant's users a group and test group membership instead.
- Across many tables, apply the same rule through attribute-based policies on tagged tables, instead of setting it table by table.
- Column masks hide sensitive columns (emails, card numbers) even inside a tenant, for users without the right role.
3. Identity and mapping
- One
user_tenantstable is the source of truth, fed from the product's account system, with an owner and an audit trail. - Service accounts for embedded dashboards act on behalf of one tenant at a time, with the tenant taken from the authenticated session, never from a URL parameter.
4. The pipelines
tenant_idis required (not null) in every silver and gold table, and checked by expectations.- Aggregates are computed per tenant. Cross-tenant tables (benchmarks, internal reporting) live in a separate schema with no customer access.
- Caches and extracts are keyed by tenant.
5. Prove it
Automated tests log in as a user of tenant A and query every exposed table, expecting zero rows from tenant B. Alert on any table without a filter or policy, and review access logs for queries returning several tenants.
What interviewers want: weighing shared, per-schema and per-account isolation, platform-enforced row filters rather than query discipline, a single user-to-tenant mapping, tenant IDs enforced through the pipelines, column masks, and continuous cross-tenant tests.
Last updated 16 October 2026