One of the common problems in Apex triggers is accidental recursion. That happens when a trigger causes an update, and the same trigger runs again.
Uncontrolled recursion can lead to infinite loops, repeated DML operations, and hitting governor limits. The safe fix is to add a guard so each trigger only runs once per transaction.
Static variables keep state for the transaction, so you can detect whether your trigger already ran.
public class OpportunityTriggerHelper {
public static Boolean hasRun = false;
}
trigger OpportunityTrigger on Opportunity (before update) {
if (OpportunityTriggerHelper.hasRun) {
return;
}
OpportunityTriggerHelper.hasRun = true;
for (Opportunity opp : Trigger.new) {
if (opp.StageName == 'Closed Won') {
opp.Description = 'Closed this deal';
}
}
}
A small helper class makes recursion control easier to reuse across multiple triggers.
public class TriggerExecutionGuard {
private static Set executedTriggers = new Set();
public static Boolean canRun(String triggerName) {
if (executedTriggers.contains(triggerName)) {
return false;
}
executedTriggers.add(triggerName);
return true;
}
}
trigger AccountTrigger on Account (before update) {
if (!TriggerExecutionGuard.canRun('AccountTrigger')) {
return;
}
// trigger logic here
}
Sometimes a trigger must update a related record, and that related record has its own trigger. In those cases, design the triggers so they can safely run multiple times without repeating work.