Apex Sharing Context in Salesforce: A Practical Guide for Secure and Scalable Implementations
- 4 hours ago
- 3 min read
In Salesforce, security is not optional—it is architectural. One of the most misunderstood (and misused) aspects of Apex development is sharing context. Many Salesforce implementations fail security audits, leak data, or behave unpredictably, not because of missing features, but because sharing rules were assumed rather than explicitly enforced.
At Winobell, we often encounter Salesforce orgs where Apex code unintentionally bypasses record visibility, leading to compliance risks, data exposure, and inconsistent user experiences. This article explains how Apex sharing really works, why defaults are dangerous, and what best practices enterprises should follow to build secure, future-proof Salesforce solutions.

Understanding Apex Sharing Context: The Basics
By default, all Apex classes run in without sharing mode unless a sharing declaration is explicitly specified. This default behavior is powerful—but risky.
Sharing context in Apex controls record-level access only. It does not automatically enforce:
Object-level permissions (CRUD)
Field-level security (FLS)
These must always be handled explicitly using:
Schema.sObjectType permission checks
WITH SECURITY_ENFORCED in SOQL
User-mode DML where applicable
Relying on defaults is one of the most common root causes of Salesforce security issues.
Apex Sharing Keywords Explained
with sharing
Enforces the organization’s sharing rules for the current user
Users can only access records they are entitled to see
Applies record-level security only
Recommended for most user-facing business logic
Best suited for:
UI controllers (LWC, Aura)
Business services invoked by end users
Data access layers where visibility matters
without sharing
Ignores record-level sharing rules
Allows access to all records, regardless of user visibility
Still respects object permissions unless bypassed explicitly
Best suited for:
System-level operations
Background processing
Administrative or data correction logic
⚠️ Use sparingly. Overuse creates hidden security risks.
inherited sharing
The class inherits the sharing context of the calling code
Allows the same class to behave differently based on how it is invoked
If no sharing is declared, Apex defaults to without sharing
Best suited for:
Shared utility or service classes
Logic reused across UI, batch, REST, and triggers
Large enterprise orgs with layered architectures
Apex Entry Points and Their Default Sharing Behavior
Different Apex entry points apply different default sharing contexts:
Apex Entry Point | Default Sharing |
Aura component controller | with sharing |
@AuraEnabled method (LWC) | with sharing |
Visualforce controller | without sharing |
Apex REST service | without sharing |
Asynchronous Apex (Batch, Queueable, Future, Scheduled) | without sharing |
Other Apex entry points | without sharing |
Important: The calling context is only honored if the called class is declared as inherited sharing.
Why Explicit Sharing Declaration Is Critical
When sharing is not declared:
Code behavior becomes unpredictable
Security issues surface only during audits or incidents
Future enhancements can unintentionally expose data
Salesforce security audit fails
Explicit sharing declarations:
Make intent clear
Improve maintainability
Reduce regression risks
Align code with Salesforce’s Secure by Design principles
Winobell’s Recommendations
For New Apex Classes
Always declare sharing explicitly at creation time:
Default to with sharing
When unsure
For user-driven operations
Use inherited sharing
For reusable service or utility classes
When behavior should depend on the caller
Use without sharing
Only when business logic truly requires unrestricted access
Rule of thumb: If you must ask “should this bypass sharing?”—it probably shouldn’t.
For Existing Apex Classes
Introducing sharing into legacy code is not risk-free:
Existing logic may rely on unrestricted access
Automation and integrations may break
Regression testing is mandatory
Best approach:
Introduce sharing incrementally
Apply during enhancements or refactoring
Validate downstream automation, integrations, and reports
At Winobell, we often include this as part of a Salesforce ROI Recovery or Security Hardening engagement.
Apex Triggers and Sharing: What Architects Must Know
Triggers always run in without sharing by default
If a trigger calls an Apex class:
The class runs according to its declared sharing
If a trigger fires due to a CRUD operation:
User-mode DML (as user) → trigger runs with sharing
System-mode DML → trigger runs without sharing
If a trigger is invoked by a with sharing Apex class:
The trigger inherits with sharing
Sharing vs Security: A Common Misconception (Sharing ≠ Security)
To build secure Apex:
Use with sharing or inherited sharing
Enforce CRUD using Schema.describe
Enforce FLS using WITH SECURITY_ENFORCED
Prefer user-mode DML and queries where possible
Never assume UI-level security applies to Apex
Final Thoughts
Salesforce provides powerful security tools—but it is up to architects and developers to use them correctly. The safest Apex code is explicit, intentional, and defensive.
At Winobell, we help organizations:
Identify insecure Apex patterns
Refactor legacy code safely
Pass Salesforce security reviews
Restore trust and ROI from underperforming Salesforce implementations
Key takeaway:
Never rely on defaults. Explicit sharing + explicit security enforcement leads to predictable, scalable, and compliant Salesforce solutions.
👉 Talk to a Winobell Salesforce expert. Schedule a free 30-minute discovery call with our team by emailing us at support@winobell.com or call us at +1 (437) 253-5469




Comments