100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

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.

Triggers & LogicIntermediate8 min readJul 10, 2026
Analogies

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.

apex
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

Was this page helpful?

Topics covered

#Programming#ApexSalesforceStudyNotes#TriggerContextVariables#Trigger#Context#Variables#New#StudyNotes#SkillVeris#ExamPrep