Use owner-based rules when access follows who owns the record, and criteria-based rules only when it genuinely follows a field value. Owner-based rules recalculate when ownership or group membership changes. Criteria-based rules recalculate whenever the criteria field changes on any record, so putting one on a field your automation updates daily is the expensive choice, and you are limited to 50 of them per object anyway.
The four mechanisms, side by side
| Keys off | Survives owner change | Limit | Who can create it | |
|---|---|---|---|---|
| Owner-based rule | Record owner’s role, group, or territory | Yes — recalculates to the new owner | 300 per object, shared with criteria-based | Admin, Manage Sharing |
| Criteria-based rule | Field values on the record | Yes — ownership is irrelevant to it | 50 per object, shared with guest user rules | Admin, Manage Sharing |
| Manual sharing | An explicit act by the owner | No — deleted on owner change | None documented | Record owner, or anyone with Full Access |
| Apex managed sharing | Whatever your code decides | Yes, with a custom row cause | None documented | Modify All Data only |
The two right-hand columns are where the real decision lives. Manual sharing looks like the easy answer until the account gets reassigned and every share silently disappears. Apex managed sharing solves that and costs you a deployment plus a permission almost nobody should hold.
What each rule type actually matches on
An owner-based rule has a source and a target: in the metadata it is sharedFrom, which the Metadata API describes as specifying the record owners, and sharedTo, the recipients. Both are groups, roles, or territories. The rule says “records owned by anyone in here become visible to everyone in there.”
A criteria-based rule replaces the source with criteriaItems (“an array of the boolean criteria (conditions) for the sharing rule”) plus an optional booleanFilter. Ownership plays no part. It asks a question about the record itself.
First check your field is eligible. Sharing Rule Considerations rules out four categories, and they are the four people most want to use:
- Lookup fields
- Formula fields
- Encrypted fields
- Fields with derived values
No formula fields is the one that ends most designs. “Share the record when the parent account’s segment is Enterprise” is not expressible as a criteria-based rule, because reaching the parent’s field means either a formula or a lookup. The standard workaround is a real field on the child, populated by automation, which is exactly the pattern that makes criteria-based rules expensive, as below.
Two smaller traps. Criteria on record type use the record type label, not the developer name, so duplicated or translated labels break the rule quietly. And Apex cannot create or test criteria-based sharing rules at all, which means this part of your sharing model has no automated test coverage available to it. Plan a manual verification step instead of assuming you can assert it.
How they layer with OWD and the role hierarchy
Sharing rules only ever add. The documentation says it three ways: a rule “can never be stricter than your org-wide default settings”; “you can use sharing rules to grant wider access to data — you can’t restrict access below your organization-wide default levels”. And when multiple grants apply, “Salesforce uses the most permissive grant when determining record access.”
Which produces a prerequisite people discover late: sharing rules require the OWD set to Public Read Only or Private. On a Public Read/Write object there is nothing left to grant, so the feature has no work to do.
The role hierarchy then compounds on top. Sharing with a role reaches the users in that role plus everyone above them, and for standard objects you cannot switch that off — Grant Access Using Hierarchies is deselectable for custom objects only. The practical reach of any rule targeting a role is the whole branch above it, which is usually more people than whoever requested the rule had in mind.
The limits, and which one bites first
300 total sharing rules per object, of which at most 50 can be criteria-based or guest user rules. The 50 is what you actually run out of. Owner-based rules tend to be few and structural (a handful per role branch) while criteria-based rules multiply, because every new business exception looks like it deserves one.
Four more constraints shape a design. Guest user sharing rules can only grant Read — the Metadata API is explicit that “for SharingGuestRule, the accessLevel field can be set only to Read.” High-volume community and site users cannot be included in owner-based rules at all, since they have no role and cannot join public groups. Reach them with criteria-based or guest user rules instead.
Then two editing quirks that cost you a recalculation each. Creating an owner-based rule with the same source and target as an existing one overwrites it rather than adding a second. And the “Share with” target cannot be changed after the rule is saved — a wrong target means delete and recreate, so the recalculation runs twice. Note too that not every object supports criteria-based rules: product requests, product transfers, service contracts, service crews, shipments, time sheets, and user provisioning requests are owner-based only.
Why criteria-based rules on volatile fields are the expensive choice
Be aware of what is and isn’t documented here. Salesforce documents that changing sharing rules “requires processing potentially large record volumes,” queued with an email on completion. It does not publish a cost model for recalculating a criteria-based rule as its criteria field churns across many records, so treat what follows as reasoning from the mechanism, not a documented figure.
The mechanism: record access is precomputed. Record-Level Access: Under the Hood states that Salesforce calculates record access data only when configuration changes occur, storing grants as sharing rows. A criteria-based rule is therefore not a query-time filter — it is a standing instruction to maintain sharing rows for whichever records currently match. Change the criteria field and rows are inserted or deleted for every user and group the rule targets.
So the cost scales with how often the field changes multiplied by how many principals the rule grants to. A criteria-based rule on a stable field (Country, Record Type, a segment set at creation) is cheap, because the rows are written once. The same rule on Stage, on a rollup-driven field, or on anything a nightly integration touches is doing continuous sharing-row maintenance, and it is doing it on a role target that fans out to the whole branch above.
Two consequences. If sharing must follow a volatile value, consider whether ownership can carry the signal instead — an assignment rule that reassigns the owner plus an owner-based sharing rule moves the work onto a single well-understood recalculation path. And for a bulk realignment, use deferred sharing maintenance: suspend sharing rule and group membership calculations, resume during a maintenance window, and note that deferring group membership defers sharing rules too, while deferral “doesn’t defer the recalculation of some sharing changes in order to preserve data integrity.”
Manual sharing: the escape hatch that expires
Manual sharing is the right answer for genuine one-offs. A specific deal a specific specialist needs to see once. The Share button writes a row with row cause Manual, and for standard objects that is the only row cause you are permitted to touch: “you can only create, edit, and delete sharing entries for standard objects whose RowCause field is set to Manual.”
Its cost is stated plainly in the Apex Developer Guide. User managed sharing “is removed when the record owner changes.” That is the whole problem with using it as a pattern: every manual share is a grant with an undocumented expiry date attached to a reassignment nobody will connect to the resulting ticket.
Two more constraints. The access level “must be set to an access level that’s higher than the organization’s default access level for the parent object,” so there is nothing to grant on a Public Read/Write object. And “objects on the detail side of a master-detail relationship don’t have an associated sharing object”. You cannot manually share a detail record at all. Share the parent.
Apex managed sharing: durable, and expensive in a different way
Apex managed sharing exists to fix manual sharing’s fragility. You insert rows into the share object (AccountShare for standard objects, MyObject__Share for custom ones) with four fields: ParentId, UserOrGroupId, AccessLevel, and RowCause.
List<Deal_Review__Share> shares = new List<Deal_Review__Share>();
for (Deal_Review__c dr : reviews) {
Deal_Review__Share s = new Deal_Review__Share();
s.ParentId = dr.Id;
s.UserOrGroupId = dr.Reviewer__c;
s.AccessLevel = 'Edit';
s.RowCause = Schema.Deal_Review__Share.RowCause.Review_Panel__c;
shares.add(s);
}
Database.insert(shares, false);
The payoff is the row cause. With a custom Apex sharing reason, the guide confirms the share is maintained even when the record owner changes or a user is deactivated. That is the durability manual sharing lacks.
Now the costs, and there are four.
Custom objects only. “Apex sharing reasons and Apex managed sharing recalculation are only available for custom objects.” On standard objects you can still write share rows, but with a built-in row cause and no custom reason to protect them.
Modify All Data. “Only users with ‘Modify All Data’ permission can add or change Apex managed sharing on a record.” Since that permission bypasses your entire sharing model, the running user has to be a system context you control, not the end user.
You now own recalculation. The platform recalculates its own rules. It does not recalculate yours. You write a Database.Batchable recalculation class, and it runs when the custom object’s OWD changes or when you invoke it. Sharing that drifts out of sync with your business rules is a class of bug that only exists once you take this on.
It is code in your security model. A sharing rule is visible in Setup to anyone reviewing access. An Apex share is visible only to someone reading the class. Document it where an auditor will look.
Rule of thumb: exhaust declarative options first, and reach for Apex managed sharing only when the requirement genuinely cannot be expressed as ownership or a stable field value. A per-record panel of named reviewers is the classic legitimate case. Using it to avoid designing a role hierarchy is how orgs end up with sharing logic nobody can explain.
Frequently asked
How many sharing rules can I have per object?
300 in total, of which at most 50 can be criteria-based or guest user rules. Salesforce Support can raise the total for some orgs, but plan against these numbers rather than the increase.
Can a sharing rule restrict access?
No. Sharing rules only grant, and can never take access below the org-wide default. The feature that narrows access within what a user can already see is restriction rules, which is a separate mechanism.
Why can’t I use my formula field in a criteria-based rule?
Criteria-based rules cannot use formula fields, lookup fields, encrypted fields, or fields with derived values. The usual workaround is a real field kept up to date by automation. Accepting that you have now made the rule recalculate every time that field is written.
Do sharing rules apply to records owned by inactive users?
Yes. Rules apply to both active and inactive users, and to all new and existing records matching the definition. Deactivating a user does not withdraw the access their records were granting.
Will a manual share survive if I change the record owner?
No. User managed sharing is removed when the record owner changes. If the grant needs to outlive a reassignment, it has to be a sharing rule or Apex managed sharing with a custom row cause.
Reference: Sharing Rules and Sharing Rule Considerations (Salesforce Help), SharingRules and SharingReason (Metadata API Developer Guide), Understanding Sharing, Sharing a Record Using Apex and Recalculating Apex Managed Sharing (Apex Developer Guide), and Deferred Sharing Calculations.