What Is an Apex Trigger?
An Apex trigger is a piece of code that Salesforce executes automatically before or after a DML operation - insert, update, delete, or undelete - occurs on a specific sObject. Unlike a class method you call explicitly, a trigger is invoked implicitly by the platform the moment a record change of the type it listens for reaches the database layer, making it the primary hook for enforcing business rules that declarative tools cannot express.
Cricket analogy: Just like a DRS review is triggered automatically the moment a bowler appeals and the on-field umpire signals uncertainty, without a player filing a separate request, an Apex trigger fires the instant a DML event like an Account insert occurs.
Trigger Syntax and Supported Events
A trigger declaration names the trigger, the sObject it monitors, and a comma-separated list of DML events it should respond to: before insert, after insert, before update, after update, before delete, after delete, and after undelete. Before triggers run prior to the record being saved to the database and are used to validate or modify field values on the triggering records directly, while after triggers run once the record is committed and are used for actions that need the record's generated Id, such as creating related child records.
Cricket analogy: Choosing 'before insert' versus 'after insert' is like a batsman adjusting his stance before facing a delivery versus reviewing the replay after the ball is bowled - before triggers reshape the record pre-save, after triggers react once it's locked in.
trigger AccountTrigger on Account (before insert, before update, after insert, after update) {
if (Trigger.isBefore) {
if (Trigger.isInsert) {
AccountTriggerHandler.beforeInsert(Trigger.new);
} else if (Trigger.isUpdate) {
AccountTriggerHandler.beforeUpdate(Trigger.new, Trigger.oldMap);
}
} else {
if (Trigger.isInsert) {
AccountTriggerHandler.afterInsert(Trigger.new, Trigger.newMap);
} else if (Trigger.isUpdate) {
AccountTriggerHandler.afterUpdate(Trigger.newMap, Trigger.oldMap);
}
}
}Choosing Triggers Over Declarative Automation
Salesforce encourages a 'clicks before code' philosophy, so Flow should be the first choice for simple field updates, record creation, and approval routing. Triggers become necessary when logic requires complex conditional branching across multiple objects, needs to run efficiently against very large data volumes such as bulk API loads or Data Loader imports, or must integrate tightly with Apex classes that already contain reusable business logic like callouts or complex calculations.
Cricket analogy: Choosing Flow for a simple field update is like using a pinch-runner for a straightforward single, while reaching for a trigger for complex cross-object logic is like sending in a specialist finisher such as MS Dhoni to close out a tense run chase.
Record-Triggered Flows now run efficiently in the same transaction context as triggers and can outperform simple triggers for basic field updates, but they still can't easily do things like recursive-safe complex branching logic or elegant unit-testable code reuse the way an Apex trigger handler class can.
The One-Trigger-Per-Object Pattern
Salesforce best practice restricts each sObject to a single trigger that delegates all logic to a separate handler class, rather than scattering logic across several triggers on the same object. This matters because when multiple triggers exist on one object, the order in which they execute is not guaranteed and cannot be controlled declaratively, which makes debugging unpredictable and increases the risk of conflicting field updates or unintended recursion.
Cricket analogy: Letting two separate triggers fire on the same object is like having two different captains simultaneously setting the field for the same over - their instructions conflict - whereas one trigger delegating to a handler class is like a single captain giving one clear field placement.
Never assume the execution order of multiple triggers on the same object is stable across orgs or deployments - Salesforce does not document or guarantee it. A single trigger per object with all logic routed through one handler class removes this risk entirely and keeps behavior deterministic.
- An Apex trigger executes automatically before or after DML operations (insert, update, delete, undelete) on a specific sObject.
- Trigger events are declared in a comma-separated list: before insert, after insert, before update, after update, before delete, after delete, after undelete.
- Before triggers modify field values on the in-memory records prior to save; after triggers act once records have a committed Id.
- Prefer declarative Flow automation for simple field updates and reserve triggers for complex, high-volume, or multi-object logic.
- Follow the one-trigger-per-object pattern, delegating all logic to a single handler class for predictable, testable behavior.
- Multiple triggers on the same object have an undocumented, unreliable execution order and should be avoided.
- Triggers are the mechanism of choice when logic must run reliably against bulk DML from the API or Data Loader.
Practice what you learned
1. Which of the following is a valid Apex trigger declaration?
2. Why would you choose an after-insert trigger instead of a before-insert trigger to create related child records?
3. What is the main risk of having multiple triggers on the same sObject?
4. Which automation tool should generally be preferred for a simple, non-recursive single-field update?
5. In trigger AccountTrigger on Account (before insert, before update), which statement is true?
Was this page helpful?
You May Also Like
Trigger Context Variables
A guide to Trigger.new, Trigger.old, their map equivalents, and the boolean context flags that let a single handler branch correctly across all seven trigger contexts.
Bulkification and Best Practices
How to write Apex trigger logic that stays safely within governor limits regardless of whether it processes one record or two hundred.
Trigger Frameworks
Why orgs adopt a shared trigger handler framework, the core components such frameworks share, and how metadata-driven bypass mechanisms support safe data migrations.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics