Skip to main content
power bi row-level securitydata securityaccess controluser permissions

Power BI Row-Level Security (RLS)

A regional sales manager opens the company's sales dashboard and sees only their region's data. Their colleague in another region sees the same report layout but different numbers. The finance director sees everything. All three use the same Power BI report — Row-Level Security filters the data per user, transparently.

RLS restricts which rows of data a user can see in a Power BI report based on their identity. It uses DAX filter expressions applied to the data model, enforced automatically across Power BI Service, mobile apps, embedded analytics, and API access. Without RLS, organizations either build separate reports per audience (unscalable) or give everyone access to everything (a security and compliance risk). RLS solves this: one report, many audiences, each seeing only what they should.

TL;DR

Row-Level Security (RLS) in Power BI restricts data visibility per user using DAX filter expressions applied to the data model. Static RLS uses fixed role definitions (e.g., Region = "Europe"). Dynamic RLS uses USERNAME() to filter data based on the logged-in user's identity mapped to a security table. RLS works across Power BI Service, embedded analytics, and mobile. The governance requirement: a data catalog must track which datasets have RLS configured and which roles exist.

How RLS Works

RLS operates at the semantic model level, not the visual level. Roles are defined in Power BI Desktop with DAX filter expressions. When a user accesses a report in Power BI Service, the engine checks their role membership, applies the corresponding DAX filters to the data model, and every visual renders with the filtered data. The user never sees the filter — it is invisible and cannot be removed by the report consumer.

HOW RLS FILTERS DATAManager ARegion: NorthManager BRegion: SouthFinance DirectorAll regionsRLS FilterDAX expressionsper roleNorth rows1,200 of 5,000South rows800 of 5,000All rows5,000 of 5,000SameReportLayoutFilter propagation: filtering the Region table automatically filters all related tables (Sales, Customers, Products)
Click to enlarge

Filter propagation through relationships is what makes RLS powerful. If you define a filter on the Region table, all tables related to Region — Sales, Customers, Products sold in that region — are automatically filtered. You do not need to write separate filters for every table. The data model's relationship graph does the work.

Row-Level Security in Power BI is enforced across all consumption modes — Power BI Service, mobile apps, embedded analytics, and publish-to-web (with appropriate configuration). RLS roles are defined in the data model and cannot be bypassed by end users.

— Microsoft, Power BI Security Documentation

Static RLS: Fixed Role Definitions

Static RLS assigns users to predefined roles with hardcoded DAX filters. It is the simplest pattern: create a role, write the filter, assign users.

-- Static RLS: users in this role see only North America data [Region] = "North America" -- Static RLS: users see only Sales department data [Department] = "Sales" -- Combine conditions: Europe, Electronics and Computers only [Region] = "Europe" && [Product Category] IN {"Electronics", "Computers"}

Role creation happens in Power BI Desktop under Modeling > Manage Roles. Each role contains one or more table-level DAX filter expressions. After publishing to Power BI Service, you assign users or Azure AD security groups to each role under dataset settings.

When to use static RLS: Small number of well-defined audience segments. Three regional roles (North America, Europe, APAC) that rarely change. A partner-facing report where each partner organization has its own role.

Limitation: Every new audience segment requires a new role definition, a Desktop update, and a republish. If the organization adds a fourth region, someone has to open the .pbix, create the role, publish, and assign users. This does not scale past a dozen roles.

Dynamic RLS: User-Based Filtering

Dynamic RLS uses USERNAME() or USERPRINCIPALNAME() to identify the logged-in user and look up their data access scope from a security table in the data model. One role handles all users — no role-per-audience maintenance.

The pattern: create a table mapping UserEmail to allowed data scope (region, department, customer ID). The DAX filter uses LOOKUPVALUE() to match the current user against this table:

-- Dynamic RLS: one role, data-driven filtering -- Security table: UserRegions (UserEmail, Region) [Region] = LOOKUPVALUE( UserRegions[Region], UserRegions[UserEmail], USERNAME() )

When a new employee joins or someone changes regions, you update the security table — not the role definition. No Desktop republish needed. The security table can be maintained in a source database and refreshed with the dataset.

Hierarchical RLS

Many organizations need hierarchical access: employees see their own data, managers see their team's data, executives see everything. The SWITCH pattern handles this cleanly:

-- Hierarchical RLS: employee → manager → executive VAR CurrentUser = USERNAME() VAR UserLevel = LOOKUPVALUE(Users[Level], Users[Email], CurrentUser) VAR UserDepartment = LOOKUPVALUE(Users[Department], Users[Email], CurrentUser) RETURN SWITCH( UserLevel, "Executive", TRUE(), -- sees all data "Manager", [Department] = UserDepartment, -- sees department data "Employee", [AssignedTo] = CurrentUser, -- sees own data only FALSE() -- no match = no access )

STATIC VS. DYNAMIC RLSStatic RLSRole: North AmericaRole: EuropeRole: APAC[Region] = "North America"[Region] = "Europe"[Region] = "APAC"New region = new role + republishDynamic RLSRole: DataAccessUSERNAME() lookupSecurity Tablealice@co.comNorth Americabob@co.comEuropeNew user = new row in table
Click to enlarge

Common RLS Patterns

Four patterns cover the majority of enterprise RLS implementations.

1. Manager hierarchy. Managers see their direct reports' data. Executives see everything. The security table maps each user to their level and scope. The SWITCH pattern (above) handles this with three branches.

2. Multi-tenant isolation. Each customer organization sees only their own data. Common in embedded analytics scenarios where one Power BI report serves multiple tenants:

-- Multi-tenant RLS: isolate data by tenant VAR UserTenant = LOOKUPVALUE( UserTenants[TenantID], UserTenants[UserEmail], USERNAME() ) RETURN [CustomerTenantID] = UserTenant

3. Date-based access. Users see only the current fiscal year's data, or a rolling 12-month window:

-- Rolling 12-month window [Date] >= DATE(YEAR(TODAY()) - 1, MONTH(TODAY()), 1) && [Date] <= TODAY()

4. Combination filters. Region + department + date in one expression. The most common enterprise pattern: a user in Europe's Finance team sees European financial data for the current year only. This combines dynamic user lookup with multiple filter dimensions.

Testing and Validating RLS

RLS testing catches three categories of errors: over-permissive (users see data they should not), over-restrictive (users see nothing — the "blank report" problem), and filter propagation failures (the Region table is filtered but the Products table is not, because the relationship is missing or inactive).

Test in Power BI Desktop using "View as Roles" (Modeling tab). Select a role, optionally combine it with a specific user identity, and the report renders exactly as that user would see it. Check row counts — if a regional manager should see 1,200 rows but the report shows 5,000, the filter is not working.

Testing checklist:

  • Test each role individually — verify correct data subset
  • Test users assigned to multiple roles — Power BI applies the union of all role filters (more data, not less)
  • Test a user with no role assigned — they should see no data (Power BI returns empty results)
  • Verify filter propagation across all related tables — if Region is filtered, check that Sales, Customers, and Products are also filtered
  • Test with production data volumes — an RLS filter that works on 10K rows may timeout on 10M rows
  • Check cross-filter direction — bidirectional relationships can leak data if not configured carefully

Performance Impact of RLS

RLS adds DAX filter evaluation to every query. The impact depends on filter complexity.

Simple filters like [Region] = "Europe" have negligible performance impact. The engine pushes these to the storage engine as scan predicates — the same mechanism used for slicer selections.

Complex filters with LOOKUPVALUE, CALCULATE, or large security tables can degrade performance measurably. A security table with 50,000 user-region mappings scanned via LOOKUPVALUE on every query adds latency. Mitigation strategies:

  • Keep security tables narrow — 3-4 columns maximum (UserEmail, DimensionKey, Scope)
  • Use integer keys instead of text matching where possible
  • Avoid nested IF/SWITCH with more than 5 branches — consider refactoring into a flattened security table lookup
  • Cache user lookups in variables — evaluate USERNAME() once per query, not in every filter expression
  • Test with production data volumes and concurrent users — RLS performance that looks fine in Desktop with test data may degrade under 500 concurrent Service users

68% of organizations with more than 500 Power BI datasets report that they lack visibility into which datasets have Row-Level Security configured and which roles are actively maintained.

— Gartner, Data and Analytics Governance Survey

Why RLS Needs a Governance Layer

RLS definitions live inside the Power BI data model — invisible to anyone who does not open Power BI Desktop or query the REST API. In an enterprise with hundreds of datasets, nobody has a consolidated view of which datasets have RLS configured, what roles exist, what DAX filters they apply, and which users are assigned to which roles.

RLS GOVERNANCE VISIBILITYWithout CatalogDataset 1RLS?Dataset 2Roles?Dataset 3Owner?Dataset 4Audit?No visibility into security configurationWith Data CatalogDataset 13 rolesDataset 2DynamicDataset 3No RLS!Dataset 4AuditedFull visibility: roles, owners, last audit dateCatalog Entry: Dataset 1 — Sales ReportRLS Status: EnabledRoles: NA, Europe, APACOwner: Data OpsAudited: Jan 2026Type: Dynamic (USERNAME lookup)Security Table: UserRegions (342 rows)Next review: Apr 2026
Click to enlarge

This creates a security blind spot. An auditor asks "which datasets expose customer PII, and which of those have RLS?" Nobody can answer without manually inspecting each .pbix file or writing custom REST API scripts. At 500+ datasets, that is not feasible.

A data catalog provides this visibility: documenting which datasets are secured, what access patterns exist, and who manages the security definitions. Without external governance, RLS becomes a hidden security layer that nobody can audit at scale.

How Dawiso Supports RLS Governance

Dawiso's data catalog documents which Power BI datasets have RLS configured — role names, filter logic summaries, and owner contacts. When an auditor asks which datasets have security controls, the answer is a catalog query, not a week of manual investigation.

The business glossary ensures that the dimensions used in RLS filters have consistent definitions across datasets. If "Region" means different things in different datasets — one includes Middle East in APAC, another does not — RLS filters produce inconsistent access boundaries. The glossary resolves this by providing a single authoritative definition that all datasets reference.

Data lineage traces security-relevant columns from source systems through transformations to the RLS filter expression. When someone asks "where does the Region column in the RLS filter come from?", lineage shows the complete chain: CRM system > staging table > data warehouse > Power BI model > RLS filter.

Through the Model Context Protocol (MCP), AI agents can query Dawiso's catalog programmatically to verify that every published dataset has documented RLS configuration. An automated governance check can flag new datasets published without RLS documentation — catching security gaps before they become audit findings.

Conclusion

Row-Level Security is one of Power BI's most practical enterprise features — one report serving many audiences with transparent, per-user data filtering. Static RLS works for small, stable audience segmentations. Dynamic RLS scales to thousands of users with a single role and a security table. The technical implementation is well-documented. The harder challenge is visibility: knowing which of your 500 datasets have RLS, what roles they define, and whether those roles are still correct six months after deployment. That is where data governance and a data catalog close the gap.

Dawiso
Built with love for our users
Make Data Simple for Everyone.
Try Dawiso for free today and discover its ease of use firsthand.
© Dawiso s.r.o. All rights reserved