🎯 Situation

A sales VP asked us to build one Power BI dashboard for the entire sales team — 5 regional managers and 25 reps. The requirement: each person sees their own region's data, managers see their region plus their reps' individual data, and the VP sees everything. Same report. Same dataset. Completely different views depending on who logs in.

👉 Row-Level Security (RLS) in Power BI filters data at the row level based on who is viewing the report. The filter is applied automatically — the user never sees a filter selector. They just see their data. One report serves the entire organization, each person with the appropriate scope.

⚠️ Challenge

🔒 Static RLS — simplest case

  • Create a role in Power BI Desktop: Manage Roles → New Role
  • Add a DAX filter on the table: [Region] = 'North'
  • Add the specific users to that role in Power BI Service
  • Works for small teams with stable regions
  • No mapping table needed — just hardcoded values per role

👤 Dynamic RLS — scales with the organization

  • Create a mapping table: [UserEmail] and [Region] columns
  • Load it into your Power BI dataset
  • Write one DAX filter: [Region] IN VALUES(UserRegionMap[Region]) where UserRegionMap filters to USERPRINCIPALNAME()
  • When a new rep joins, add one row to the mapping table — the report updates automatically
  • Scales to 500 users with zero report changes

🔍 Analysis

The exact DAX for dynamic RLS:

-- In the Region filter on the Sales table:
[Region] IN
    CALCULATETABLE(
        VALUES(UserRegionMap[Region]),
        FILTER(UserRegionMap, UserRegionMap[UserEmail] = USERPRINCIPALNAME())
    )

This single filter, applied as a role, dynamically restricts every visual in the report to the regions mapped to the logged-in user's email. The VP account maps to all regions. A regional manager maps to one. A rep maps to a single territory.

One common mistake: RLS filters are applied AFTER DAX measure calculations. This means a measure like [Total Revenue] already filtered by RLS will show only the user's revenue — not the total. If you want to show 'my revenue vs. company total', you need a specific measure that removes the RLS filter using ALL(). This is the most frequent RLS debugging issue.

✓️ Best Practice

Three deployment steps:

  • Build and test in Power BI Desktop — use 'View as Role' to simulate each user type before publishing
  • Publish to Power BI Service, then go to the dataset → Security → assign users or security groups to each role
  • Test again in Service using 'Test as Role' — confirm the data scoping is correct before sharing with users

💡 Summary

RLS is one of the highest-value Power BI features for any organization with different data access needs across teams. One report replaces five. One dataset serves everyone. The management overhead is a mapping table with one row per user — updated when the team changes.

👉 One dashboard. Every person sees only their data. No filter selectors. No separate reports.

That's RLS — and it takes an afternoon to build.