skip to content

In Power BI, what does a row-level security role do to the data a report user sees?

level: middleimportance: must knowfreq 75%

answer

  1. a role is a filter, not a user list
  2. one DAX boolean expression per table
  3. relationships carry it to the fact
  4. applied before your measures run
  5. Desktop defines it, the Service assigns it

basics

~20 s

A Power BI role holds a DAX boolean filter on one or more tables. The engine applies it to every query the assigned user runs and propagates it along relationships, so excluded rows never reach visuals, totals or exports.

solid answer

~50 s

A role in Power BI is a named set of table filter expressions written in DAX, for example `[Region] = "West"` on the region dimension. When a user assigned to that role opens a report, the engine adds the role's predicate to every query before the report's own filters and measures run, and the filter then propagates through model relationships in their cross-filter direction — so filtering the region dimension also restricts the sales fact joined to it. Because the filter is applied by the engine as a security filter, a measure cannot undo it: `CALCULATE(SUM(Sales[Amount]), ALL(DimRegion))` still returns only the permitted rows. Roles are **defined in Power BI Desktop** but **members are assigned in the Power BI Service**, on the published semantic model's security page. RLS filters rows only; it does not hide columns or tables.

code

dax · 2 lines
dax
-- Role "West Region", filter expression on table DimRegion
[Region] = "West"

go deeper

for a junior

Be able to say that a role holds a DAX filter such as [Region] = "West", that it is written in Power BI Desktop, and that people are added to the role after publishing.

for a middle

Explain the mechanics: the security filter is applied before report filters and measures, it travels along relationships from dimension to fact, and no DAX in the model can remove it.

for a senior

Show that you reason about propagation and leakage — inactive or wrongly directed relationships, disconnected facts, and the effect of the security filter on percent-of-total measures and exports.

for a principal

Own the model as a security boundary: decide whether entitlements belong in the semantic model at all, how role membership is driven by identity groups, and what an editor-rights bypass means for who may work in the workspace.

## What a role is Row-level security (RLS) in Power BI is implemented with **roles**. A role is a name plus, for each table you choose, one DAX expression that must evaluate to TRUE for a row to be visible. A role that filters nothing on a table leaves that table unrestricted. Roles are authored in Power BI Desktop (Manage roles), stored in the model metadata, and travel with the file when you publish. A typical static filter looks like: ``` [Region] = "West" ``` placed on `DimRegion`. Anyone assigned to that role sees only the West row of the dimension. ## Where the filter is applied The key point most candidates miss: the role filter is applied by the storage engine **outside** the report's own logic. Conceptually the order is: security filter → report/page/visual filters and slicers → measure evaluation. That has two consequences. First, **totals are secure**. A card showing `SUM(Sales[Amount])` for a restricted user is the total of the rows that user may see, not the grand total with rows hidden from the table visual. Nothing in the report can reveal the suppressed rows, including drillthrough, tooltips, Export data, Analyze in Excel, or a query issued over the XMLA endpoint. Second, **filter-removing DAX does not bypass it**. `ALL`, `ALLEXCEPT` and `REMOVEFILTERS` clear the filters the report placed on a table; they cannot clear the security filter. So `CALCULATE(SUM(Sales[Amount]), ALL(DimRegion))` — the usual "percent of total" pattern — returns the user's own total, which is why a "% of all regions" measure quietly becomes "% of my regions" under RLS. That is correct security behaviour, and a design problem you have to solve another way (for example by publishing a separate unrestricted aggregate, or accepting the restricted denominator). ## How the filter reaches the fact table RLS relies entirely on the model's relationships. A filter placed on a dimension flows to the fact table exactly as any other filter does — down the one-to-many relationship, in its cross-filter direction. This is why RLS is usually applied to the **dimension**, not the fact: one small predicate on `DimRegion` restricts `FactSales`, `FactBudget` and anything else related to it. It also means RLS inherits every propagation weakness of the model. If a relationship is missing or inactive, or points the wrong way, or a fact table is disconnected, the filter does not arrive and rows leak. Filtering a table on the *many* side (a user-permission bridge, for example) reaches the *one* side only if the relationship is bi-directional or has the relationship's security-filtering-in-both-directions option enabled. ## Static versus dynamic The filter above is **static**: the permitted value is hardcoded, so you need one role per audience (West, East, EMEA…) and you maintain membership by hand. **Dynamic** RLS writes one role whose filter compares a column to the signed-in identity, typically `[UserEmail] = USERPRINCIPALNAME()` on a user-mapping table, so a single role serves every user and permissions are data you can refresh. Dynamic is the standard answer for "each manager sees only their region". ## Defining versus assigning Desktop defines roles and their expressions; it does **not** hold membership. After publishing, an admin opens the semantic model's security settings in the Power BI Service and adds users or, better, Microsoft Entra security groups to each role. Membership by group means joiners and leavers are handled by identity management rather than by a BI admin. ## What RLS is not RLS filters **rows**. It does not hide a column or a table — a restricted user still sees that a `Salary` column exists and can put it on a visual (over their permitted rows). Hiding metadata is object-level security (OLS), a separate feature configured through external tooling against the model, not in the Desktop RLS dialog. RLS also does not restrict people who can edit the model. A user with workspace edit rights bypasses roles entirely, so consumers must land in read-only access (Viewer, or an app audience) for RLS to mean anything. ## Modes RLS works in Import and DirectQuery models. Under DirectQuery the predicate is pushed into the generated source query, so the source database sees a filtered SQL statement. For a live connection to an external Analysis Services model, the roles live in that source model, not in the report.

  • If the security filter is applied first, what happens to a percent-of-total measure that uses ALL?
    The denominator shrinks to the user's own rows. ALL and REMOVEFILTERS clear report filters, never the security filter, so `% of all regions` silently becomes `% of my regions`. If a true company-wide denominator is required, it has to come from somewhere RLS does not restrict — a separate unrestricted aggregate table or model — because no DAX written inside the restricted model can recover the hidden rows.
  • Can a role hide a sensitive column rather than rows?
    No. RLS filters rows only; a restricted user still sees the column in the field list and can use it over their permitted rows. Hiding a whole table or column is object-level security, defined in the model metadata through external tooling rather than in the Desktop role dialog, and it makes visuals that reference the hidden object fail rather than return blanks.
  • Where would you apply the role filter in a star schema — the fact or the dimension?
    The dimension. One predicate on a small dimension propagates down its relationships to every related fact, so it is cheaper to evaluate and stays correct when new fact tables are added. Filtering a large fact table directly means repeating the rule per fact, evaluating it over many more rows, and forgetting one table the next time the model grows.

A role is like a badge that dims the lights in every aisle of the warehouse except yours: you can still walk anywhere and run any calculation, but you can only ever count the boxes you can see.

saying these in an interview costs you the question

  • Thinking RLS just hides visuals or report pages
  • Believing ALL or REMOVEFILTERS can bypass a role filter
  • Assigning role members in Desktop instead of the Service
  • Assuming a role hides columns as well as rows
  • Applying the filter to the fact table by default

context