Row-level security (RLS) restricts which rows of data each user can see, enforcing access control at the data level rather than the dashboard level. This guide explains how row-level security works in Tableau, Power BI, and data warehouses, and the design patterns that make it maintainable at scale.
Row-level security (RLS) is a data access control mechanism that restricts which rows of data each user can see, based on the user's identity or role. Rather than building separate dashboards for different audiences or filtering at the application layer, RLS enforces access control at the data level — the user can only query and visualize the records they are authorized to see.
RLS is a foundational governance capability for organizations where the same analytical environment serves users with different data access entitlements: regional managers who should only see their region's data, account managers who should only see their assigned accounts, or HR business partners who should only see their business unit's headcount data.
How Row-Level Security Works
At its core, RLS works by adding a filter to every query a user executes against a secured dataset. The filter is derived from the user's identity — their username, their group membership, their role — and is applied automatically, without the user being able to override it.
The implementation varies by platform:
**In the data warehouse (Snowflake, BigQuery, Redshift):** Row access policies or row-level security policies are defined at the table level. When a query hits a secured table, the warehouse automatically applies the appropriate filter based on the querying user or role. This is the most robust implementation — it is enforced at the source, regardless of which tool or query is used to access the data.
**In Tableau (using user functions):** Tableau's USER() and USERDOMAIN() functions return the username of the currently authenticated user. A row-level filter in the published data source uses these functions to filter rows: IF [Region Manager] = USERNAME() THEN TRUE ELSE FALSE END. When the user loads a dashboard, Tableau sends a query to the data source that includes this filter, and only the matching rows are returned.
**In Power BI:** RLS is configured in Power BI Desktop by defining roles with DAX filter expressions. A "Sales Manager" role might have a filter on the Sales table where [ManagerEmail] = USERPRINCIPALNAME(). Users are assigned to roles in the Power BI service, and the filter is applied automatically when they access the report.
Implementation Patterns
### Username-to-Entitlement Mapping
The most common RLS implementation uses a mapping table: a table that maps user identities to the data they are authorized to see.
A sales region entitlement table might have columns for username and region. The RLS filter joins the data table to this entitlement table on the current user's identity, returning only the rows where the region matches an entitlement record for that user.
This pattern is flexible — entitlements can be many-to-many (a national sales manager sees multiple regions) — and maintainable. Adding or removing a user's access requires changing a row in the entitlement table, not modifying the RLS logic itself.
### Role-Based Access
Rather than mapping individual users to entitlements, role-based RLS maps roles to entitlements. Users are assigned to roles (via Tableau groups, Active Directory groups, or the BI tool's role mechanism), and roles are mapped to data permissions.
Role-based RLS scales better than user-based RLS in large organizations: managing 500 individual user entitlements is harder than managing 20 role entitlements and assigning users to roles.
### Static Filters
For simple cases, static filters in published data sources restrict all users to a specific subset of data. A published data source containing only the last 90 days of transactions, or only production environment data with test records excluded, is a form of access control even if it applies equally to all users of that source.
Static filters are appropriate when the access restriction applies to all users equally. They are not row-level security in the dynamic sense — they do not vary by user — but they achieve the same outcome (restricting data access) with less complexity.
Performance Implications
RLS in BI tools has performance implications that are frequently underestimated:
**Live connection RLS** sends one query to the database per user interaction. If the RLS filter requires a join to an entitlement table on every query, the join adds overhead to every query execution. For large entitlement tables or complex join conditions, this overhead can be significant.
**Extract RLS in Tableau** uses either user filters (filtering the extract at query time, which avoids data duplication but adds query overhead) or partitioned extracts (creating separate extract partitions per user group, which is fast but increases storage and extract refresh time proportionally). Partitioned extracts become impractical at high user-group cardinality.
**Warehouse-native RLS** pushes the filtering overhead to the warehouse, which is typically better equipped to handle it than a BI tool. Warehouse RLS also benefits from query optimization (partition pruning, clustering) that BI tool filters cannot exploit as effectively.
Common RLS Design Mistakes
**Implementing RLS at the workbook level, not the data source level.** Workbook-level filters restrict what is shown in a specific dashboard but do not prevent a determined user from downloading the underlying data source. Data-source-level RLS restricts data access regardless of how the data is consumed.
**Maintaining entitlement logic in multiple places.** If RLS logic is implemented independently in Tableau, in Power BI, and in a Python report — each with its own entitlement table — a change to user entitlements requires updating three systems. Centralizing entitlements in the warehouse and enforcing RLS at the warehouse level ensures consistency.
**Not testing with realistic user diversity.** RLS is often tested by the developer, who may not have a restricted entitlement profile, or with a small test dataset that does not expose edge cases. Test with representative users from each entitlement category, including edge cases like users in multiple groups or users with no matching entitlements.
**Ignoring performance at scale.** An RLS implementation that works correctly for 20 users may perform unacceptably for 2,000 users if the entitlement join is not indexed and optimized.
Our Tableau consulting and data architecture practices design and implement RLS for Tableau, Power BI, and warehouse environments — including entitlement modeling, performance optimization, and testing frameworks. Contact us to discuss your data access control requirements.
A former Microsoft data architect audits your data foundation, identifies your top priorities, and sends you a written plan. Free. No pitch.
Book a Call →