Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
Salesforce Developer
hard

How do you handle recursion in triggers?

Recursion — your trigger fires another DML on the same object that re-invokes the same trigger. Without protection: infinite loop, stack overflow, governor-limit exhaustion.

Sources of recursion:

  • A trigger updates a field on Trigger.new -> after-trigger fires another update -> trigger fires again.
  • An after-update trigger updates related records, which fire their own triggers, which update back, etc.
  • Workflow rule + trigger circular dependency.

The static flag pattern (most common):

`apex public class AccountTriggerHandler { private static Boolean isExecuting = false;

public override void afterUpdate() { if (isExecuting) return; isExecuting = true; try { // your logic } finally { isExecuting = false; } } } `

A static variable persists for the duration of one transaction. Setting it on entry and checking on subsequent entries blocks recursion.

Variations:

  • Per-record recursion guard — track Set<Id> of processed records:

apex private static Set<Id> processedIds = new Set<Id>(); public override void afterUpdate() { Set<Id> toProcess = new Set<Id>(); for (Account a : (List<Account>) Trigger.new) { if (!processedIds.contains(a.Id)) toProcess.add(a.Id); } processedIds.addAll(toProcess); // process toProcess }

This lets the trigger fire for new records but skip already-processed ones in the same transaction.

  • Per-context-and-event guard — separate flags for beforeInsert, afterUpdate, etc., so a guard for one event doesn't block others.

When NOT to suppress recursion:

  • If your trigger needs to react to a chain of changes (e.g., parent update -> child update -> parent recalc), suppressing recursion blocks the desired logic. Restructure to compute final state on the first invocation.

Architectural alternative:

  • Move the after-trigger work to a Queueable, which fires after commit. The Queueable can update related records without re-firing the parent trigger in the same transaction.

Static guards are necessary but should be a last resort. The cleaner solution is usually to design the data flow so recursion isn't needed.

Why this answer works

Senior. Mentioning per-record guards and the Queueable alternative differentiates a senior from someone who knows only the basic static flag.

Follow-ups to expect

Related dictionary terms