In this Salesforce tutorial, we will learn about triggers in Salesforce and different types of triggers in Salesforce. So what is a trigger in Salesforce? Is it a class, an Object or apex code ? Most of the people will answer Trigger is an apex code ,yes it is correct , However rest two are also correct .
A Salesforce trigger is Apex code that runs automatically when records are inserted, updated, deleted, or undeleted. Triggers are used when a business rule must run close to the database transaction and cannot be handled fully with a declarative automation tool. A well-written Apex trigger should be bulk-safe, easy to test, and limited to logic that really belongs in the save transaction.
What are triggers in salesforce?
Triggers in Salesforce are programmatic event handlers which is an Apex code that gets executed when a record is saved. Trigger is an object where for each trigger we have written, Salesforce will create a record in ApexTrigger object.
In practical Apex development, think of a trigger as the entry point for record-change logic. The trigger receives the affected records through trigger context variables such as Trigger.new, Trigger.old, Trigger.newMap, and Trigger.oldMap. The trigger can then validate data, update related records, call Apex helper methods, or add errors to stop a save operation.
- Apex Trigger is also a class which contains twelve static context variables.
- Triggers in Salesforce gets executed when a DML operation occurs on an sObject record.
- Apex triggers run on Server side, not on client side.
- Triggers can handle Database manipulation language (DML) operations, can execute SOQl and can call custom Apex methods.
For the official syntax and behavior, refer to the Salesforce Apex Developer Guide pages on Apex triggers, trigger syntax, and the System.Trigger context reference.
Different Triggers in Salesforce.
Triggers in Salesforce are two types, Before Triggers and After Triggers. Now will learn about basic syntax of a trigger in SFDC.

A before trigger runs before Salesforce saves the record to the database. Use before triggers to set field values on the same records or to stop invalid data by using addError(). An after trigger runs after Salesforce saves the record and assigns record IDs. Use after triggers when you need the saved record ID, need to work with related records, or need to perform logic that depends on the record already being committed in the current transaction context.
Syntax – Salesforce Trigger
trigger triggerName on ObjectName (trigger_events) {
//code_block
}
trigger TestTrigger on Case (Before Insert,After Insert,Before Update ,After Update ,Before Delete ,After Delete,After Undelete) {
//Code Block
}
- Apex trigger is always started with a keyword trigger.
- Next we have to enter Trigger name.
- Enter the condition.
- To execute trigger on a case like before insert, after insert, before update, after update, before delete, after delete, after undelete, we must specify trigger events in a comma separated list as shown above.
We can declare more than one trigger event in one trigger ,but each should be separated by comma. The events we can specify in an Apex Trigger are as follows.
- Before Insert.
- Before Update.
- Before Delete.
- After Insert.
- After Updat.
- After Delete.
- After Undelete.
The supported trigger events are before insert, before update, before delete, after insert, after update, after delete, and after undelete. Salesforce does not provide a before undelete trigger event.
Salesforce Trigger Events and When to Use Each One
| Trigger event | When it runs | Typical use |
|---|---|---|
before insert | Before new records are saved | Set default field values, validate values, stop invalid inserts |
before update | Before existing records are updated | Compare old and new values, validate changes, update fields on the same records |
before delete | Before records are deleted | Prevent deletion when related rules are not satisfied |
after insert | After new records are saved | Create or update related records that need the new record ID |
after update | After existing records are updated | Respond to confirmed changes and update related data |
after delete | After records are deleted | Update related rollups or audit data after deletion |
after undelete | After records are restored from the Recycle Bin | Restore related state or recalculate related values |
Trigger Context Variables in Salesforce Apex
There is a System defined class called Trigger which contains 12(twelve) implicit variable,which we can access at run time. All Trigger Context variables are prefixed with “Trigger”. Ex : (trigger.isinsert).
Below are the varibales with description.
- isExecuting : It returns true, if the current apex code is trigger.
- isBefore : It returns true, if the code inside trigger context is executed before the record is saved.
- isAfter : It returns true, if the code inside trigger context is executed after the record is saved.
- isInsert : It returns true, if the code inside trigger context is executed due to an insert operation.
- isUpdate : It returns true, if the code inside trigger context is executed due to an update operation.
- isDelete : It returns true, if the code inside trigger context is executed due to delete operation.
- isUnDelete : It returns true, if the code inside trigger context is executed due to undelete operation. i,e when we recovered data from recycle bin .
- new : It returns the new version of the object records. Suppose when we inserted/updated 10 records trigger.new will contain 1o records .
- newMap : It returns a map of new version of sObject which contains an ID’s as a key and the old versions of the sObject records as value. This map is only available in before update, after insert, and after update triggers.
- old : It returns the old version of the object records.
- oldMap : It returns a map of old version of sObject which contains an IDs as a key and the new versions of the sObject records as value. This map is available for only update and delete trigger.
- size : It return the size of the manipulated record. It will return one if you will insert one record, It will return the size of the record you are inserting ,updating or deleting or undeleting.
The commonly used context variables are listed below with corrected availability notes.
| Context variable | Meaning | Available in |
|---|---|---|
Trigger.isExecuting | Returns true when the current code is running from a trigger context. | All trigger contexts |
Trigger.isBefore | Returns true for before trigger events. | Before insert, before update, before delete |
Trigger.isAfter | Returns true for after trigger events. | After insert, after update, after delete, after undelete |
Trigger.isInsert | Returns true when records are being inserted. | Before insert, after insert |
Trigger.isUpdate | Returns true when records are being updated. | Before update, after update |
Trigger.isDelete | Returns true when records are being deleted. | Before delete, after delete |
Trigger.isUndelete | Returns true when records are restored from the Recycle Bin. | After undelete |
Trigger.new | List of new versions of the records. | Insert, update, undelete contexts where new records are available |
Trigger.old | List of old versions of the records. | Update and delete contexts |
Trigger.newMap | Map of record IDs to new versions of records. | Before update, after insert, after update, after undelete |
Trigger.oldMap | Map of record IDs to old versions of records. | Update and delete contexts |
Trigger.size | Number of records in the current trigger invocation. | All trigger contexts |
| Trigger Event | Trigger.New | Trigger.Old |
| Before Insert | Yes | No |
| Before Update | Yes | Yes |
| Before Delete | No | Yes |
| Before UnDelete | No | Yes |
| After Insert | Yes | No |
| After Update | Yes | Yes |
| After Delete | No | Yes |
Note: the older table above uses the term Before UnDelete, but Salesforce supports after undelete, not before undelete.
Bulk-Safe Apex Trigger Example on Account
A Salesforce trigger may run for one record or for many records in the same transaction. For that reason, avoid writing trigger logic that assumes only one record. The following example updates a field on each Account record in a before insert or before update context without using SOQL or DML inside a loop.
trigger AccountBeforeSave on Account (before insert, before update) {
for (Account acc : Trigger.new) {
if (String.isBlank(acc.Rating)) {
acc.Rating = 'Warm';
}
}
}
This is a before trigger, so changing acc.Rating directly is enough. No extra update statement is required for the same records in Trigger.new. This keeps the code simple and avoids unnecessary DML.
Using Trigger.oldMap to Detect Field Changes
For update triggers, Trigger.oldMap helps compare the previous value with the new value. This is useful when logic should run only after a specific field changes.
trigger OpportunityStageChange on Opportunity (after update) {
List<Task> tasksToCreate = new List<Task>();
for (Opportunity opp : Trigger.new) {
Opportunity oldOpp = Trigger.oldMap.get(opp.Id);
if (opp.StageName != oldOpp.StageName && opp.StageName == 'Closed Won') {
tasksToCreate.add(new Task(
Subject = 'Follow up after opportunity is closed won',
WhatId = opp.Id,
Status = 'Not Started',
Priority = 'Normal'
));
}
}
if (!tasksToCreate.isEmpty()) {
insert tasksToCreate;
}
}
The example collects all tasks in a list and performs one DML statement after the loop. This pattern is important because Salesforce governor limits apply to every transaction.
Order of Execution for Salesforce Triggers
Salesforce triggers run as part of the record save process. The full save order includes validation rules, before triggers, duplicate rules, after triggers, assignment rules, workflow rules, processes, flows, escalation rules, roll-up summary calculations, sharing rules, and commit steps depending on the object and automation configured in the org. Before writing complex trigger logic, review the official Salesforce order of execution.
The main point for Apex developers is that a trigger is not the only automation that may run in a transaction. If a workflow rule, flow, or process updates the same record again, update triggers can run again. Design trigger logic to handle repeated execution safely.
Best Practices for Triggers in Salesforce
- Write bulk-safe trigger code: Always assume
Trigger.neworTrigger.oldcan contain many records. - Avoid SOQL inside loops: Query once outside the loop and use maps to access related records.
- Avoid DML inside loops: Collect records in lists and perform DML once after the loop.
- Use one trigger per object when possible: This makes ordering easier to control and reduces duplicate logic.
- Move business logic to Apex classes: Keep the trigger as a routing layer and place reusable logic in handler classes.
- Prevent recursion carefully: If automation can update the same object again, use a clear recursion control pattern.
- Write test methods for every trigger path: Cover insert, update, delete, undelete, positive cases, and blocked/error cases.
Simple Trigger Handler Pattern in Apex
For small examples, code inside the trigger may be easy to read. In real projects, a handler class makes trigger logic easier to test and maintain.
trigger AccountTrigger on Account (before insert, before update) {
if (Trigger.isBefore) {
if (Trigger.isInsert || Trigger.isUpdate) {
AccountTriggerHandler.setDefaultRating(Trigger.new);
}
}
}
public class AccountTriggerHandler {
public static void setDefaultRating(List<Account> accounts) {
for (Account acc : accounts) {
if (String.isBlank(acc.Rating)) {
acc.Rating = 'Warm';
}
}
}
}
This pattern keeps the trigger short. The class method can also be tested more directly by inserting and updating Account records in Apex test methods.
Common Mistakes in Salesforce Apex Triggers
- Writing queries inside a for loop: This can quickly hit SOQL governor limits when many records are processed.
- Updating the same records in an after update trigger: This can cause recursion if not controlled properly.
- Using
Trigger.new[0]for all logic: This ignores the rest of the records in bulk operations. - Assuming trigger order across multiple triggers: Multiple triggers on the same object can make execution harder to reason about.
- Forgetting delete and undelete behavior:
Trigger.newandTrigger.oldare not available in the same way for all events. - Mixing all logic inside the trigger file: Large trigger files become difficult to test, review, and maintain.
Editorial QA Checklist for Salesforce Trigger Tutorial
- Does the tutorial clearly explain that Salesforce triggers run automatically on DML events?
- Are all supported trigger events listed correctly, including
after undeleteand notbefore undelete? - Does every Apex trigger example avoid SOQL and DML inside loops?
- Are trigger context variables explained with the events where they are available?
- Does the content mention order of execution and the risk of repeated update execution?
- Does the tutorial encourage handler classes and test coverage for production trigger code?
FAQs on Triggers in Salesforce
What is a trigger in Salesforce?
A trigger in Salesforce is Apex code that runs automatically before or after a record is inserted, updated, deleted, or undeleted. It is used to execute custom logic during the database transaction.
What are before and after triggers in Salesforce?
A before trigger runs before Salesforce saves the record, so it is commonly used to validate data or set field values on the same record. An after trigger runs after the record is saved, so it is commonly used when record IDs or related record updates are required.
What trigger events are available in Salesforce Apex?
The available Salesforce trigger events are before insert, before update, before delete, after insert, after update, after delete, and after undelete.
Why should Apex triggers be bulk-safe?
Apex triggers can process many records in one transaction through imports, APIs, batch jobs, or mass updates. Bulk-safe code avoids SOQL and DML inside loops and handles every record in Trigger.new or Trigger.old.
Can a Salesforce trigger call an Apex class?
Yes. A trigger can call static methods in an Apex class. This is a common pattern because it keeps the trigger small and moves reusable business logic into a handler class.
Conclusion
In our next Salesforce tutorial, we will create our first Apex trigger in Salesforce and will learn how to call a class method from a trigger with an example.
Before writing production trigger logic, confirm the trigger event, understand which context variables are available, and design the code for bulk operations. A small trigger that delegates to a tested handler class is usually easier to maintain than a large trigger containing all business rules directly.
TutorialKart.com