Apex triggers now always run in a without sharing context. Previously,
nested triggers enforced sharing rules in certain edge cases. However, in API version 67.0 and
later, database operations within trigger bodies, including SOQL queries, SOSL queries, DML
statements, and Database methods, run in user mode unless system mode is explicitly specified.
User mode overrides the trigger’s without sharing context and effectively
enforces a with sharing context in the trigger body.
Where: Triggers run in a without sharing context in all API versions.
Database operations in trigger bodies default to user mode in API version 67.0 and later. The
changes apply to Lightning Experience and Salesforce Classic in Enterprise, Performance,
Unlimited, and Developer editions.
Why: These changes are part of the new “secure by default” security paradigm. For more information, see Database Operations Run in User Mode by Default, Not System Mode. To control behavior reliably independent of the API version, set explicit access mode on all database operations in your trigger and handler classes. When possible, delegate all business logic to trigger handlers.
How: This example demonstrates trigger database access in API version 67.0 and later.
// API version 67.0
// The trigger itself runs as without sharing (all records accessible by default)
trigger AccountUpdateTrigger on Account (after update) {
// This SOQL query doesn't specify an access mode, so it defaults to WITH USER_MODE.
// Object- and field-level permissions are enforced.
// User mode reapplies the record-sharing rules of the current user,
// effectively overriding trigger's own sharing context.
List<Contact> contactsAccessibleByCurrentUser = [SELECT Id, Name, AccountId
FROM Contact
WHERE AccountId = :Trigger.newMap.keySet()];
// This SOQL query explicitly includes a WITH SYSTEM_MODE clause.
// Object- and field-level are bypassed.
// Record sharing remains governed by the trigger's own without sharing context,
// so all records are visible regardless of the user running the query
List<Contact> allRelatedContacts = [SELECT Id, Name, AccountId
FROM Contact
WHERE AccountId = :Trigger.newMap.keySet()
WITH SYSTEM_MODE ];
// Further processing with the related Contacts
}