Introduction
Salesforce developers often encounter Mixed DML exceptions, but there’s confusion around when they occur. A common myth is that updating setup and non-setup objects in the same transaction triggers this error. Let’s debunk this myth and clarify best practices for writing efficient Apex code.
What is a Mixed DML Exception?
In Salesforce, setup objects (e.g., User
, Profile
, PermissionSet
) manage org configuration, while non-setup objects (e.g., Account
, Contact
) handle business data. A Mixed DML exception occurs when you try to modify setup and non-setup objects in the same transaction during DML operations.
However, not all operations trigger this error!
The Myth: Updates Always Cause Errors
Many developers assume that any interaction between setup and non-setup objects (like updates) will throw a Mixed DML error. This is false!
When Does a Mixed DML Exception Actually Occur?
✅ Safe Operations (No Error):
- Updating setup and non-setup objects in the same transaction.
- Inserting a non-setup object while updating a setup object (e.g., modifying a
User
record’s username).
❌ Unsafe Operations (Causes Error):
- Inserting a setup object (e.g.,
User
) and inserting/updating a non-setup object (e.g.,Account
) in the same transaction.
Code Examples
✅ Allowed: Update Operations
// Update User (setup) and Account (non-setup) in the same transaction
User u = [SELECT Id, Username FROM User WHERE Id = :UserInfo.getUserId()];
u.Username = 'new.email@example.com';
Account acc = [SELECT Id, Name FROM Account LIMIT 1];
acc.Name = 'Updated Name';
update u; // Setup object update
update acc; // Non-setup object update
// No exception thrown!
✅ Allowed: Insert Non-Setup + Update Setup
// Insert Account (non-setup) and update User (setup)
Account acc = new Account(Name = 'Test Account');
insert acc; // Non-setup insert
User u = [SELECT Id, Username FROM User WHERE Id = :UserInfo.getUserId()];
u.Username = 'updated@example.com';
update u; // Setup object update
// No error occurs!
❌ Unsafe: Insert Setup + Insert Non-Setup
// Insert User (setup) and Account (non-setup) in the same transaction
User newUser = new User(
Alias = 'test',
Email = 'test@example.com',
Username = 'test@example.com',
LastName = 'Test',
ProfileId = [SELECT Id FROM Profile LIMIT 1].Id
);
Account acc = new Account(Name = 'Test Account');
// This will throw a Mixed DML error!
insert newUser;
insert acc;
Best Practices for Avoiding Errors
- Use
@future
Only for Inserts
- If you need to insert setup and non-setup objects together, separate them using
@future
methods. - Updates don’t require
@future
and can coexist in the same transaction.
- Write Cleaner Code
Avoid unnecessary asynchronous logic for updates. Simplify your code by grouping safe operations. - Test with Real Data
Always validate scenarios in a sandbox to avoid surprises in production.
Conclusion
Understanding Mixed DML exceptions helps you optimize Apex code and avoid overcomplicating transactions. Remember:
- Updates between setup/non-setup objects are safe.
- Inserts of non-setup objects paired with setup object updates are allowed.
- Reserve
@future
for insert operations involving both object types.