Briefly: sharing recalculation is the platform rebuilding the rows that record who can see what. It runs when you change something structural, it can take hours on a large org, and while it runs you may see row locks and users may see records appear or disappear. The cost scales with how concentrated your ownership is, which is why skew matters.
What triggers it
Not record edits. Structural changes:
- Changing an org-wide default, in either direction
- Creating, editing or deleting a sharing rule
- Moving a user in the role hierarchy
- Changing a role’s parent
- Adding or removing users from a public group used in sharing rules
- Transferring ownership of many records
- Enabling or changing territory assignment
The pattern is that each of these changes who should see what, and the platform has to work out the difference and write it down. Sharing is stored, not computed at read time, which is why queries are fast and changes are slow.
Why it takes so long
The work is proportional to affected records multiplied by affected users. A sharing rule granting a group of 200 users access to 500,000 records is a hundred million potential rows to evaluate.
Two org properties make it worse:
Ownership skew. One user owning 400,000 records means any change to that user’s position recalculates all of them, in one operation. This is the main reason skew matters, and it is why integration users should sit outside the role hierarchy.
Deep role hierarchies. Every level above an owner gets access through the hierarchy, so a ten-level hierarchy multiplies the rows per record. Depth costs more than width.
What users see while it runs
This is the part worth warning people about. During recalculation, access is being rewritten, so a user may briefly not see a record they should, or see one they should not. Reports return different numbers on consecutive runs.
It is not corruption and it resolves. It is also indistinguishable from a bug if nobody told the support desk it was happening, which is how a planned change becomes an incident ticket.
The locking problem
Recalculation holds locks on the records it is updating. A data load touching the same records gets UNABLE_TO_LOCK_ROW, and the error points at your load rather than at the recalculation, so the diagnosis goes in the wrong direction.
The rule: do not run a bulk load while a structural sharing change is processing. Check that the recalculation has finished before starting, and if you are doing both in one weekend, sequence them deliberately.
Reducing the cost
- Take integration users out of the role hierarchy. The highest-value single change, and it removes most of the hierarchy recalculation for the records they own.
- Use queues rather than users for unassigned work, since queue ownership does not carry the same hierarchy cost.
- Keep the hierarchy shallow. Roles exist for record access, not to mirror the org chart. Every unnecessary level costs on every recalculation.
- Batch structural changes into one window rather than making five over five days, each triggering its own pass.
- Prefer permission sets over sharing rules where the requirement is really about capability rather than specific records.
Doing it safely
For a change you know is large: pick a low-usage window, tell the support desk, avoid concurrent data loads, and open a case with Salesforce Support beforehand if the org is big. Support can run a recalculation as a controlled background job and advise on timing, and they would rather hear from you before than after.
Deferred sharing calculation exists for exactly this. It lets you suspend recalculation during a large change and resume it afterwards, which turns many passes into one. It is not enabled by default and it needs Support to turn on, and for a large migration it is worth the request.
Frequently asked
How do I know when it has finished? There is no clean progress indicator. Setup shows some background job activity, and Support can see the detail. Watch for the symptoms stopping.
Does it affect queries? Reads stay fast. Sharing is stored. What changes is which rows come back while the rewrite is in progress.
Can I avoid it entirely? Only by not changing the sharing model. An org with a Public Read/Write default has almost nothing to recalculate, which is one of the underrated advantages of a simple model.
