Understanding Trigger Context Variables
Every trigger execution has access to a set of implicit context variables exposed through the Trigger class, including Trigger.new (the list of records after the change), Trigger.old (the list of records before the change), their map equivalents keyed by Id, and boolean flags like Trigger.isInsert and Trigger.isBefore that identify exactly which event and phase fired the trigger. These variables are what let a single handler class branch its logic correctly for every one of the seven possible trigger contexts.
Cricket analogy: Trigger context variables are like a ball-by-ball data feed telling you not just the current score (Trigger.new) but also what it was before the last delivery (Trigger.old), so commentators like Sunil Gavaskar can explain exactly what changed on that ball.
Trigger.new vs Trigger.old
Trigger.new holds the list of sObjects after the triggering change and is available in all insert and update contexts (both before and after); it is null in delete triggers because there is no 'new' state. Trigger.old holds the pre-change list and is available in update, delete, and after-undelete contexts, but not in insert, since no prior version exists; comparing corresponding elements of Trigger.new and Trigger.old by matching Ids is the standard way to detect exactly which fields changed on an update.
Cricket analogy: Trigger.new not existing in a delete context is like there being no 'next delivery' data once a batsman is given out and the innings ends for that player - there's simply no forward state to record, only the final one before dismissal.
trigger OpportunityTrigger on Opportunity (before update) {
for (Opportunity opp : Trigger.new) {
Opportunity oldOpp = Trigger.oldMap.get(opp.Id);
if (opp.StageName != oldOpp.StageName) {
opp.Stage_Change_Date__c = Date.today();
}
}
}Map Variables: newMap and oldMap
Trigger.newMap and Trigger.oldMap expose the same record lists as Map<Id, sObject>, keyed by record Id, which is essential when you need to look up a specific record's before-and-after state efficiently rather than iterating a list. Critically, Trigger.newMap is not available in a before-insert context because the records have not yet been assigned an Id by the database, so calling it there throws a runtime error; it only becomes usable starting in after-insert once Salesforce has committed the records and generated Ids.
Cricket analogy: Trigger.newMap keyed by Id is like a scorecard app looking up a specific player's stats by their unique player ID rather than scrolling the whole XI, letting you jump straight to Virat Kohli's entry.
Referencing Trigger.newMap inside a before-insert block throws a runtime error because no Ids exist yet for new records - always guard map usage with Trigger.isInsert && Trigger.isBefore checks, or simply avoid newMap in that specific context and use Trigger.new instead.
Boolean Context Checks
The boolean flags Trigger.isBefore, Trigger.isAfter, Trigger.isInsert, Trigger.isUpdate, Trigger.isDelete, and Trigger.isUndelete let a single trigger, wired to fire on multiple events, correctly branch to the right block of logic. Trigger.isExecuting additionally tells any called Apex code, such as a helper method, whether it is currently running inside a trigger context at all, which is useful for methods shared between trigger handlers and other invocation paths like an anonymous Apex script.
Cricket analogy: Checking Trigger.isBefore && Trigger.isInsert is like an umpire distinguishing a no-ball call, before the delivery is legal, from a run-out review after the ball is already in play, applying completely different rules to each phase.
A typical handler pattern checks compound conditions like if (Trigger.isBefore && Trigger.isInsert) to isolate before-insert-only logic, letting one trigger declared on (before insert, before update, after insert, after update) still keep each event's logic cleanly separated inside its handler class.
- Trigger.new holds post-change records; Trigger.old holds pre-change records; both are unavailable in certain contexts (old on insert, new on delete).
- Trigger.newMap and Trigger.oldMap are Map<Id, sObject> versions for efficient Id-based lookups.
- Trigger.newMap is not accessible during before-insert since records don't yet have committed Ids.
- Boolean flags (isBefore, isAfter, isInsert, isUpdate, isDelete, isUndelete) let a single handler branch correctly per context.
- Trigger.isExecuting tells shared Apex code whether it's currently running inside a trigger context.
- Comparing Trigger.new and Trigger.old field by field is the standard pattern for detecting exactly what changed on an update.
- Trigger.size returns the total number of records in the current trigger invocation, useful for bulk-safe logic checks.
Practice what you learned
1. In which trigger context is Trigger.old NOT populated?
2. Why does accessing Trigger.newMap in a before-insert trigger throw a runtime error?
3. What is the primary advantage of Trigger.newMap over Trigger.new when you need one specific record's data?
4. Which check correctly isolates logic that should run only during the before-insert context?
5. What does Trigger.isExecuting indicate?
Was this page helpful?
You May Also Like
Apex Triggers Basics
An introduction to what Apex triggers are, how their syntax and events work, and when to reach for a trigger instead of declarative automation.
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.
The Order of Execution
The fixed sequence Salesforce follows on every save - system validation, triggers, validation rules, and post-commit automation - and why it matters for rollups and workflow interactions.
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