In one sentence: record-triggered flows already run in system context without sharing — they can read and write every record in the org regardless of who saved the record. Screen flows run in user context by default, which is why the flow you built as an admin fails for a sales rep. Setting a flow to “System Context Without Sharing — Access All Data” removes object permissions, field-level security, and record sharing from every operation the flow performs, and that is a permanent grant to anyone who can trigger it.
The three contexts, precisely
The Metadata API calls this the flow’s runInMode, and the three values it can hold are the whole model.
| Context | Object permissions | Field-level security | Sharing and record access |
|---|---|---|---|
| User context (default for screen flows) | Enforced | Enforced | Enforced |
| System context with sharing | Not enforced | Not enforced | Enforced — org-wide defaults, role hierarchy, sharing rules |
| System context without sharing | Not enforced | Not enforced | Not enforced — all data |
The documentation is blunt about the third: in system context without sharing, “the flow can access all data.” The middle option is the one people misread. System context with sharing still respects org-wide defaults, role hierarchies and sharing rules, but not the running user’s object permissions, so a user with no Read access to Contract can have a flow read the Contracts they would have seen if they did have access.
What runs in which context by default
Record-triggered flows (before-save and after-save) run in system context without sharing. This is not a setting you chose and, per Salesforce’s Flow Run Context documentation, not one you can change for this flow type. It is also the correct default: automation that fired only when the saving user happened to have access would produce data that depends on who typed it.
Scheduled and platform event-triggered flows also run in system context without sharing, as the Automated Process user.
Screen flows run in user context. Every Get Records, Create Records and Update Records is subject to the running user’s object permissions, field-level security and sharing. Autolaunched flows depend on how they were launched, which is what the DefaultMode value means — “how the flow is launched determines whether the flow runs in user context or in system context.”
You change it in Flow Builder under the flow version’s advanced settings, where the option is offered for screen and autolaunched flows. In source it is the runInMode element — absent or DefaultMode means the launch method decides. One more failure mode worth knowing: if a user cannot start a flow at all, that is flow access rather than data access, governed by the Run Flows permission and by any override restricting the flow to named profiles or permission sets.
Why the flow works for you and fails for the user
You have View All Data and Modify All Data. Almost nothing in a user-context flow can fail for you, so testing as yourself tells you nothing about whether the flow works.
Signature 1: Get Records returns nothing, and no error appears
The most common and the most misleading. Sharing does not throw an exception. It filters rows. Get Records returns an empty collection, the record variable is null, and the flow carries on. The next Decision takes the wrong branch, or an Assignment on the null variable faults somewhere unrelated to the real cause.
If a flow behaves as though a record does not exist, check record access before checking your filter logic.
Signature 2: insufficient access rights on cross-reference id
The flow is writing a lookup field pointing at a record the user cannot access, or updating a record they hold read-only. The error names the operation, not the record they are missing, so read it as “something in this write refers to data this user cannot touch” and work out which lookup that is.
Signature 3: it fails only on some records
Ownership. The user can see records they own or that their role grants, and not others. A flow that works on the rep’s own opportunities and fails on their colleague’s is a sharing problem, every time.
How to find out in five minutes
Log in as the user. Setup → Users → the user → Login, and reproduce it. Nothing else is as reliable, because it exercises the same permission and sharing evaluation the flow does. With the failure reproduced, check that user’s object permissions, field-level security on the fields the flow writes, and their access to the specific record.
What it costs you to switch it off
Turning on system context without sharing makes the failure stop. It also means the flow is no longer constrained by anything.
The consequence people miss is that the privilege belongs to the flow, not to the operation you had in mind. Salesforce’s own guidance for external-facing flows is direct: “Avoid running flows in system context when possible, and restrict access to subflows.” The reason is in the same document: a user who can run a screen flow “can invoke the flow at any time and with parameters of their choosing,” and can view and modify the flow’s input variables.
Put those two facts together. A screen flow running without sharing that takes a record ID as an input variable, looks the record up and displays fields from it lets any user who can run the flow read any record of that type in the org. The flow’s UI never offers them that choice. The input variable does. The same shape with an Update Records element is a write.
If you need the elevation, keep it narrow:
- Do not trust an input ID. Get the record, then use a Decision to confirm it meets the condition the flow is meant to handle, and stop if it does not.
- Widen access for the smallest unit possible. Keep the screen flow in user context and call an autolaunched flow in system context for the one operation that needs it, rather than running the whole interview without sharing.
- Restrict who can run it. Override the default flow access and grant it through a permission set built for that flow.
- Write down why in the flow’s description. “without sharing because support agents close cases they do not own” is a sentence the next admin needs.
The Apex comparison, because it changed
Apex used to be the permissive one. It is not any more: in API version 67.0 and later, classes without an explicit sharing declaration run in with sharing mode. What has not changed is that sharing declarations “don’t enforce object-level access or field-level security”, that is still on you, through WITH USER_MODE on queries, user-mode DML, or Security.stripInaccessible.
Two consequences for flows. An Apex action invoked from a system-context flow is governed by that class’s own sharing declaration, so it can be more restrictive than the flow that called it. A real cause of “the flow works but the Apex action returns nothing.” And flows have no equivalent of user-mode operations: context is all-or-nothing per flow, decided in advance.
Frequently asked
Do before-save flows respect sharing rules?
No. Before-save and after-save record-triggered flows run in system context without sharing, and that is not configurable for those flow types.
Does system context bypass validation rules and required fields?
No. Context governs permissions and record access, not data integrity. Validation rules, required fields and duplicate rules all still run in the save order, and a flow in system context can absolutely be blocked by a validation rule.
Why does my flow return no records instead of throwing an error?
Because sharing filters query results rather than rejecting the query. Design for it: after every Get Records that matters, check whether the record variable is null and route to a Custom Error or a screen that says something useful.
Should I just set every flow to system context to avoid support tickets?
No, and this is the tempting mistake. You would be removing the security model from every automated path in the org to save yourself permission work. Fix the permission (the user probably needs that access for their job anyway), and reserve elevation for the cases where the business genuinely wants a user to act beyond their own access.
Reference: Flow, Metadata API Developer Guide; Flow Security, Experience Cloud Developer Guide; Using the with sharing, without sharing, and inherited sharing Keywords, Apex Developer Guide, Salesforce. Default contexts per “Flow Run Context,” Salesforce Help.
