In multi-tenant analytics, a tenant filter is a convenience; row-level security is an authorization boundary. The difference appears when a user changes a URL, edits a report, drills to detail, exports data, calls an API, hits a cached result, or receives a scheduled delivery. Row-level security multi-tenant analytics must carry a trusted identity from the application to the query and enforce policy at every path that can reveal data. A hidden filter in the browser is never enough.
RLS reduces duplicated models and can simplify operations, but a policy is only as strong as its bypass paths, relationship logic, tenant keys, and tests. PostgreSQL enables per-table policies and defaults to deny when row security is enabled without an applicable policy, while superusers, roles with BYPASSRLS, and usually table owners can bypass unless explicitly constrained. Power BI documents that RLS applies differently by workspace role. These details must be part of the threat model, not footnotes after launch.
Define the tenant-isolation threat model
Inventory actors: tenant viewer, tenant administrator, internal support, analyst, content author, semantic-model developer, warehouse operator, service principal, scheduler, and platform administrator. List assets including row values, aggregate inference, object names, query text, cache entries, exports, logs, and error messages. Identify every serving path and privileged bypass. Decide whether internal administrators are trusted, audited, approval-gated, or technically prevented from reading customer data.
Choose isolation strength by risk. Shared tables with RLS can be appropriate for many tenants and centralized analytics. Separate schemas, databases, models, workspaces, or capacities can provide stronger operational boundaries for regulated or very large tenants. Physical separation does not remove application authorization, and RLS does not remove encryption or network controls. Use defense in depth where the consequence of one policy defect is high.
| Isolation model | Strength | Tradeoff | Best-fit evidence |
|---|---|---|---|
| Shared table with RLS | Central policy and efficient scale | One defect can affect many tenants | Strong policy tests and stable tenant key |
| Separate schema | Additional namespace boundary | More migrations and metadata | Moderate tenant count and custom models |
| Separate database or model | Smaller data-plane blast radius | Higher provisioning and cost | Regulatory or contractual separation |
| Separate workspace or capacity | Content and performance isolation | Operational duplication | Large or premium tenants |
| Hybrid tiers | Risk- and scale-based placement | Two operating patterns | Clear placement and migration policy |
Establish a complete tenant key
Every tenant-scoped fact and dimension needs a tenant key or a provably safe relationship to one. Use an immutable internal identifier, not a customer name, domain, or user-supplied label. Enforce non-null values and referential integrity where the platform allows it. Composite business keys should include tenant ID so an order number reused by two customers cannot collide. Shared global dimensions must be explicitly classified and contain no tenant-specific attributes.
Trace tenant scope through bridges, many-to-many relationships, slowly changing dimensions, aggregates, and precomputed extracts. A fact filtered by tenant can still expose another tenant's dimension row through a faulty relationship. Pre-aggregations must retain tenant scope unless they are proven non-sensitive global totals. Quarantine rows with missing or unknown tenant keys; assigning them to a default tenant is a direct isolation failure.
Propagate trusted identity and entitlements
Authenticate in the host application, then derive tenant, user, roles, and permitted scopes from server-side session or entitlement data. Generate an analytics token or database context on the server. Bind it to the intended audience, content, and short expiry. Ignore tenant IDs supplied by browser filters except as a requested subset that is intersected with server-authorized tenants. For users who can access several tenants, represent the allowed set explicitly and test set boundaries.
Keep identity mapping deterministic. Service principals or master identities used to access an embedded platform must not become the effective data identity for every viewer. Power BI embedded documentation distinguishes embed token identity and RLS roles; Looker uses user attributes, access filters, access grants, roles, and signed embedding context. Verify which claims are trusted, which are merely presentation filters, and which administrative identities bypass restrictions.
Place policy at the strongest practical layer
Database RLS protects queries that reach the database under a policy-aware identity or session context. Semantic-model RLS protects governed BI queries and can express business relationships. Application authorization protects content and actions. Use more than one when independent paths exist. If all warehouse queries use one unrestricted service account and tenant filtering exists only in generated SQL, a query-generation defect can cross tenants. If database policy exists but extracts copy unrestricted data into a BI model, database protection no longer covers serving.
Prefer deny by default. In PostgreSQL, enabling row security without an applicable policy yields default deny, but table owners and privileged roles require special attention. In BI platforms, restrict authoring and workspace roles because RLS may not apply to editors or administrators in the same way as viewers. Separate policy deployment rights from content authoring where feasible, review policy code, and record privileged queries.
| Leak path | Why a visual test misses it | Control | Adversarial test |
|---|---|---|---|
| Cross-tenant cache | Default user receives correct first result | Security context in cache key | Alternate tenants on same query |
| Export or schedule | Interactive chart is filtered | Server-side policy on export job | CSV and emailed attachment |
| Broken relationship | Top-level fact is filtered | Tenant-aware model joins | Drill and dimension-only query |
| Privileged author | Viewer role behaves correctly | Least privilege and audit | Member, contributor, admin personas |
| Error or metadata | No rows displayed | Sanitized diagnostics and object policy | Invalid IDs and forbidden fields |
Secure caches, exports, and background work
Cache identity must include tenant, role, policy version, user attributes when relevant, filters, semantic version, and source cutoff. Prefer physically partitioned tenant caches for high-risk data. Purge or version caches when entitlements change. Test cache warm-up jobs because a privileged preloader can create unrestricted results that later users receive. Encryption does not repair an incorrect cache key.
Scheduled reports, alerts, subscriptions, and exports run outside the interactive request and may outlive a session. Re-evaluate current entitlement at execution and delivery, not only at schedule creation. Store tenant and recipient scope, audit the resulting artifact, apply retention and classification, and revoke accessible links when access changes. Apply row limits and sensitive-field restrictions to downloads. A user permitted to view aggregates may not be permitted to export underlying records.
Build an adversarial security test matrix
Create at least two tenants with deliberately colliding business keys and distinguishable marker data. Include users with one tenant, several tenants, no tenant, changed entitlement, internal support, author, and administrator roles. Test empty and null tenant keys, bridge tables, drill-through, custom filters, direct URLs, saved views, APIs, mobile, exports, schedules, alerts, and cache order. Negative assertions should prove that forbidden markers never appear in values, counts, labels, metadata, or errors.
Run policy tests in CI for model and database changes, integration tests for token generation, and production canaries with synthetic tenant markers. Property-based tests can generate tenant and key combinations. Review query plans for policy predicates and performance because a correct policy that makes all queries unusable invites unsafe bypasses. Re-test after model relationship, role, workspace, extract, cache, or embedding changes.
Operate privileged access and incidents
Log identity, tenant scope, content, policy version, query or job ID, export, administrative action, and authorization outcome while minimizing sensitive payloads. Alert on queries without tenant context, unusual multi-tenant scope, policy bypass roles, bulk exports, and marker canary access. Conduct periodic entitlement and privileged-role reviews. Use just-in-time support access with reason, approval, expiry, and customer or compliance notice where required.
Prepare for an isolation incident. Be able to disable embedded access, revoke tokens, stop exports, purge caches, identify affected tenants and queries, preserve audit evidence, and communicate through the security process. Do not fix only the visual that exposed the problem. Trace the path from identity through model, database, cache, and artifact delivery, then add a regression test for the bypass.
Key takeaways
- Treat tenant isolation as authorization, not a default report filter.
- Use immutable tenant keys and trace them through every fact, dimension, bridge, and aggregate.
- Derive analytics identity from trusted server-side sessions and current entitlements.
- Enforce deny-by-default policy at database, semantic, and application layers as paths require.
- Include security context in caches and reauthorize exports and scheduled work.
- Test colliding tenants, bypass roles, metadata, and negative paths continuously.
Frequently asked questions
Is a dashboard tenant filter sufficient?
No. Users or tools may alter filters, call other paths, export, or receive cached results. Enforce authorized tenant scope server-side in the semantic model, database, or both, and treat visible filters only as a way to narrow already authorized data.
Does RLS apply to administrators?
It depends on the platform and role. PostgreSQL privileged roles and table owners can bypass under documented conditions, and Power BI workspace roles differ. Inventory bypass identities, minimize them, audit use, and test the exact deployed configuration.
Should every tenant have a separate database?
Not necessarily. Shared RLS can scale efficiently when risk and operations permit. Separate databases or models may be justified by regulation, contractual isolation, customization, performance, or blast radius. A hybrid tier can serve both needs.
Conclusion
Multi-tenant RLS is dependable when tenant identity is complete, trusted, and enforced through every route to data. Database and semantic policies, security-aware caching, export controls, bypass governance, and adversarial tests make isolation resilient beyond the happy-path dashboard. The standard is simple to state and demanding to prove: no tenant can learn another tenant's data, even when the user, tool, cache, or operator takes an unexpected path.