These keywords on a class declaration control how Apex enforces the org's sharing rules when querying or updating data.
`with sharing` — Apex respects the running user's sharing rules. SOQL only returns records the user can see; DML respects their edit access.
apex public with sharing class CustomerController { ... }
Use for: code invoked from a user context where data privacy must be enforced — Visualforce/LWC controllers, REST services called by users.
`without sharing` — Apex ignores the running user's sharing rules. SOQL returns all records; DML can modify anything.
apex public without sharing class SystemUtility { ... }
Use for: code that legitimately needs system-level access regardless of who invoked it — system maintenance, calculations across all records, integration handlers running as integration users that have View All Data anyway.
`inherited sharing` — Apex uses whatever sharing context the caller declared. If called from a with sharing class, runs with. If called from without sharing, runs without. If invoked from outside Apex (top-level), defaults to with sharing.
apex public inherited sharing class DataProcessor { ... }
Use for: utility classes that should respect their caller's intent, not impose their own.
Default behaviour (no keyword) — depends on context:
- Triggers: typically run
with sharing. - Visualforce/LWC controller methods: run with the page's controller's sharing setting.
- Anonymous Apex /
executeAnonymous: runs with system-level access.
Best practice: be explicit. Default classes should declare a sharing keyword so behaviour is deliberate, not accidental.
