In Salesforce Apex, understanding Trigger.old is very important for handling record updates and deletes efficiently.
In this article, we will not only learn what Trigger.old is, but also explore real-time use cases, differences with Trigger.new and Trigger.oldMap, and common mistakes developers make.
By the end, you will be confident in using Trigger.old in real Salesforce projects.
In the previous tutorial, we saw the Trigger.New context variable in Apex, which is used to get access to the new records being processed in an insert or update operation.
Now, the Trigger.Old in Salesforce Apex is also a type of context variable that returns a list of the old versions of sObject records.
In that, I will explain what is Trigger.Old Salesforce Apex Trigger, what are its uses? Then, we will see how to use Trigger.Old context variable in Apex trigger code.
What is Trigger.Old in Salesforce Apex Trigger?
Trigger.Old is a context variable in Salesforce Apex triggers. It is a read-only list of the old records that are being updated or deleted.
This list contains the original values of the records as they existed in the Salesforce database before the current trigger event was executed.
- The Trigger.Old is a read-only context variable, which means we cannot modify its contents within the trigger.
- It is accessible only in update and delete trigger events because these operations require comparisons with existing records.
- The records in Trigger.Old aligns with the records in Trigger.New by index, making it easy to compare old and new values.
In the examples below, we will see scenarios where we can use Trigger.Old context variable in Apex trigger, and I will also explain how to use it.
Common Mistakes Developers Make
- Using Trigger.old in the insert trigger
- Not using Trigger.oldMap when needed
- Forgetting null checks
Example: Prevent Field Change Using Trigger.Old in Apex Trigger
For example, in the account object, we have created an account record. After that, if we attempt to change the account number field value of an existing account record, we need to display an error message.
In the Apex code below, I have created a trigger on the Account object with the before update event. Then, in the first for each loop, we created an account object instance and assigned Trigger.Old context variable to return the old version of the account records.
Then, in the second for loop, an account instance was again created and assigned Trigger.New context variable so that it will return a new version of the updated account records.
In the if statement, we added two conditions: If we already have x account record ID and whichever record is being updated, they are the same. Second: After updating the record, if the new account number is not equal to the old one, the new number is used. So here, we want to prevent that record from being saved.
For that, we added the addError() method, which displays error messages in the Salesforce UI and prevents records from being saved. Provide the message you want displayed when the error occurs.
After that, save the Apex trigger code to activate it.
trigger PreventFieldChange on Account ( before update ) {
for ( Account oldAcc : Trigger.Old ) {
for ( Account newAcc : Trigger.New ) {
if ( oldAcc.Id == newAcc.Id &&
oldAcc.AccountNumber != newAcc.AccountNumber) {
newAcc .addError ( 'You cannot change the Account Number.' );
}
}
}
}Navigate to the account object tab and open any existing account record in edit mode.

Then, change the account number and enter a different value. Click the Save button to save changes.

As you click the save button, you will see the error message that you provided in the addError() method.

In this way, we can use Trigger.Old context variable in Apex to compare old and new values from the Salesforce database.
Example: Displaying Old and Updated New Values Using a Trigger.Old in Apex
For example, when the phone number in the account object is updated, the account description value should be updated to include both the old and new phone numbers.
Here, I created a trigger on the account object with a before update event because we want to update the same object’s field value.
Then, we added a simple for-loop, which iterates through all the records being updated. The Trigger.new list contains the latest version of the records after the updates. The Trigger.old list includes the old version of the duplicate records before the updates.
In the loop, an index(i) is used to access records from Trigger.new and Trigger.old. Both Trigger.new and Trigger.old are lists, and their elements refer to the same index record.
Then, in the if statement, we checked if the old phone number and the new updated phone number were not the same. Then, we displayed the old and new phone numbers in the description field.
Save the Apex trigger code to activate it.
trigger NewVsOld on Account ( before update ) {
for( integer i=0; i < trigger.new.size(); i++ ) {
if( trigger.old[i].phone != trigger.new[i].phone ){
trigger.new[i].description = 'old phone number is ' + trigger.old[i].phone + ' and
New phone number is ' + trigger.new[i].phone ;
}
}
}Navigate to the account object tab and open any existing account record in edit mode. Here, you can see the description field in the blank.

Now, update the phone number field, enter a different number, and click the Save button to update the record.

As the record is updated, the text will automatically be added to the description field we provided in the if statement in the trigger, using the old and new phone number values.

In this way, we can Trigger.Old context variable in Apex to update the fields and display old and new values in the fields.
Example: Delete Related Records Using Trigger.Old Context Variable in Apex
For example, when we delete the account record from the Salesforce account object, any associated child opportunity records should also be deleted. For that, we need to use Trigger.Old context variable in Apex trigger.
Here, we created a trigger on the account object, and as per our example, we want to delete related records when the parent account gets deleted. For that, we have used the delete trigger event.
After that, we created a list collection where we will store opportunity records related to the account to get deleted. Then in, for each loop, we created an account object instance and assigned the old version of the account records. Again, I created a list collection that stores the opportunity records related to the account.
Then, we add the opportunity records that we get related to the account to the first list, which we created to store opportunity records to delete.
After that, we used the delete DML operation to remove the records from the list. Save the trigger.
trigger DeleteRelatedOppo on Account ( after delete ) {
List<Opportunity> OppoToDelete = new List<Opportunity>();
for ( Account acc : Trigger.old ) {
List<Opportunity> relatedOppo = [
SELECT Id
FROM Opportunity
WHERE AccountId = :acc.Id
];
OppoToDelete.addAll (relatedOppo);
}
if ( !OppoToDelete.isEmpty() ) {
delete OppoToDelete;
}
}Navigate to the account object tab and open any existing account record to the related tab to see the related opportunity records. Here, you can see we have three opportunities related to the GenePoint account.

Now, delete the GenePoint account.

After deleting the account, navigate to the opportunity object to check whether the related opportunity has been deleted. Search for the account name in the opportunity search bar, and you will see that there are no items to display here.

In this way, we can use Trigger.Old context variable with after delete event in Apex to perform the operation after the record gets deleted.
Trigger.old vs Trigger.new vs Trigger.oldMap in Salesforce
| Feature | Trigger.old | Trigger.new | Trigger.oldMap |
|---|---|---|---|
| Contains old values | Yes | No | Yes |
| Contains new values | No | Yes | No |
| Available in Insert | No | Yes | No |
| Available in Update | Yes | Yes | Yes |
| Data Type | List | List | Map |
Frequently Asked Questions
Q1: When is Trigger.old available?
Only in update and delete triggers
Q2: What is the difference between Trigger.old and Trigger.oldMap?
old = List, oldMap = Map
Can we modify Trigger.old?
No, it is read-only
Conclusion
Trigger.old is a powerful feature in Salesforce Apex that enables developers to compare previous record values and implement critical business logic.
Understanding its proper usage with Trigger.oldMap and Trigger.new is essential for writing efficient and error-free triggers.
I hope you have got an idea about Trigger.Old in Salesforce Apex, which is one of the types of context variables in the trigger. In that, I have explained Triggers.Old in Apex Trigger, its uses, and then we have seen how to use Trigger.Old context variable with different trigger events in Apex trigger code with different examples and explanations.
You may like to read:
- Apex Triggers in Salesforce
- Trigger.New in Salesforce Apex
- How to Avoid Recursion in Salesforce Apex Triggers
- Apex Trigger Handler and Helper Class in Salesforce
I am Bijay Kumar, the founder of SalesforceFAQs.com. Having over 10 years of experience working in salesforce technologies for clients across the world (Canada, Australia, United States, United Kingdom, New Zealand, etc.). I am a certified salesforce administrator and expert with experience in developing salesforce applications and projects. My goal is to make it easy for people to learn and use salesforce technologies by providing simple and easy-to-understand solutions. Check out the complete profile on About us.