The Role metadata type represents a single node in your organization’s Role Hierarchy. Introduced in API version 24.0 (extending RoleOrTerritory), Role governs vertical record-level visibility: any user assigned to a parent role (parentRole) automatically inherits read/edit access to records owned by or shared with users in subordinate roles (for all standard objects and custom objects with Grant Access Using Hierarchies enabled).
In Salesforce DX projects, role definitions are stored in force-app/main/default/roles/ with the .role-meta.xml suffix.
Key Metadata Fields
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | UI display label of the Role in the Role Hierarchy tree |
parentRole |
string |
No | Developer fullName of the role immediately above this role in the hierarchy |
description |
string |
No | Description of the role’s scope |
opportunityAccessLevel |
string |
No | Account owner’s implicit access to child Opportunities (None, Read, or Edit) |
caseAccessLevel |
string |
No | Account owner’s implicit access to child Cases (None, Read, or Edit) |
contactAccessLevel |
string |
No | Account owner’s implicit access to child Contacts (None, Read, or Edit) |
mayForecastManagerShare |
boolean |
No | Indicates whether the forecast manager can share forecast data |
Production-Grade XML Example
Below is a Role definition (VP_Enterprise_Sales.role-meta.xml) reporting to Chief_Revenue_Officer:
<?xml version="1.0" encoding="UTF-8"?>
<Role xmlns="http://soap.sforce.com/2006/04/metadata">
<caseAccessLevel>Read</caseAccessLevel>
<contactAccessLevel>Edit</contactAccessLevel>
<description>Vice President of Enterprise Sales overseeing North America AEs.</description>
<mayForecastManagerShare>false</mayForecastManagerShare>
<name>VP, Enterprise Sales</name>
<opportunityAccessLevel>Edit</opportunityAccessLevel>
<parentRole>Chief_Revenue_Officer</parentRole>
</Role>Tip
PreventingImplicit Sharing Recalculation Locks: Setting opportunityAccessLevel and caseAccessLevel to None on roles that do not require automatic visibility into every child Opportunity or Case on their Accounts reduces implicit OpportunityShare and CaseShare table volume and speeds up Account ownership transfers.
Querying the Role Hierarchy with SOQL (UserRole)
In SOQL, roles are stored in the standard UserRole object:
-- 1. Inspect the Role Hierarchy structure and implicit Account child access
SELECT Id, DeveloperName, Name, ParentRoleId, PortalType,
OpportunityAccessForAccountOwner, CaseAccessForAccountOwner, ContactAccessForAccountOwner
FROM UserRole
WHERE PortalType = 'None'
ORDER BY Name ASC
-- 2. Count active users per Role to identify unpopulated or skewed roles
SELECT UserRole.DeveloperName, UserRole.Name, COUNT(Id) activeUsers
FROM User
WHERE IsActive = true AND UserRoleId != null
GROUP BY UserRole.DeveloperName, UserRole.Name
ORDER BY COUNT(Id) DESCFrequently asked questions
What is the difference between a Role and a Profile or Permission Set?
Profiles and Permission Sets control object-level and field-level permissions (what types of data a user can see and edit). Roles control record-level visibility (which specific records a user can see based on ownership and hierarchy).
What do opportunityAccessLevel, caseAccessLevel, and contactAccessLevel control on a Role?
They control the implicit access that the owner of an Account (and users above that owner in the Role Hierarchy) automatically receives on child Opportunities, Cases, and Contacts linked to that Account, even if someone else owns those child records.
What is the recommended maximum depth and total count for Roles in an enterprise org?
Salesforce recommends keeping the Role Hierarchy to no more than 10 levels deep and staying well below the default 5,000 Role limit to prevent slow sharing recalculations and Account Owner data skew locks.
How do I query Role metadata in SOQL?
In SOQL, Role metadata is represented by the standard UserRole object, which exposes Id, Name, DeveloperName, ParentRoleId, OpportunityAccessForAccountOwner, and CaseAccessForAccountOwner.
Why did my Role deployment fail with invalid ContactAccessLevel?
If Contact Organization-Wide Default (OWD) sharing is set to Controlled by Parent, contactAccessLevel on Role must be set to Edit (or omitted when Account access is Edit) because Contacts cannot have narrower access than their parent Account.
Comments
Questions, corrections and tips are welcome. Comments are GitHub Discussions, so you sign in with GitHub.