Apex Triggers in Salesforce

In this blog, we will master the Apex Triggers in Salesforce. Automation is key to enhancing productivity and streamlining business processes in salesforce development. We have two powerful automation tools: Salesforce Flows and Apex Triggers.

While Flows offers declarative, point-and-click automation capabilities, Apex Triggers in Salesforce stand out as the backbone of programmatic automation within the platform.

Whether it’s enforcing complex validation rules, updating related records, or triggering email notifications, Triggers empower developers to tailor Salesforce to the unique needs of their organization.

What are Apex Triggers in Salesforce?

We can invoke our apex code by using triggers. It enables us to perform tasks before or after the changes made to the records such as insertion, updation, deletion, etc.

However, it can be used to perform actions that can’t be possible with point and click method, solve complex scenarios based on some condition, and restrict users from executing certain actions.

What is the syntax of trigger?


Here, we have to specify on which object our trigger would be, what are the events on which our trigger executes, the name of the trigger and the code logic.

 What are the types of Apex triggers in Salesforce?

In Salesforce we have two different types of triggers :

  1. Before
  2. After

Let’s understand what before and after exactly means in terms of Salesforce and what to choose according to the requirements.

Before – In this type, records are saved to the Database but don’t commit to it. This means changes are temporarily saved and can be rolled back.

At this point, records are only visible to you within your transaction scope. Id and Autonumber get generated. It is useful to perform tasks like validating records, and changes on the same object.

After – In this type, records are committed to the Database. This means changes are permanently saved to the Database and cannot be rolled back. Now, the records are also visible to the other users.

It is useful to perform an action that has to be done when records get committed like performing any action on related records and also to access system fields. The records that fire the after trigger are read-only.

What are the apex trigger events in Salesforce?

Following are the triggers events :

  1. Before Insert
  2. Before Update
  3. Before Delete
  4. After Insert
  5. After Update
  6. After Delete
  7. Before Undelete

What operations cause a trigger to fire?

A trigger is Apex code that executes before or after the following types of operations:

  1. insert – When a new record is created in Salesforce the insert event will fire.
  2. update – When the record is modified, the update event will fire.
  3. upsert – When the new record is created or an existing one is modified then it will fire both update and insert events.
  4. merge – Merge events do not fire their trigger events. Instead, they fire delete and update events. For losing records it will fire before delete and after delete. For winning records it will fire before update and after update.
  5. delete – When the records get removed from the database.
  6. undelete – When the records get recovered from the database, i.e. restoring records from the recycle bin.

What are the context variables available in apex triggers?

They are the trigger’s internal variables that we can use in the runtime context contained in the System.Trigger class. Following is the list:

  1. isExecuting – Returns true if the current context of an apex code is the trigger.
  2. isInsert – Returns true if trigger fire due to an insert operation.
  3. isUpdate – Returns true if the trigger is executing due to an update operation.
  4. isDelete – Returns true if the trigger is executing due to a delete operation.
  5. isBefore – Returns true if the trigger is firing before the records get saved.
  6. isAfter – Returns true if the trigger is firing after the records get saved.
  7. isUndelete – Return true if the trigger is executing due to an undelete (restoring the records from the recycle bin) operation from Salesforce UI, API, or Apex.
  8. new – Returns the list of newly loaded versions of sObject records.
  9. newMap – Returns the Map of newly loaded versions of sObject records with their generated ID.
  10. old – Returns the list of old versions of sObject records. In Insert, it is not available as we don’t have the old records there.
  11. oldMap – Returns the Map of old versions of sObject records with their generated ID.
  12. operationType – It specifies the trigger operation such as before insert, after insert, etc. It returns the enum of type System.TriggerOperation. We can use this to operate on different types by switching on this operationType.
  13. size – It returns the total number of records invocation in old and new.

Below is the table showing what context variable is available in each event

Info showing about context var

How to create Trigger?

To create an Apex trigger we have two ways

  1. From Salesforce UI – Navigate to Setup –> Object Manager –> Select Object on which you want to create trigger –> Trigger –> Newapex triggers
  2. Developer Console – Click on the gear icon –> Developer Console –> File –> New –> Apex Trigger –> Select the object from the dropdown and provide the trigger name.create apex trigger from developer console
    If working from Visual Studio Code, then below is the screenshot of creating the Apex trigger.
    Here, open your project in the VS Code, authorise the salesforce org you are working on, go to the force-app\main\default folder, right-click the trigger folder, and then create Apex trigger.
    Another approach is to provide the Ctrl+shift+P command in Windows and then search for SFDX: Create Apex Trigger.

    Apex trigger in VS Code

Let’s take a scenario and understand how the trigger works in a few trigger events.

Scenario 1: Before Insert

Whenever we try to insert an opportunity with the stageName as “Needs Analysis“, then the probability cannot be greater than 50%.



Here, OpportunityTrigger is the Trigger name and it is firing on the before event. So in the if condition we are checking with the context variable if it is in the Before and Insert operation. We have used it before insert here because we want to validate our records before they get committed to the database.

Then, we iterate on the newly created opportunity list i.e. Trigger.new and check if it matches the condition then we throw the error message by adding an error on opp.



Scenario 2: Before Update

Whenever the opportunity stage name changes to Closed Won, there is one Date field that WonDate on Opportunity, update that to today’s date.

After modifying the above trigger code. Below is the result


Here, we are checking if it is the update operation on the before type. According to our condition, we only want to fire our trigger whenever there is a change in stageName to Closed Won. For that, we have utilised the Trigger.oldMap variable, It will store the older version of that record. We have used oldMap because it will be easier to fetch older records specific to the opportunity ID.

We have stored the older version of the opp record in the oldOpportunity variable and then we compare the old value is not closed won and the new value is closed won, that means the value is changed and we have to fire the trigger.

Then, we are updating the WonDate__c to today’s date. There is no need to add a DML statement explicitly in the before type because data is not yet committed to the database and it is still in memory, and the DML statements would cause recursion and other issues.


Best practices while writing apex triggers in Salesforce

  1. Logic less – Trigger should be logic less. Use Handler instead.
  2. One Trigger per object – We should always write one trigger per object. Because multiple triggers per object can cause problems as the order of execution will not be fixed.
  3. Bulkify your code – try to bulkify your code to avoid hitting the governor limit.
  4. Try using the trigger framework – There are many trigger frameworks available that we can use to apply best practices and avoid hitting the governor limit.
  5. Avoid recursion as much as possible – Recursion can cause the trigger to fire multiple times. To stop recursion we can use different logics available.
  6. Reusable code

Now, let’s modify our above trigger to use a handler and make our trigger logic less. Here we have created one Apex class OpportunityTriggerController.

Syntax: OpportunityTriggerController.apxc


Syntax: OpportunityTriggerController.apxt


What is trigger Bulkification?

Trigger bulkification means operating a trigger on the collection of sObject records. Bulkify trigger helps us to handle triggers operating on single records as well as bulk records.
If we trigger is executing via Salesforce UI, it will not be a problem but while inserting records by other tools like Data Loader or through API then we need to handle our trigger.
We need to use SOQL and DML efficiently to avoid hitting the governor limit.

What are the types of trigger frameworks in Salesforce?

Frameworks are the reusable structure that serves as a building block. It provides common functionality that developers can utilize for their own needs. It improves efficiency and clarity. We have different types of trigger frameworks according to the development that has to be done.

  1. Trigger Handler Pattern 
  2. Framework using virtual class
  3. Using Interface
  4. Architecture framework

What are the ways to avoid recursion in the trigger?

Recursion occurs when the trigger invokes itself in a loop and eventually hits the governor’s limit due to repeated execution and iteration. We can also encounter the error “Maximum trigger depth exceeded” due to multiple executions because the stack depth limit in Salesforce is 16.

For Example:  If a trigger is firing on an Account’s update and in that trigger logic we are updating those Accounts then it will lead to recursion due to multiple executions.

Avoiding recursion is very important in Salesforce to ensure stability and efficiency. We have different methods to avoid recursion in trigger

  1. Static Boolean variable – We will use the boolean variable make it default true, and check the value if true, will enter it into the transaction and make it false afterwards.
  2. Static Set – In this process we will store the processed ID and check if the ID is contained in the Set or not.
  3. Static Map – Here, we will create a Map of String and Set of Id (Map<String, Set<Id>>) to store the processed Id with their event.
  4. Static Old Map – We will use the old map to compare the values before executing.


1. Does the trigger run in System mode or User mode?

System Mode – When code runs in System mode it ignores all user’s permission and it has access to all the objects and fields

User Mode – Code executed respecting the user’s permission

Apex trigger runs in System mode but it also depends if we are calling handler and that handler is running in user mode then it will apply user permission.

2. Can we perform a callout from the trigger?

Yes, we can perform a callout from the trigger but it must be made asynchronously so that the trigger process isn’t blocked while waiting for the external service’s response.

3. What are the events on which a trigger can be fired?

Insert, update, upsert, merge, delete and undelete are the events on which a trigger can be fired.

4. What is the System.FinalException: Record is read-only and when we encounter?

When we try to update the trigger.new records in after insert/ after update context are read-only then we encounter this exception. To demonstrate the error, I have written a trigger on Opportunity firing after the insert event and am trying to update the records.

Syntax :



Final Exception demo


As we conclude this exploration into the realm of Triggers, it’s clear that these tools are super important. They help make things work automatically and smoothly. Additionally, they help us do all sorts of cool stuff like ensuring correct data.

Moreover, they enable complex tasks to happen at just the right time. Apex Triggers are powerful helpers that make Salesforce do exactly what we need.

Get a complete Roadmap To Learn Salesforce Admin And Development

Share Now

Kashish have extensive Salesforce development experience, holding 4 Salesforce certifications. she posses expertise in Apex, Lightning Web Components, and Salesforce Admin, with a track record of successful project delivery. As a dedicated Salesforce enthusiast, she actively seek and embrace new challenges and opportunities within the dynamic Salesforce ecosystem.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *