---
title: "Manual shares and Apex managed sharing"
url: "https://trailassembly.com/manual-sharing-and-apex-sharing/"
topic: "Admin and Permissions"
published: "2026-09-20T11:01:41+00:00"
updated: "2026-10-06T13:59:37+00:00"
---

# Manual shares and Apex managed sharing

**The short version:** every sharable object has a shadow object holding one row per grant, and both manual shares and Apex managed sharing write rows to it. The difference is the RowCause. A manual share is deleted the moment the record changes owner. A share written with a custom Apex sharing reason survives, which is the only reason Apex managed sharing exists.

## The share object

For a custom object `Project__c` the share object is `Project__Share`. For standard objects it is `AccountShare`, `OpportunityShare`, `CaseShare` and so on. The field names differ between the two families, which trips up code written against one and reused on the other.

- **Custom objects:** `ParentId`, `UserOrGroupId`, `AccessLevel`, `RowCause`.

- **Standard objects:** a named parent field such as `AccountId`, plus access fields named after the object, for example `AccountAccessLevel`. `AccountShare` also carries `OpportunityAccessLevel`, `CaseAccessLevel` and `ContactAccessLevel`, because account access drags children with it.

## RowCause is the field that matters

RowCause records why the grant exists. `Owner`, `Manual`, `Rule`, `ImplicitChild`, `ImplicitParent`, `Team` and `Territory` are the ones you will see. You can query them all, but you can only insert and delete rows for causes the platform lets you control.

A row with RowCause `Manual` is what the Sharing button creates, and what Apex creates by default. The platform deletes those rows automatically whenever the record’s owner changes. That is not a bug. It is the reason the next section exists.

## Apex managed sharing

On a custom object you can define an Apex sharing reason in the object setup, giving you a RowCause of your own such as `Project_Team__c`. Rows written with that cause are preserved through owner changes and are not touched by sharing recalculation, because the platform treats them as yours to maintain.

```apex
Project__Share s = new Project__Share();
s.ParentId = projectId;
s.UserOrGroupId = userId;
s.AccessLevel = 'Edit';
s.RowCause = Schema.Project__Share.RowCause.Project_Team__c;
Database.SaveResult sr = Database.insert(s, false);
```

Two constraints. Apex sharing reasons are available on custom objects only, so on Opportunity or Case your code is writing manual shares and inheriting their fragility. And adding, editing or deleting rows with a custom sharing reason requires Modify All Data, which means the code doing it runs in a context that holds that permission.

## Recalculation is your job now

Because the platform will not rebuild your Apex managed shares, you have to. That means a Batchable class registered against the object as an Apex sharing recalculation class, which reads the source of truth and rewrites the share rows.

Write it before you need it. Shares drift for boring reasons: a bulk load bypassed the trigger, a deployment disabled it briefly, someone changed the driving field through the API.

## Writing and deleting shares safely

- Use `Database.insert(shares, false)` and inspect the results. Duplicate share rows produce errors you usually want to ignore rather than abort on.

- Delete by querying the share object with your RowCause and the parent Ids, then deleting. Never delete rows with RowCause `Owner`, `Rule` or either implicit cause.

- A user can hold several rows for one record. Access is the most permissive of them, so removing one row does not necessarily remove access.

- Do this from an after-insert or after-update trigger. Before-insert has no record Id to share.

- Bulkify. One share row per record per user adds up fast, and share table volume is a real contributor to sharing recalculation times.

## When to use which

Manual shares are for people, on individual records, as an exception. If you find them being created programmatically to implement a rule, that rule belongs in a sharing rule or in Apex managed sharing.

Apex managed sharing is for access that follows a relationship the declarative model cannot express: team membership held in a junction object, an approval chain, a rule spanning two objects. It is code you own forever, so try criteria-based sharing rules first.

## Frequently asked

**Why did my shares disappear?** Almost always an owner change on rows with RowCause `Manual`. Check whether the code is using a custom Apex sharing reason.

**Can I see implicit shares in the share object?** You can query them. You cannot insert, edit or delete them, and there is no setting that turns them off.

**Do I need Modify All Data for manual shares?** No. A user with Full Access on the record can create a manual share. The Modify All Data requirement applies to rows using a custom Apex sharing reason.

**Does Apex managed sharing work on Account?** Apex sharing reasons do not exist on standard objects, so code there writes manual shares that will not survive an owner change. Design around that rather than discovering it in production.

---

Source: https://trailassembly.com/manual-sharing-and-apex-sharing/
Trail Assembly — independent Salesforce write-ups.
