Trigger Framework Fundamentals
By the end of this lesson, you'll be able to:
- Explain the "one trigger per object" convention and why it exists
- Route different event types to different handler methods from a single trigger
- Recognize what a full trigger framework adds beyond this module's simple handler pattern
Prerequisites: "Order of Execution"
The problem with multiple triggers on one object
Nothing stops a codebase from having AccountTrigger1, AccountTrigger2, and AccountTrigger3 all firing on the same Account object — but Salesforce doesn't guarantee the order multiple triggers on the same object run in relative to each other. This makes behavior genuinely unpredictable as more triggers accumulate over time.
One trigger, routed by event
trigger AccountTrigger on Account (before insert, before update, after insert, after update) {
AccountTriggerHandler handler = new AccountTriggerHandler();
if (Trigger.isBefore && Trigger.isInsert) {
handler.beforeInsert(Trigger.new);
}
if (Trigger.isBefore && Trigger.isUpdate) {
handler.beforeUpdate(Trigger.new, Trigger.oldMap);
}
if (Trigger.isAfter && Trigger.isInsert) {
handler.afterInsert(Trigger.new);
}
if (Trigger.isAfter && Trigger.isUpdate) {
handler.afterUpdate(Trigger.new, Trigger.oldMap);
}
}
Exactly one trigger per object, routing to a dedicated handler method per event combination — this eliminates the ordering ambiguity of multiple separate triggers, while keeping each event's logic in its own clearly-named method.
The corresponding handler class
public class AccountTriggerHandler {
public void beforeInsert(List<Account> newAccounts) {
for (Account acc : newAccounts) {
if (String.isBlank(acc.Industry)) {
acc.Industry = 'Unknown';
}
}
}
public void beforeUpdate(List<Account> updatedAccounts, Map<Id, Account> oldMap) {
// update-specific logic here
}
public void afterInsert(List<Account> newAccounts) {
// after-insert-specific logic here
}
public void afterUpdate(List<Account> updatedAccounts, Map<Id, Account> oldMap) {
// after-update-specific logic here
}
}
Every method here can be called and tested directly — this closing lesson's shape combines "one trigger per object" with Lesson 5's "avoid logic in triggers" into a single, coherent pattern.
What a full trigger framework adds
Real production orgs typically go further than this module's simple routing — a full trigger framework adds a shared base class handling the routing automatically (so every trigger's body becomes nearly identical), built-in recursion guards (Lesson 6, generalized), and a consistent way to bypass triggers during data loads or tests. This module's pattern is the genuine foundation those frameworks build on — understanding it well is what makes a full framework make sense later, rather than feeling like unnecessary extra machinery.
Exercise
Write a Case trigger routing before insert and after insert to a CaseTriggerHandler with matching method names.
Show hint
if (Trigger.isBefore && Trigger.isInsert) { handler.beforeInsert(Trigger.new); }
Trigger Framework Fundamentals Quiz
My Notes
Log in to keep private notes on this lesson.
Questions about this lesson
No questions yet — be the first to ask.
Log in to ask a question about this lesson.
Summary
This closing lesson formalizes the handler pattern from earlier in the module into "one trigger per object," routing every event type to its own handler method — the foundation real trigger frameworks build on.