with sharing, without sharing, and inherited sharing
By the end of this lesson, you'll be able to:
- Explain what "sharing" means in a Salesforce record-access context
- Choose the correct sharing keyword for a given class's purpose
- Recognize inherited sharing as the safer default for utility classes
Prerequisites: Module 27: "Project: Leave Management"
A concept foreshadowed, now resolved
Module 20's closing lesson left an open question: whether a plain SOQL query enforces the running user's record-level access depends on the sharing mode of the class it runs in — this module explains exactly what that means. Sharing refers to Salesforce's record-level access model — role hierarchies, sharing rules, manual sharing — that determines which specific records a given user is allowed to see, on top of their object- and field-level permissions.
with sharing: enforce the running user's access
public with sharing class OpportunityService {
public List<Opportunity> getMyTeamOpportunities() {
return [SELECT Id, Name, Amount FROM Opportunity]; // only records this user can see
}
}
public with sharing class OpportunityService {—with sharingmeans the class's queries and DML respect the running user's actual sharing access.public List<Opportunity> getMyTeamOpportunities() {— the method.return [SELECT Id, Name, Amount FROM Opportunity];— a sales rep calling this only ever sees Opportunities they're actually allowed to see, exactly as if they'd run the query themselves through the UI.}— closes the method.}— closes the class.
without sharing: bypass sharing rules deliberately
public without sharing class OrgWideReportingService {
public Integer getTotalOpportunityCount() {
return [SELECT COUNT() FROM Opportunity]; // every Opportunity, regardless of who's asking
}
}
public without sharing class OrgWideReportingService {—without sharingdeliberately bypasses record-level sharing.public Integer getTotalOpportunityCount() {— the method.return [SELECT COUNT() FROM Opportunity];— every query and DML statement in this class sees the entire object's data, not just what the running user could normally access.}— closes the method.}— closes the class.
This is a real, sometimes-necessary tool (an org-wide dashboard, a system integration), but one that needs a genuinely deliberate reason, not a default choice.
inherited sharing: the safer default for shared utility code
public inherited sharing class DateFormatterUtil {
public String formatFriendly(Date d) {
return d.format(); // doesn't touch sharing at all, but declares intent clearly
}
}
public inherited sharing class DateFormatterUtil {—inherited sharingmeans: behavewith sharingwhen called directly, but inherit whatever sharing mode the calling class was already running under when called from somewhere else.public String formatFriendly(Date d) {— the method.return d.format();— doesn't touch sharing at all, but declares intent clearly.}— closes the method.}— closes the class.
For a reusable utility class that might get called from both with sharing and without sharing contexts, this is generally the safest, most predictable default.
Exercise
As a comment, decide which sharing keyword fits a class meant to be called by ordinary sales reps to view their own team's data only.
Show hint
Think about whether this class should ever see data the user couldn't normally access.
with sharing, without sharing, and inherited sharing Quiz
My Notes
Log in to keep private notes on this lesson.
Questions about this lesson
No questions yet — be the first to ask.
Log in to ask a question about this lesson.
Summary
A class's sharing keyword controls whether its code respects the running user's record-level access (like role hierarchy and sharing rules) — with sharing, without sharing, and inherited sharing each answer this differently.