We have apex sharing all over our project. When we developed and tested it in a Developer sandbox everything went nice and smooth. Now, in full sandbox this apex sharing seems to be the bottleneck. It just takes waaaaay to long to insert a single share record.

Copypaste from debug log:

10:36:05.0 (738649900)|DML_BEGIN|[150]|Op:Insert|Type:AccountShare|Rows:1
10:36:17.159 (12159588081)|DML_END|[150]

As you can see, insert of 1 AccountShare record takes 12 seconds. And that's not the slowest.

So the question is:
What exactly is happening when a share record is inserted? Is there some huge process behind the scenes that also recalculates all child records sharing(in case of Master-Detail)?

We do not have any triggers(I think that it's not even possible) on these records.

  • When you insert an AcchoutShare record you can specify the access level for the related: opportunities, Contacts, Cases, what values are you giving to those fields ?
    – ihssan
    Jan 30, 2017 at 13:29

1 Answer 1


What exactly is happening when a share record is inserted? Is there some huge process behind the scenes that also recalculates all child records sharing(in case of Master-Detail)?

Depending on the sharing model you're using, there's AccountOwnerSharingRule and AccountShare. Additionally there might also be OpportunityShare, a ContactShare and a CaseShare. Each of Record has a RowCause associated with it. There's a Record Sharing Table that get's created which must be updated for all records and the sharing recalculated when you add sharing.

Apex sharing reasons can be retrieved describing the custom object's sharing object, and examining the information in the rowCause field. The name of a sharing object for each custom object is of the form: MyObjectName__Share, similar to AccountShare and other standard object sharing objects.

Here's an example of a sharing query and code to create a new share programmatically.

QueryResult result = conn.query("SELECT Id FROM Account WHERE OwnerId = '005D0000001LPFB'");
// Create a new AccountShare object
List<AccountShare> shares = new ArrayList<AccountShare>();
for (SObject rec : result.getRecords()) {&nbsp;&nbsp;
&nbsp;    AccountShare share = new AccountShare();
    //Set the portal user Id to share the accounts with
conn.create(shares.toArray(new AccountShare[shares.size()]));

Sharing is best done asynchronously because it's not a quick operation. Quite often, all the sharing on an object record will need to be recalculated. Why? A user will often already have certain permissions to access a record. That of course depends on the current sharing model. Since permissions are additive, as opposed to being restrictive, the code must determine whether the new sharing opens up permissions for a user or attempts to restrict them. If the latter, it may not apply the rules if a profile provide higher permissions than a user already has, or if the rules may only apply to a part of the the default permissions a user already has. Ultimately, these issues need to resolved, which takes time to do.

BTW, if you're using Apex Sharing, you can expect that very likely do have triggers involved in doing the work for you. Your triggers would be initiating the work, might be doing all of it for you, but most likely are calling some kind of class to do it in the background asynchronously. That's why they call it "Apex Managed Sharing", because it requires Apex code to run to do the work.

  • Hard-coded ids? Really?
    – Adrian Larson
    Jan 30, 2017 at 15:02
  • That was copy/pasted from the Object Reference docs. Is how to query and add a single sharing record. Not how you'd do this programmatically in production.
    – crmprogdev
    Jan 30, 2017 at 15:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .