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.

Role: Chief_Revenue_Officer(Top Level - No parentRole) Role: VP_Enterprise_Sales(parentRole: Chief_Revenue_Officer) Role: Enterprise_Account_Executive(parentRole: VP_Enterprise_Sales) Implicit Account Owner Access:- opportunityAccessLevel- caseAccessLevel- contactAccessLevel

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
<?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:

SQL
-- 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) DESC

Frequently 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.