Trigger.new and Trigger.newMap hold the same records — just in different shapes. Trigger.new is a List<SObject> (positional, ordered). Trigger.newMap is a Map<Id, SObject> (keyed by record Id, O(1) lookup). The key difference for interviews: newMap is null in before insert, because the records have no Ids yet.
Side-by-side
| Property | Trigger.new | Trigger.newMap |
|---|---|---|
| Type | List<SObject> | Map<Id, SObject> |
| Lookup | By index | By record Id |
Available in before insert | Yes | No (null) — records have no Id |
Available in before update | Yes | Yes |
Available in after insert | Yes | Yes |
Available in after update | Yes | Yes |
Available in delete contexts | No | No |
Available in after undelete | Yes | Yes |
| Writable | In before contexts only | Never (the map view is read-only) |
When to reach for which
Use Trigger.new when you’re iterating — collecting Ids, computing fields in place, walking every record once.
for (Account a : Trigger.new) {
if (a.AnnualRevenue == null) a.AnnualRevenue = 0;
}
Use Trigger.newMap when you need lookup by Id — pairing each new record with its old version, or correlating with related records you queried separately.
trigger CaseTrigger on Case (after update) {
Set<Id> changedIds = new Set<Id>();
for (Case c : Trigger.new) {
if (c.Status != Trigger.oldMap.get(c.Id).Status) changedIds.add(c.Id);
}
Map<Id, Case> changed = new Map<Id, Case>();
for (Id id : changedIds) changed.put(id, Trigger.newMap.get(id));
AuditService.logStatusChanges(changed);
}
The “construct your own map” idiom
In before insert, you don’t have Trigger.newMap, but sometimes a downstream method expects a map. You can build one from Trigger.new only after the records have Ids — i.e. in any after context:
Map<Id, Account> byId = new Map<Id, Account>(Trigger.new);
The Map<Id, SObject> constructor accepts a List<SObject> and indexes by Id automatically. This is the same data Salesforce hands you as Trigger.newMap, just constructed manually.
Common interview follow-ups
- Why is
Trigger.newMapnull inbefore insert? — Records have noIdfield yet, so there’s no key to map by. - Is
Trigger.newMapavailable inbefore delete? — No, bothnewandnewMapare null in any delete context. UseTrigger.old/Trigger.oldMap. - Can I modify the records via
Trigger.newMap? — Inbeforecontexts, yes —newMap.get(id).Field__c = value;works because it returns a reference to the same recordTrigger.newholds.
Verified against: Apex Developer Guide — Trigger Context Variables. Last reviewed 2026-05-17.