Overview
Apex sharing is a mechanism in Salesforce that lets developers programmatically create, update, or delete share records to open record access for users or groups beyond what is provided by the standard role hierarchy, sharing rules, or organization-wide defaults (OWD). Apex sharing is commonly used when declarative sharing (sharing rules, manual sharing) can’t express complex business rules for record-level access.
When to use Apex sharing
Use Apex sharing when you need fine-grained, dynamic control of record-level access that cannot be achieved through:
- Role hierarchy
- Sharing rules (criteria or owner-based)
- Manual sharing via the UI
Common scenarios: granting temporary access, sharing with users in complex groups, or applying business rules that depend on related records or external systems.
How Apex sharing works
Every object that supports sharing has a corresponding share object: for example, AccountShare, OpportunityShare, and for custom objects MyObject__Share. A share record contains fields such as ParentId
, UserOrGroupId
, AccessLevel
, and RowCause
. By inserting/deleting these share rows via Apex, you control which user or group can see or edit a specific record.
Key fields in a share record
ParentId
: Id of the record being shared.UserOrGroupId
: Id of the User or Group that will get access.AccessLevel
: e.g.,Read
,Edit
, orAll
depending on object.RowCause
: reason for the share (e.g.,Manual
or a custom Apex-managed sharing reason).
Example: Sharing a custom object record via Apex
Below is a basic example showing how to grant Edit access to a user for a custom object record. Replace MyObject__c
with your object API name.
Id recordId = 'a0Nxx0000001Abc';
Id userId = '005xx000001Xyz';
MyObject__Share shareRow = new MyObject__Share();
shareRow.ParentId = recordId;
shareRow.UserOrGroupId = userId;
shareRow.AccessLevel = 'Edit';
shareRow.RowCause = Schema.MyObject__Share.RowCause.Manual; // or a custom row cause
insert shareRow;
Apex-managed sharing vs manual sharing
Apex-managed sharing is created and maintained by Apex code. Manual shares are created by users via the UI (those are visible and can be modified by users). Apex-managed shares usually use a custom RowCause (configured in Setup for custom objects) and are typically removed/updated by your Apex logic.
Best practices
- Use Apex-managed sharing reasons (RowCause) for custom objects to differentiate your programmatic shares from manual ones.
- Batch DML operations to avoid hitting DML limits. Use bulkified code (process lists of records, not single inserts in loops).
- Keep ownership model in mind — if you can solve access with ownership changes or sharing rules, prefer declarative approaches for maintainability.
- Provide cleanup logic — when access should be revoked, delete the specific share rows created by your code.
- Write comprehensive tests that verify share rows are created with correct AccessLevel and RowCause.
Considerations and limits
- Apex runs in system context by default (unless declared with ‘with sharing’), so your code can create share rows even if the invoking user wouldn’t normally have the UI permissions — but you should design responsibly and follow least-privilege principles.
- RowCause values depend on the object: custom Apex sharing reasons are available for custom objects and must be defined in Setup.
- Sharing recalculation may be necessary in complex orgs; be aware of sharing recalculation impacts for large data volumes.
- Some objects have specific constraints on sharing; always verify the object supports sharing and the correct share object name.
Testing example
In your test class, create test users and records, then assert that the expected share rows exist with the proper AccessLevel and RowCause.
@isTest
static void testApexSharing() {
// Setup test data: create a user, record etc.
// Run the sharing code
// Query the MyObject__Share table and assert the share exists
}
Summary: Apex sharing gives developers precise programmatic control over record-level access by creating or deleting share rows in share tables. It’s powerful for complex security scenarios but should be implemented carefully with bulkification, proper RowCause usage, and cleanable share records.
Leave a Reply