
In Short: How Row-Level Security in Power BI Works
Row-level security in Power BI lets you publish one report to an entire organisation while ensuring each user only sees the data they are permitted to see. A regional manager sees their region. A salesperson sees their own pipeline. An executive sees everything. All from the same report, with no manual filtering or separate report versions.
RLS is enforced inside the semantic model itself, so the filtering happens at query time regardless of how the report is accessed - in Power BI Service, embedded in an app, or through Analyze in Excel. This guide covers the three main approaches, a step-by-step setup, and the details that decide whether your security actually holds.
Why Row-Level Security Matters
Without RLS, controlling data access in Power BI means one of two approaches: build separate reports for each audience, which is expensive to maintain, or restrict access to the report entirely, which defeats the purpose of self-service analytics.
RLS enforces data access rules at the model level, and those rules travel with the semantic model. If a Viewer with Build permission connects from Excel, the row-level filter still applies. If they build their own report on the shared model, they still only see their permitted rows.
One rule shapes everything else: RLS only applies to users with Viewer permissions. Workspace Admins, Members and Contributors have edit rights on the model and see all data.
Static RLS
Static RLS is the simpler approach. You define roles in Power BI Desktop using DAX filter expressions, then assign users or Microsoft Entra security groups to those roles in Power BI Service.
Example: A role called "UK Region" with a DAX filter applied to the Region table:
[Region] = "United Kingdom"
Any user assigned to the UK Region role sees only rows where Region is United Kingdom, across all visuals in every report built on that semantic model.
When to use static RLS:
- Your audience segments are fixed and change infrequently
- The number of roles is manageable - typically fewer than twenty
- You are comfortable that a new segment means a new role and a republish
Limitations: Each new region, department, or segment requires a new role definition and a republish. At scale - fifty regional roles or a role per salesperson - this becomes an administrative burden. Dynamic RLS solves this.
Dynamic RLS
Dynamic RLS uses a security mapping table and the USERPRINCIPALNAME() DAX function to filter data based on the signed-in user's identity - without defining individual roles per user. In the Power BI service, USERPRINCIPALNAME() returns the user's UPN, which usually looks like their email address.
The pattern:
- Create a mapping table in your model - for example, columns for UserEmail and Region - that defines which user can see which data.
- Create a single role that filters the mapping table with [UserEmail] = USERPRINCIPALNAME(), and let relationships carry that filter to your dimension and fact tables.
- Assign all report users to that single role in Power BI Service.
Adding a user or changing their permissions then means updating the mapping table - no role changes, no model republish.
When to use dynamic RLS:
- Your user base is large or changes frequently
- Access permissions already live in a database or HR system you can sync to the mapping table
- You need to add or remove users without touching the model
Dynamic RLS is the recommended pattern for most enterprise implementations. The mapping table becomes the single source of truth for data access and can be refreshed on a schedule from your authoritative source system.
How to Set Up Row-Level Security in Power BI
The workflow Microsoft documents has four stages: define roles, publish, add members, validate.
1. Define the roles in Power BI Desktop
- On the Modeling tab, select Manage roles, then New, and name the role (role names cannot contain commas).
- Select the table to filter. For a static rule, the default editor is enough. For a dynamic rule, select Switch to DAX editor - rules using USERPRINCIPALNAME() or USERNAME() can only be written in DAX.
- If your mapping table sits on the "many" side of a relationship, the filter will not flow towards your dimension by default. Select the relationship and tick Apply security filter in both directions, which Microsoft recommends only where dynamic RLS needs it, as it can slow queries.
- Save the role.
2. Test in Desktop with View as
On the Modeling tab, select View as, pick the role, and for dynamic rules tick Other user and enter a real UPN. In Desktop, USERNAME() returns DOMAIN\user format and USERPRINCIPALNAME() returns the UPN, so build dynamic rules on USERPRINCIPALNAME().
3. Publish and assign members in the Service
Publish the model, open the workspace, select More options on the semantic model and choose Security. Add users or groups to each role. Distribution groups, mail-enabled groups and Microsoft Entra security groups are supported; Microsoft 365 groups are not. You cannot assign members in Desktop.
4. Validate with Test as role
On the Security page, select More options next to the role, then Test as role. Use Now viewing as to test a combination of roles or a specific person.
Object-Level Security
Object-level security (OLS) extends beyond rows to control which tables and columns a user can see at all. For a user without permission, secured tables or columns behave as if they do not exist.
OLS is defined within model roles, using TMDL view in Power BI Desktop or external tools such as Tabular Editor, and members are assigned on the same Security page as RLS.
Common uses:
- Hiding salary columns from non-HR roles
- Restricting margin or cost-price data from non-finance roles
- Controlling which measures are visible to different audiences
OLS and RLS can be combined: a user might be restricted to their own region via RLS and unable to see the cost-price column via OLS. Visuals that use a secured field show an error rather than a blank.
RLS in Microsoft Fabric, Direct Lake and DirectQuery
RLS defined in the semantic model works with Import, DirectQuery and both flavours of Direct Lake. The fallback behaviour people worry about comes from somewhere else:
- Direct Lake on SQL analytics endpoints falls back to DirectQuery when a query touches a table secured by RLS at the SQL analytics endpoint, or a view. Model RLS alone does not force fallback.
- Direct Lake on OneLake never falls back. It does not apply SQL-endpoint RLS; it enforces OneLake security roles instead.
- DirectQuery pushes RLS filters into every source query, so index the source columns the rules filter on.
Microsoft strongly recommends a fixed-identity cloud connection for Direct Lake models that use RLS. With the default single sign-on, users need read access to the lakehouse and could query it directly, bypassing model rules.
For organisations running Fabric, OneLake security applies rules across every engine - a complementary layer covered in our guide to the Microsoft Fabric security model.
Common Mistakes With Row-Level Security in Power BI
Mistake 1: Giving consumers the wrong workspace role RLS does not apply in Desktop until you use View as, and in the Service it does not apply to Admins, Members or Contributors. If people who should be filtered sit in those roles, they see everything. Put consumers in Viewer, or share through an app - part of sound workspace governance.
Mistake 2: Treating report filters as security Report-level filters are not security controls. RLS must be applied at the semantic model.
Mistake 3: Stacking roles Roles are additive. A user in a restrictive role and a permissive role sees the union of both.
Mistake 4: Mismatched identities USERPRINCIPALNAME() returns the sign-in UPN, which can differ from the mail address, and B2B guests may appear in #EXT# format. Store exactly what the function returns.
Mistake 5: Overlooking relationships RLS filters propagate only through active relationships. Putting rules on dimension tables in a clean star schema is usually faster and safer than filtering fact tables.
Mistake 6: Expecting service principals to be filtered Service principals cannot be added to RLS roles. Embedded apps must pass an effective identity in the embed token.
Testing Your RLS Before Publishing
Always validate RLS before publishing to a broad audience:
- Use View as in Desktop, including Other user for dynamic rules
- Use Test as role in the Service - but note it uses your own identity for USERPRINCIPALNAME(), so sign in as a real Viewer to prove dynamic rules
- Test B2B guests with their actual accounts
- Add a "Who Am I" card measure returning USERPRINCIPALNAME() during testing
- Confirm Analyze in Excel respects the filters, and check row counts against the source
A brief security testing checklist, signed off by the data owner, is worth including in any governed deployment process.
Getting RLS Right in Production
Row-level security that is misconfigured gives false confidence, and RLS that is badly designed slows every report that touches it. Both failure modes are common and neither is obvious from the report surface.
If that is where you are, Power BI consulting is the work we do, and how governed access works across a whole estate covers the background.
Sources and Further Reading
- Row-level security (RLS) with Power BI
- Row-level security (RLS) guidance in Power BI Desktop
- Object-level security (OLS) with Power BI
- Direct Lake overview
- Integrate Direct Lake security
Frequently asked
Row-level security (RLS) restricts which rows of data each user can see in a Power BI semantic model. Roles are defined with DAX filter expressions, and every query against the model - from a report, Analyze in Excel or a report a user builds themselves - is filtered for users the rules apply to. RLS only applies to users with Viewer-level access: workspace Admins, Members and Contributors are not filtered.
In Power BI Desktop, go to the Modeling tab, select Manage roles, create a role and define a DAX filter on the relevant table. Test it with View as, publish the model, then in the Power BI service open the semantic model's More options menu, select Security and add users or security groups to the role. Finish by checking each role with Test as role.
Static RLS hard-codes a value in each role, such as [Region] = "United Kingdom", so you need one role per audience. Dynamic RLS uses one role and a mapping table filtered by USERPRINCIPALNAME(), which returns the signed-in user's UPN, so access changes are made in the mapping data rather than in the model. Dynamic RLS suits most organisations with more than a handful of audiences.
Yes. RLS defined in the semantic model is supported in Import, DirectQuery and both Direct Lake modes. What causes Direct Lake on SQL to fall back to DirectQuery is RLS defined at the SQL analytics endpoint, not RLS in the model. Microsoft strongly recommends binding Direct Lake models that use RLS to a fixed-identity cloud connection, so users cannot bypass the model by querying the lakehouse directly.
Object-level security (OLS) hides whole tables or columns from a role, so for those users the objects behave as if they do not exist. Like RLS it is defined in model roles, using TMDL view in Power BI Desktop or an external tool such as Tabular Editor, and members are assigned on the same Security page in the Power BI service.
The most common reason is their workspace role. RLS only filters users with Viewer permission; anyone who is an Admin, Member or Contributor in the workspace has edit rights on the semantic model and is not filtered. Other causes are membership of several roles, because roles are additive, and report-level filters being mistaken for security.


