Skip to main content

SF-0292 · Concept · Hard

What is Apex Sharing?

✓ Verified by Vikas Singhal · Last reviewed 5/17/2026

Apex sharing is the programmatic creation of share records via Apex code — inserting rows into the object’s __Share table to grant specific users or groups access to specific records. It’s used when declarative sharing (OWD + role hierarchy + sharing rules + manual sharing) can’t express the rule your business needs, typically because the rule depends on data relationships, runtime conditions, or external system logic that sharing-rule criteria can’t evaluate.

Why Apex sharing exists

Every object whose OWD is Private or Public Read Only has a corresponding share object — Salesforce auto-generates it. For standard objects it’s named like AccountShare, OpportunityShare, CaseShare. For custom objects it’s MyCustomObject__Share. Every row in the share table grants one user or group access to one record at a specified access level (Read or Edit).

Apex sharing lets you insert rows into that share table from code, giving you a programmatic backdoor for sharing requirements like:

  • Share an opportunity with the related Account’s account team members.
  • Share a custom Project record with everyone who’s listed in a related “Stakeholders” junction object.
  • Share an Order record temporarily with a user during a specific approval step.
  • Share a Lead with users selected by an external matching service.

These rules can’t be expressed in standard sharing-rule criteria because they depend on related records, user lists computed at runtime, or external data.

The share record structure

A row in any *__Share table has four key fields:

FieldWhat it holds
ParentIdThe Id of the record being shared (e.g., the Project__c record)
UserOrGroupIdThe Id of the user, public group, role, role+subordinates, or queue receiving access
AccessLevel (or e.g. OpportunityAccessLevel)Read, Edit, or All (All is reserved for the owner)
RowCauseWhy this share exists — Manual, an Apex-defined sharing reason, or a system reason

Sharing reasons — the key custom feature

For custom objects, you can define Apex Sharing Reasons on the object — labels that let you distinguish your code-created shares from manual shares. This matters because manual shares are removed when ownership of the record changes, but Apex-reason shares with a custom reason can persist across owner changes and be filtered/recalculated as a group.

On standard objects, you must use RowCause = Schema.OpportunityShare.RowCause.Manual (or the equivalent) — standard objects do not support custom Apex sharing reasons.

Minimal code example

public without sharing class ProjectStakeholderSharing {
    public static void shareProjectWithStakeholders(Id projectId, Set<Id> userIds) {
        List<Project__Share> shares = new List<Project__Share>();
        for (Id uid : userIds) {
            Project__Share s = new Project__Share();
            s.ParentId       = projectId;
            s.UserOrGroupId  = uid;
            s.AccessLevel    = 'Edit';
            s.RowCause       = Schema.Project__Share.RowCause.Stakeholder_Access__c;
            shares.add(s);
        }
        Database.SaveResult[] results = Database.insert(shares, false);
        // Inspect results to handle duplicate-share errors gracefully
    }
}

A few production-grade notes:

  • The class is declared without sharing because creating share rows often requires bypassing the running user’s own sharing — the user wouldn’t necessarily have access to the records they’re sharing with others.
  • Use Database.insert(shares, false) (allOrNone = false) so partial successes are allowed — duplicates raise DUPLICATE_VALUE errors you can swallow.
  • The RowCause references an Apex Sharing Reason named Stakeholder_Access defined on the Project__c object in Setup.

When Apex sharing is the right answer

ScenarioRight tool
Share leads in a territory with everyone in that territoryTerritory management
Share all opportunities over $1M with the CFO groupCriteria-based sharing rule
Share an account with everyone in its account teamAccount team (built-in)
Share a custom Project with the related Account’s ownerApex sharing (no declarative path covers this)
Share a record temporarily during one approval stepApex sharing triggered from the approval process
Share a record with an externally computed list of usersApex sharing

Caveats and gotchas

  • Apex sharing does not apply when OWD is Public Read/Write — everyone already has access; share rows are ignored.
  • Manual-reason shares are automatically deleted when record ownership changes. Custom-reason shares on custom objects are not.
  • A user can have multiple share rows pointing at the same record (different reasons). Their effective access is the most permissive (Edit beats Read).
  • Recalculation of shares on owner change or sharing-model change can be expensive; Apex sharing rows are part of that recalc.
  • Apex sharing requires the same care around governor limits as any DML — bulkify, batch where needed.

Verified against: Apex Developer Guide — Sharing in Apex and Apex Managed Sharing. Last reviewed 2026-05-17.