⚙️ Writing Triggers in Apex
Triggers are essential for automating logic in Salesforce. They run before or after DML operations on records and allow you to enforce business rules at the database level.
---🕐 Before vs After Triggers
- Before Triggers: Used to modify record values before saving to the database.
- After Triggers: Used when you need the record's ID or want to perform operations on related records.
Trigger Type | Use Case |
---|---|
before insert |
Set default values before saving |
after insert |
Log creation, send notifications |
before update |
Validate or modify updates |
after update |
Act on changes with old/new values |
before delete |
Prevent deletion with custom checks |
after delete |
Clean up related records |
after undelete |
Re-link relationships after restore |
🎯 Trigger Events
Triggers can fire on the following DML events:
before insert
after insert
before update
after update
before delete
after delete
after undelete
📐 Trigger Design Pattern
The recommended pattern is One Trigger Per Object and delegate logic to a handler class.
AccountTrigger.trigger
trigger AccountTrigger on Account (before insert, after update) {
AccountTriggerHandler.run(Trigger.isBefore, Trigger.isAfter);
}
AccountTriggerHandler.cls
public class AccountTriggerHandler {
public static void run(Boolean isBefore, Boolean isAfter) {
if (isBefore && Trigger.isInsert) {
// Call helper logic
} else if (isAfter && Trigger.isUpdate) {
// Call helper logic
}
}
}
💡 Bulkification
Triggers should handle bulk operations (up to 200 records). Avoid SOQL/DML inside loops.
Bad Practice ❌
for (Account acc : Trigger.new) {
insert new Contact(LastName = acc.Name + ' Contact');
}
Good Practice ✅
List newContacts = new List();
for (Account acc : Trigger.new) {
newContacts.add(new Contact(LastName = acc.Name + ' Contact'));
}
insert newContacts;
🔁 Handling Recursion
To prevent infinite loops, use a static variable in a utility class.
TriggerControl.cls
public class TriggerControl {
public static Boolean isFirstRun = true;
}
Usage in Trigger
if (TriggerControl.isFirstRun) {
TriggerControl.isFirstRun = false;
// Call logic
}
🧭 Order of Execution
- Validation rules
- Before triggers
- Duplicate rules
- Record saved (but not committed)
- After triggers
- Assignment rules, workflow, process builder
- Roll-up summary, escalation
- Commit to DB
- Post-commit logic: emails, queueable, etc.
✅ Summary Tips
- Use one trigger per object
- Always bulkify your code
- Use handler classes for logic
- Guard against recursion
- Understand the order of execution