In this blog post, we'll explore different approaches to avoid recursion in Apex triggers, covering both simple and scalable patterns.
🔁 What is Trigger Recursion?
Trigger recursion happens when an update in a trigger causes the same trigger to fire again, which causes another update, and so on — creating a loop. This is especially common when:
- A trigger updates records of the same object it’s written on.
- There are cross-object updates causing re-entry into the trigger indirectly.
✅ Approaches to Prevent Recursion in Apex Triggers
1. Static Boolean Flag (Basic Approach)
A static variable retains its value throughout the transaction, making it ideal to track whether a trigger has already executed.
Example:
public class AccountTriggerHandler {
public static Boolean hasRun = false;
public static void handleAfterUpdate(List<Account> accList) {
if (hasRun) return;
hasRun = true;
// Your logic here
}
}
Trigger:
trigger AccountTrigger on Account (after update) {
AccountTriggerHandler.handleAfterUpdate(Trigger.new);
}
✅ Simple to implement
⚠️ Not suitable for bulkified or multi-object logic
2. Static Set to Track Record Ids (Bulk-safe)
Instead of using a single flag, maintain a static Set<Id>
to track which records have already been processed.
Example:
public class AccountTriggerHandler {
private static Set<Id> processedAccountIds = new Set<Id>();
public static void handleAfterUpdate(List<Account> accList) {
List<Account> toProcess = new List<Account>();
for (Account acc : accList) {
if (!processedAccountIds.contains(acc.Id)) {
toProcess.add(acc);
processedAccountIds.add(acc.Id);
}
}
// Process only unprocessed records
}
}
✅ Better control over which records are processed
✅ Bulk-safe
⚠️ Can grow memory usage with very large datasets
3. Custom Metadata/Custom Settings Based Flags (Org-level Control)
You can create a hierarchy custom setting or custom metadata to turn trigger logic on/off based on environment or admin control.
Use Case:
- Disable trigger logic temporarily during data migration or batch jobs.
- Better control for admins without changing code.
✅ Useful in admin-controlled deployments
⚠️ Not a direct solution to recursion but good for managing trigger logic
4. Trigger Frameworks with Recursion Guards
Robust trigger frameworks like the Trigger Handler Framework (developed in-house or using open source like SFDC Trigger Framework) provide structured ways to manage recursion.
Sample Framework Pattern:
public abstract class TriggerHandler {
private static Map<String, Boolean> handlerStatus = new Map<String, Boolean>();
protected Boolean isFirstRun(String handlerName) {
if (!handlerStatus.containsKey(handlerName)) {
handlerStatus.put(handlerName, true);
return true;
}
return false;
}
}
Your handler class would then call isFirstRun('AccountUpdateHandler')
to decide if logic should proceed.
✅ Scalable and enterprise-ready
✅ Encourages separation of concerns
⚠️ Slightly more complex setup
5. Using a "Reentrancy Key" on Custom Fields (Last Resort)
If recursion is caused by logic that cannot be easily isolated, you may store a “reentrancy token” in a custom field to track whether the logic already ran.
Example:
Add a custom field: Last_Processed_By__c
Set it with a hash or process ID so the logic doesn’t run again for the same update.
✅ Useful in edge cases
⚠️ Involves DML and schema changes — use only when others fail
🛡️ Best Practices
- Always bulkify your recursion guard — triggers run in batches, not one record at a time.
- Combine multiple patterns if needed (e.g., static flag + trigger framework).
- Consider using platform events, future methods, or queues to decouple logic that doesn't need to run synchronously.
🚀 Conclusion
Avoiding recursion in Apex triggers is critical to building robust and performant Salesforce applications. Whether you're using simple static flags or full-fledged frameworks, choosing the right approach depends on the complexity and scale of your org.
Have you faced recursion issues in your Salesforce projects? Share your experience or favorite recursion-avoidance pattern in the comments!
0 Comments
Post a Comment