Power BI RLS controls which data rows a user can see within a report. This guide covers static roles, dynamic RLS using USERNAME() and USERPRINCIPALNAME(), object-level security for table and column restriction, and the governance model for managing RLS at scale.
Row-level security in Power BI restricts which data rows a given user can see within a report or dataset. Without RLS, any user with access to a dataset sees all its data. With RLS, access is scoped by the user's identity or group membership. This guide covers static roles, dynamic RLS, object-level security, and how to manage RLS at enterprise scale.
How Power BI RLS works
Power BI RLS is defined at the semantic model (dataset) level, not the report level. Roles are defined in Power BI Desktop or the Power BI service, and each role contains a DAX filter expression that controls which rows are visible to members of that role. When a user opens a report built on an RLS-protected dataset, Power BI evaluates their role membership, applies the DAX filter to the model, and returns only matching rows.
RLS in Power BI applies to all reports built on the dataset. There is no per-report RLS configuration — the security boundary is the dataset, which is the correct governance model. If a user should not see certain rows of data, they should not see them in any report, regardless of which report they access.
Static RLS
Static RLS uses hard-coded filter values in the DAX expression. You define a role (for example, "East Region") and the filter expression is something like: [Region] = "East".
Users assigned to the East Region role see only rows where Region equals East. Users assigned to no role see all data (assuming they have at least Viewer access to the dataset).
Static RLS is simple to configure and appropriate for a small number of distinct access categories that rarely change:
- A small set of regions or departments
- Compliance environments where access categories are defined by policy, not by individual user data
The limitation is scalability. If you have 50 regional managers who each need to see their own region, creating 50 static roles and manually assigning users is operationally impractical. This is where dynamic RLS becomes necessary.
Dynamic RLS using USERNAME() and USERPRINCIPALNAME()
Dynamic RLS uses DAX functions that return the authenticated user's identity at query time:
- USERNAME() — returns the DOMAIN/username format (Windows authentication)
- USERPRINCIPALNAME() — returns the UPN / email address (Microsoft Entra ID, most common for Power BI Service)
The typical dynamic RLS pattern uses a security table — a table in the data model that maps user email addresses to the dimension values they are permitted to see. The DAX filter on the role is: [UserEmail] = USERPRINCIPALNAME(). This filters the security table to the current user's row, and through the relationship between the security table and the fact table, filters the data to only rows matching the user's permitted values.
The security table typically has columns: UserEmail, and one or more access-scope columns (Region, Department, AccountID, etc.). The relationship between the security table and the main data table is defined on the access scope column.
When User A opens the report, USERPRINCIPALNAME() returns "usera@company.com". The security table filter returns their row, which has Region = "East". The model relationship propagates this filter to the fact table, which returns only East region rows.
**Security table management**: The security table can live in the same data source as the main data or in a separate access management system. Using a separate security table that is refreshed from your identity management system (an HRIS, an IAM tool, or a custom access management database) allows access changes to propagate on dataset refresh without any Power BI model changes.
RLS with groups
Instead of mapping individual users, you can use group membership via PATHCONTAINS() or by structuring the security table to include role groups. Power BI's USERPRINCIPALNAME() returns the individual user's email — it does not natively return group memberships. To implement group-based RLS:
Option 1: Map groups to access dimensions in the security table. The security table has columns: GroupName, Region. A separate group membership table maps UserEmail to GroupName. The DAX filter joins through user → group → region.
Option 2: Use Power BI roles that correspond to groups, and assign Entra ID (Azure AD) groups to those roles in the Power BI service. Each role contains a static filter (or a dynamic filter using a parameter). The group assignment is managed outside Power BI Desktop, in the Power BI Service under dataset settings.
Object-level security
Object-level security (OLS) restricts access to entire tables or specific columns in the semantic model. Unlike RLS (which controls rows), OLS controls which model objects a user can see at all. A user without access to a table cannot see it in any visual, cannot use it in a report, and cannot query it via the XMLA endpoint.
OLS is defined using Tabular Editor or SSMS (via the XMLA endpoint) — it is not configurable in the Power BI Desktop UI as of mid-2026. The implementation involves setting the metadata permission on the table or column to "None" for specific roles.
Common OLS use cases:
- Hiding salary or compensation columns from roles that should not see individual pay data
- Hiding cost or margin columns from external-facing datasets
- Restricting access to a table that contains sensitive HR or financial data to only certain roles
OLS and RLS can be combined. A role can have both row-level filters (see only your region's data) and object-level restrictions (cannot see the cost column).
Testing RLS
Power BI Desktop has a built-in role tester: Modeling > View as > Roles. Select a role to preview the report as a member of that role. For dynamic RLS, use "Other user" and enter an email address — Power BI evaluates USERPRINCIPALNAME() as the entered address.
The Power BI service also supports "View as role" for published datasets, accessible from the dataset settings page.
Test RLS by:
1. Selecting a role and verifying that only expected rows appear
2. Using "Other user" with a specific email and verifying their access scope
3. Testing edge cases: a user in no role, a user in multiple roles, a user whose email is not in the security table
A user in no role sees no data (on a dataset with RLS defined). A user in multiple roles sees the union of all role filters — they see rows that pass ANY of their roles' filters, not only rows that pass ALL filters.
RLS in embedded and API scenarios
For Power BI Embedded (embed for your customers), RLS requires passing the user's effective identity in the embed token. The embed token generation call includes the effective_identity field with the username, and optionally role names. Power BI applies RLS for that username against the security table.
For reports embedded in SharePoint or Teams, users authenticate with their Microsoft identity — USERPRINCIPALNAME() returns their actual UPN, and dynamic RLS applies automatically without additional configuration.
For dataset access via the XMLA endpoint (Analysis Services), effective identity is determined by the connecting user's Entra ID identity. RLS applies if the connecting identity is a member of an RLS role.
Scale and performance
Dynamic RLS performance depends on:
**Security table query efficiency**: The security table filter applies on every query. If the security table is large (millions of rows) or the relationship to the fact table is complex, query time increases. Keep security tables small — one row per user-access-scope combination.
**Relationship cardinality**: The relationship between the security table and the fact table should be many-to-one (fact to dimension) not many-to-many. Many-to-many relationships in RLS can produce unexpected results and are slower.
**Import vs DirectQuery**: For import mode datasets, RLS is applied as an in-memory filter — very fast. For DirectQuery, the RLS filter is translated to a WHERE clause in the SQL sent to the source database. Complex RLS DAX may produce inefficient SQL. Test DirectQuery RLS performance at realistic user scale.
For the broader Power BI deployment context, see power bi deployment guide and power bi performance optimization. Our Tableau and BI consulting practice implements enterprise RLS across Power BI, Tableau, and Looker deployments — book a scoping call to discuss your access governance 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 →