The premise is half-right and that’s exactly why the question is good. Yes — when Apex runs as an entry point without any keyword, it defaults to without sharing. But the moment you’re inside a with sharing call chain, that context propagates to every called class with no keyword. To break out of an enforced-sharing context, you need to explicitly mark a downstream class without sharing. That’s why the keyword exists — for the deliberate, audited opt-out.
The propagation rule
Sharing context propagates down the call stack:
- A class with
with sharing→ all classes it calls without their own keyword inheritwith sharing. - A class with
without sharing→ all classes it calls without their own keyword inheritwithout sharing. - A class with
inherited sharing→ adopts the caller’s context. - A class with its own explicit keyword wins over the caller’s context.
So inside a controller marked with sharing, every helper class without its own keyword also runs with sharing — even though its standalone default (as an entry point) would have been without sharing.
When without sharing is the right answer
Specific scenarios where you legitimately want to bypass sharing:
- Apex sharing logic. The class that inserts
*__Sharerows on behalf of the running user. The running user usually doesn’t have access to all the records they’re sharing — so the class must run without sharing to perform its job. - Aggregations and rollups. Computing totals across records the user can’t see (e.g., a count of related cases for a manager dashboard).
- Privileged operations. A “find duplicate accounts” job that must scan every account regardless of who owns them.
- Integration callbacks. Inbound API operations that legitimately need to see all data (e.g., a partner integration syncing all orders).
- System callouts initiated on behalf of a low-privilege user. Where the user is invoking a tightly-scoped operation that needs elevated read.
In all of these, you’d mark the specific helper class without sharing while keeping the outer controller with sharing. The outer class enforces sharing on user-facing reads; the inner helper deliberately escapes it for one specific purpose.
Anti-pattern: blanket without sharing
Marking your entire codebase without sharing because “it just works” is a common security violation. Code review and security review (for AppExchange packages) will flag it. The correct pattern is:
- Mark controllers and entry points
with sharing(orinherited sharingfor reusable code). - Mark specific utility classes that genuinely need bypass
without sharing— and document why in a class-level comment.
A worked example
public with sharing class OrderController {
@AuraEnabled
public static OrderSummary summary(Id orderId) {
// 1. Read the order — must enforce sharing
Order o = [SELECT Id, Status, AccountId FROM Order WHERE Id = :orderId];
// 2. Compute the account-wide order total — needs to see ALL orders
Decimal totalAcrossAllOrders = OrderTotalService.computeTotalForAccount(o.AccountId);
return new OrderSummary(o, totalAcrossAllOrders);
}
}
public without sharing class OrderTotalService {
// Deliberate bypass: we want the true account total even if the
// running user can't see every order on the account.
public static Decimal computeTotalForAccount(Id accountId) {
AggregateResult ar = [
SELECT SUM(TotalAmount) total
FROM Order
WHERE AccountId = :accountId
];
return (Decimal) ar.get('total');
}
}
The controller enforces sharing on the user-visible order read. The aggregation helper opts out only for the computed total. The user can’t infer which orders they couldn’t see — just gets the rolled-up number.
Common interview follow-ups
- What about
inherited sharing? The cleaner modern keyword for reusable callees that should follow the caller. Use it instead of “no keyword” to make intent explicit and to default entry-point invocations towith sharing. - Does
without sharingbypass FLS and CRUD too? No.without sharingonly ignores record-level sharing. FLS and CRUD are enforced separately — you needSecurity.stripInaccessible()orWITH SECURITY_ENFORCEDfor those.
Verified against: Apex Developer Guide — Using the with sharing, without sharing, and inherited sharing Keywords. Last reviewed 2026-05-17.