← All insights Power Platform

Dataverse security roles, explained with a real example

A Dataverse security role is a bundle of privileges, what a user can do to a table, paired with access levels, how far each privilege reaches. Business units and teams then decide how wide "their business unit" or "shared with them" actually is. The fastest way through all four pieces is one scenario: a consultant who should see only their own clients, a team lead who sees their team's, and a practice manager who sees everyone's.

Security roles usually get designed during a migration from a SharePoint list or an Access database; the mechanics of that move are on the Power Platform migration hub.

The scenario I'll use the whole way through

Picture a professional services firm running its client relationships out of a Dataverse table called Client. A handful of consultants each run their own client list. A couple of team leads each manage a group of consultants and need visibility across everyone on their team. One practice manager needs to see the lot, across every team, for reporting and quality checks. That's the entire brief: three people, three different slices of the same table, and nothing more exotic than that.

It sounds simple, and it is, once you separate the four mechanisms that combine to produce the answer. Most of the confusion around Dataverse security comes from treating "security role" as one setting instead of four that stack on top of each other: what a privilege lets you do, how far the access level lets it reach, whether a business unit widens or narrows that reach, and whether a team or a share hands someone access they wouldn't otherwise have.

Privileges and access levels, mapped onto it

A privilege is the verb: Create, Read, Write, Delete, Append, Append To, Assign or Share, applied to a specific table. An access level is the reach of that verb, and Dataverse gives you four real options: User (only records the person owns), Business Unit (every record owned by anyone in the same business unit), Parent: Child Business Units (that, plus every business unit beneath it in the hierarchy), and Organization (every record, full stop, regardless of who owns it or which business unit it sits in). A role with no access level set on a privilege simply doesn't grant that action at all.

The same four options, against the actual people in the scenario.

Access level on the Client tableWhat it grantsWho fits it here
UserOnly records this person ownsConsultant
Business UnitEvery record owned by anyone in the same business unitOnly fits the team lead if the firm's business units already match its teams, which is rarely true from day one
Parent: Child Business UnitsThe above, plus every subordinate business unitNot needed unless teams are nested business units
OrganizationEvery record, regardless of owner or business unitPractice manager

The consultant's role is the easy one: Read privilege on Client, set to User access level. Every client record they create is owned by them, and User-level access means the app filters down to exactly that, without a single line of extra configuration. The practice manager is equally easy at the other end: Read privilege at Organization level, and every record in the table is visible no matter who owns it.

It's worth knowing one gotcha here before it bites you: if a user holds more than one security role, Dataverse always applies the least restrictive access level across all of them. Give a team lead a second role for something unrelated that happens to carry Organization-level Read on Client, and they now see everyone's clients, not just their team's, whether that role's author meant to grant that or not. Auditing what a user can see means adding up every role they hold, not reading one role in isolation.

The team lead is the one row in that table without a clean fit, and that's deliberate. Business Unit access level only lines up with "my team" if the firm's business units are already drawn along team lines, and for most firms starting out, they aren't. That gap is exactly what the next two sections are about.

Business units: powerful, and usually reached for too early

A business unit in Dataverse is a real security boundary, not a folder. It holds users, it has a default team, and Business Unit and Parent: Child access levels key directly off it. The tempting fix for the team lead's gap above is to create one business unit per team, put each team lead's consultants inside it, and set the team lead's role to Business Unit access level. It works. It also commits the firm to running its Dataverse security tree in lockstep with its org chart.

That's more than it sounds like. Business unit membership isn't a tag you flip, it interacts with which default team a user belongs to and which business unit's data they're scoped into by default. Move a consultant to a different team next quarter, which happens constantly in a services firm, and that's now a business unit change, not a note in a spreadsheet. Microsoft eased some of this with a modernised business units update rolled out from around May 2025, which decouples a record's ownership from the owner's business unit and lets one user hold roles from more than one business unit at a time. That's a genuine improvement, but it doesn't change the underlying advice. Business units are still meant to mirror something structural, a legal entity, a regional division, a genuinely separate part of the business, not this quarter's team assignments.

Reach for a business unit when two parts of the firm should never see each other's data under any circumstance, say a New Zealand practice and an overseas subsidiary with entirely separate client bases. Don't reach for it to solve "my team lead needs to see their team." That's a lighter problem than it looks.

Teams and row sharing: the lighter answer

Dataverse has two kinds of team, and they solve different problems. An owner team can hold a security role and own records itself, much like a user can, and it's the right tool when a group of people share ownership of the same work. An access team can't own anything and can't hold a security role. It exists purely to hold shared access to individual records, and a whole team only needs one shared entry rather than one per member, which is the detail that keeps it light at scale.

For the team lead's gap, an access team is the better fit. Keep every consultant in one business unit. Keep client records owned individually by the consultant who runs them, which already satisfies the consultant's User-level requirement with nothing extra. Then add an access team template on the Client table, keyed to a "Team lead" lookup field on the record. The moment a client record is created, it automatically shares itself with whoever's named in that field, with Read access, no business unit restructuring involved. When a consultant moves teams, the thing that changes is the lookup value on their client records, not their security role and not their business unit membership.

Row sharing does have a cost worth knowing before you script it at scale. Every share, whether it comes from an access team or a manual share, writes a row to Dataverse's underlying access table. An access team keeps that to one row per record rather than one per team member, which is exactly why it beats sharing individually with ten people. But bulk-sharing a very large table, tens of thousands of records at once through a script, is a different performance conversation from the handful of shares a normal working day produces. For a firm-sized client list, it's a non-issue. It's worth flagging before someone builds an automated bulk-share job over a much bigger table later.

How to test a role before you trust it

To check a security role, become the person it's built for. Reading the role definition screen and taking its word for it is how an over-wide grant survives a review. Build three disposable test users in a sandbox environment, one per persona: test-consultant, test-teamlead, test-manager. If you're a solo builder without a proper dev environment to do this safely in yet, that's worth sorting first, and I've covered the minimum viable setup in Power Platform ALM when the team is one person, and what a small tenant can actually run without buying more capacity in the environment limits post. Assign each one exactly the role stack that persona will hold in production, and nothing extra, no leftover default role, no inherited team membership you're not testing.

Then sign in as each one, in its own browser profile or a private window, and check both directions on the same handful of records. Open a client record that belongs to someone else and confirm it doesn't show up at all, rather than only checking that the record you expect to see looks right. Open one that should be visible and confirm it opens and edits the way the role intends. If there's a filtered view like "My clients" or "My team's clients," check the count matches what you'd expect by hand, because a view that looks right can still be built on a filter that has nothing to do with the security model underneath it.

The Power Platform admin centre's per-user "Run diagnostics" tool is a useful second check, particularly for the failure mode where the security role looks correct on the edit screen but the app still won't open, usually because a related table like Account or Contact is missing a basic Read privilege the form needs to render. If a role needs testing repeatedly, say after every business unit or team change, Dataverse's Web API supports calling on behalf of another user through a caller ID header, gated behind its own privilege, which lets that same "should see, should not see" check run as a script instead of a manual login every time.

The mistake almost every role review makes is only testing the "should see" case and calling it done. A stray Parent: Child setting or an Organization-level privilege buried in a role nobody remembers assigning only shows up if someone deliberately goes looking for a record that's not supposed to be there. Test for that on purpose, every time a role changes.

This is the same mechanism I walk through on the Power Platform page when the data model itself is still up for grabs, and it's worth deciding before the security roles get built, not after: whether the table needs to live in Dataverse at all, because a SharePoint list with broken permission inheritance solves a much smaller version of this problem for firms that never needed the full model in the first place.

This post is about who can see which rows. Who can build and administer, and what to give a contractor, is in Environment Maker, System Admin or Power Platform Admin.

Questions I get asked about Dataverse security

What's the difference between a privilege and an access level in Dataverse?

A privilege is the action, such as Read, Write, Create, Assign or Share, applied to a specific table. An access level is how far that privilege reaches: only records the user owns, everyone in their business unit, their business unit plus its children, or the whole organisation. A security role is a set of privilege-and-access-level pairs across every table a role needs to touch.

Do I need a separate business unit for every team?

Usually not. Business units are a structural security boundary meant to mirror something like a legal entity or a division, not a reporting line that changes when staff move teams. For a manager who needs to see their team's records without seeing everyone's, an access team with row sharing on the record usually solves it without touching the business unit tree at all.

How do I test a Dataverse security role before rolling it out?

Build a disposable test user per persona in a sandbox environment, assign each one exactly the role stack that persona will hold in production, and sign in as each one to check both directions: that they can see and edit what they should, and that they cannot see a record that belongs to someone else. Testing only the 'should see' case is the most common way a role review misses an over-wide grant.

Balu Premkumar, founder of Kove

Building a security model that has to survive a real org chart?

Free 30-minute call. Tell me the roles you need and I'll say whether it's a role tweak, an access team, or something that needs a business unit.

Book a free 30-minute call →

Do your roles do what you think they do?

Book a free 30-minute call. I'll ask who needs to see what, then say whether it's a role change, a team, or a real business unit problem.

Christchurch-based. I reply within 1 working day. Or start with a Power Platform review →