WITH USER_MODE versus system mode
SOQL queries · Intermediate · 13 min · Runs in your Salesforce Developer org · Apex Path
Run the same owned-Ids query twice, once in system mode and once with `WITH USER_MODE`, then compare the counts. The point is to see which rows a USER_MODE query still returns when the running user owns them.
Lesson
Why this matters
Apex normally runs SOQL in system mode, which ignores field-level security and sharing. That is convenient while writing a trigger, but it also means a lookup helper can leak rows the running user is not allowed to see. WITH USER_MODE tells the query to run as the calling user, so hidden fields and unshared rows disappear from the result.
The smallest working example
List<Account> rows = [
SELECT Id, Name FROM Account
WHERE Id IN :ids
WITH USER_MODE
];
If the user cannot see one of those Accounts, that row is simply left out of rows. For a user who owns the rows, the result is the same as system mode.
Name the parts
- **
WITH USER_MODE** goes after theWHEREclause (beforeORDER BY/LIMIT). - The query uses the running user's sharing rules and field-level security.
- Pair USER_MODE with **
Security.stripInaccessible** when you do DML, so writes also respect field permissions. - The query still binds variables the same way; USER_MODE does not change the syntax.
A common wrong version
List<Account> rows = [SELECT Id FROM Account]; // system mode, no filter
Two problems. There is no WHERE clause, so the query reads the whole table. And it runs in system mode, so it can see rows the user is not allowed to see.
The fix
Filter to the owned Ids and run the same query twice. The second one adds WITH USER_MODE:
Integer systemCount = [SELECT COUNT() FROM Account WHERE Id IN :createdIds];
Integer userCount = [
SELECT COUNT() FROM Account WHERE Id IN :createdIds WITH USER_MODE
];
Both counts should be 2 for the running user, because they own the Accounts.
Now you try
The starter inserts two Accounts and collects their Ids in createdIds. Count both queries, print System count: and User count:, then print Match: with whether the counts are equal.
Learn more
The challenge
Run the same owned-Ids query twice and count the rows each mode returns.
Examples:
- Query without USER_MODE →
System count: 2 - Query with WITH USER_MODE →
User count: 2 - Comparing the counts →
Match: true
Requirements:
- Uses WITH USER_MODE should be present: the second query uses
WITH USER_MODEexactly. - Scopes queries by owned Ids should be present: both queries bind
createdIdsin theWHEREclause. System count: 2should be printed for the system-mode query.User count: 2should be printed for the USER_MODE query.Match: trueshould be printed when the two counts are equal.
Starter code
String tag = 'AS-Q317-' + UserInfo.getUserId() + '-' +
String.valueOf(Datetime.now().getTime());
List<Account> seeded = new List<Account>{
new Account(Name = tag + '-A'),
new Account(Name = tag + '-B')
};
insert seeded;
Set<Id> createdIds = new Map<Id, Account>(seeded).keySet();
System.debug('System count: 0');
System.debug('User count: 0');
System.debug('Match: false');
Related drills
You write the Apex yourself. ApexSensei runs it and tells you what passed and what did not.
‹ Single-row query: zero or many rows · Group by a parent field ›