With sharing without sharing in Apex are keywords that control whether your Apex code respects the current user’s record-level security or runs with administrative privileges. These keywords define the security context for your classes and determine which records are accessible during execution.
What is With Sharing in Apex?
The with sharing keyword enforces the current user’s sharing rules, organization-wide defaults (OWD), role hierarchy, and manual sharing settings. When a class uses with sharing, it can only access records that the running user has permission to view or modify.
public with sharing class AccountService {
// This method respects user's sharing rules
public static List<Account> getUserAccounts() {
// Only returns accounts the current user can access
return [SELECT Id, Name FROM Account LIMIT 100];
}
}
In this example, the SOQL query returns only accounts visible to the current user based on their profile, role, and sharing rules.
What is Without Sharing in Apex?
The without sharing keyword bypasses all record-level security. Classes marked without sharing run in system context, accessing all records regardless of the user’s permissions. This is equivalent to running as a system administrator.
public without sharing class SystemAccountService {
// This method ignores user's sharing rules
public static List<Account> getAllAccounts() {
// Returns ALL accounts in the org
return [SELECT Id, Name FROM Account LIMIT 50000];
}
}
Security Warning: Use without sharing carefully. It can expose sensitive data to users who shouldn’t have access.
What is Inherited Sharing in Salesforce?
Inherited sharing is the default behavior when no sharing keyword is specified. The class inherits the sharing context from its caller:
- If called from a with sharing context, it enforces sharing rules
- If called from a without sharing context, it ignores sharing rules
- If called from a trigger or anonymous Apex, it runs without sharing
// No sharing keyword = inherited sharing
public class InheritedSharingService {
public static void processAccounts() {
// Sharing behavior depends on the calling context
List<Account> accounts = [SELECT Id FROM Account];
}
}
Default Apex Class Sharing Behavior
When no sharing keyword is declared, Apex classes follow these rules:
| Context | Default Behavior | Reason |
|---|---|---|
| Trigger | Without sharing | System-initiated operations |
| Anonymous Apex | Without sharing | Administrative context |
| Visualforce Controller | With sharing | User-facing operations |
| REST/SOAP Web Service | Without sharing | API context |
| Batch/Queueable/Schedulable | Without sharing | System context |
Security and Sharing in Salesforce: Best Practices
When to Use With Sharing
- User-facing operations (Visualforce controllers, Lightning components)
- Data access that should respect user permissions
- Reports and dashboards functionality
- Any code where data visibility matters for compliance
When to Use Without Sharing
- System maintenance operations
- Data integration processes
- Audit trail creation
- Cross-object updates that require elevated access
Production Security Considerations
public with sharing class SecureAccountController {
// Always validate user permissions explicitly
public static List<Account> getAccountsWithValidation() {
if (!Schema.sObjectType.Account.isAccessible()) {
throw new SecurityException('Insufficient permissions');
}
return [SELECT Id, Name FROM Account
WHERE OwnerId = :UserInfo.getUserId()
LIMIT 100];
}
}
Visualforce Page with Custom Controller Example
Here’s how sharing keywords affect Visualforce controllers:
public with sharing class AccountViewController {
public List<Account> accounts { get; set; }
public AccountViewController() {
// Respects user's account visibility
accounts = [SELECT Id, Name, Industry
FROM Account
ORDER BY Name
LIMIT 50];
}
public PageReference saveAccount() {
try {
// Insert/update respects user's create/edit permissions
upsert accounts;
return null;
} catch (DmlException e) {
ApexPages.addMessage(new ApexPages.Message(
ApexPages.Severity.ERROR,
'Error: ' + e.getMessage()
));
return null;
}
}
}
The corresponding Visualforce page:
<apex:page controller="AccountViewController">
<apex:form>
<apex:pageBlock title="My Accounts">
<apex:pageBlockTable value="{!accounts}" var="acc">
<apex:column value="{!acc.Name}"/>
<apex:column value="{!acc.Industry}"/>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
</apex:page>
Common Sharing Context Scenarios
Mixed Sharing in Class Hierarchies
public with sharing class ParentService {
public void userOperation() {
// Runs with sharing
ChildService.systemOperation();
}
}
public without sharing class ChildService {
public static void systemOperation() {
// Runs without sharing despite parent context
List<Account> allAccounts = [SELECT Id FROM Account];
}
}
Governor Limits and Sharing
Sharing keywords don’t affect governor limits, but they impact query selectivity:
public with sharing class OptimizedQuery {
public static List<Account> getRecentAccounts() {
// With sharing: query is automatically filtered by user access
// This may improve performance by reducing result set
return [SELECT Id, Name
FROM Account
WHERE CreatedDate = LAST_N_DAYS:30
AND OwnerId = :UserInfo.getUserId()
LIMIT 10000];
}
}
Frequently Asked Questions
What happens if I don’t specify with sharing or without sharing in Apex?
The class uses inherited sharing, meaning it adopts the sharing context of whatever calls it. If called from a trigger or anonymous Apex, it runs without sharing. If called from a Visualforce controller, it runs with sharing.
Can I change sharing context within the same class?
No, sharing keywords apply to the entire class. To mix sharing contexts, create separate classes with different sharing declarations and call between them.
Do sharing keywords affect field-level security (FLS)?
No, sharing keywords only control record-level access. Field-level security must be enforced separately using Schema.DescribeFieldResult.isAccessible() or Security.stripInaccessible().
What is the difference between inherited sharing and with sharing?
With sharing always enforces user sharing rules regardless of calling context. Inherited sharing changes behavior based on the caller – it may run with or without sharing depending on what invoked it.
How do sharing keywords work in test classes?
Test classes run in system context by default (without sharing). Use System.runAs() to test with sharing behavior, or create test data with specific user ownership to verify sharing rule enforcement.
Can triggers use with sharing or without sharing keywords?
No, triggers cannot use sharing keywords directly. They always run without sharing. However, classes called from triggers can use sharing keywords to control their execution context.