Getting Started with Apex Triggers in Salesforce

May 04, 2025
514 Views
Getting Started with Apex Triggers in Salesforce

Welcome to day 8 of the 10 day Apex series. In the previous article we have seen how to Create and Use Apex Classes, Methods and Constructors in apex. Now In this blog we will talk about Apex Triggers.

Apex triggers are an important feature in Salesforce that permit for automatic execution of custom actions before or after changes to Salesforce records. Triggers will enable developers to impose business logic, maintain data integrity, data updates and automate complex processes within the Salesforce as per the requirements.

This article provides a diverse overview of what triggers are, when to use them, how to write a basic trigger and best practices to make sure that it will be well organized and error-free.

What Are Apex Triggers and When to Use Them?

A trigger is a piece of Apex code that executes or runs automatically in reply to specific data changes such as insertions, updates, deletions or undeletes of Salesforce records. Triggers can be performed on standard or custom objects, letting developers to execute custom actions based on the data updates.

Triggers are commonly used for:

  • Data Integrity and Validation: Make sure that related records are updated consistently based on required changes in salesforce.
  • Automation of Business Processes: Executing tasks such as sending notifications or updating related records without user interactions.
  • Complex Data Handling: Managing data operations that go beyond what flows or normal customization can accomplish.

Using triggers wisely will help to maintain business logic at the database level and will make sure that critical actions are executed automatically and properly, granting to a reliable and consistent application.

Also Read

Don’t forget to checkout: How to Create and Use Apex Classes, Methods and Constructors.

Writing a Simple Apex Trigger

Below is an example of a simple trigger in Apex. This trigger executes before an Account record is inserted and automatically sets a default value for a custom field called Status__c (Assuming we have this field already created in our org).

trigger AccountBeforeInsert on Account (before insert) {
    // Loop over each record in the context of the trigger
    for (Account acc : Trigger.new) {
        // Check if the Status field is not set and assign a default value
        if (acc.Status__c == null) {
            acc.Status__c = 'New';
        }
    }
}
 Explanation
  • Trigger Event:
    The trigger is made to run before insert on the Account object. The meaning behind that the trigger will execute prior to the new records being saved to the database, permitting modifications to be made.
  • Trigger Context Variable:
    Trigger.new is a list of all the new records that will be inserted based on our conditions. By checking this list, the trigger iterates through each record.
  • Conditional Logic:

    An if statement checks if the Status__c field is null for each record. If this condition matches, the field is set to a default value as ‘New’. This will make sure that each Account record has a predefined status when inserted.

Best Practices for Apex Triggers

To make sure that triggers remain efficient, maintainable and will be used for scalable implementations, below best practices should be followed:
  1. 1. Avoiding Recursion

    Triggers can mistakenly call themselves when we are performing DML operations inside the trigger context. To prevent infinite loops or recursion, a common strategy and mostly we use it is to use a static pvariable in an Apex class to make sure that the trigger logic only runs once per transaction.

    Example: Controlling Against Recursion While Writing Apex
    public class TriggerHelper {
        // A static variable to prevent recursive trigger calls
        public static Boolean isTriggerExecuted = false;
    }
    
    trigger AccountBeforeUpdate on Account (before update) {
        // Check if the trigger has already run in the current context
        if (TriggerHelper.isTriggerExecuted) {
            return;
        }
        TriggerHelper.isTriggerExecuted = true;
        
        // Loop over each record to apply logic
        for (Account acc : Trigger.new) {
            // Example: Automatically update a field based on a condition
            if (acc.Industry == 'Technology') {
                acc.Status__c = 'New';
            }
        }
    }
    

    In the above example, the static variable isTriggerExecuted in the TriggerHelper class that will be useful for checking if the trigger has already executed or not. If the trigger is already executed then the trigger exits at that time and stops recursion to happen.

  2. 2. Bulkification

    Triggers should be written to handle collections of records (Like a lot of records at a time), not just single record operations. Since triggers can be invoked with many records at once (up to thousands), efficient looping and processing are necessary to prevent hitting governor limits. Make a use of collections like lists, sets and maps to perform operations on groups of records instead of one by one.

    Bulkification Tips:

    • Avoid SOQL or DML inside loops: Collect all necessary IDs in a list and perform a single query or DML operation on the entire list outside the loop.
    • Use collections: Process records in bulk to ensure our trigger can handle large data volumes without performance issues and hitting limits.
  3. 3. Keep Triggers Simple

    Apex triggers should be assigned with complex processing to handler classes. It will make the code easier to test, debug and maintain. The better way for writing triggers is the ‘one trigger per object’, it’s recommended due to its order of execution.

    Example: Delegating Logic to a Handler Class

    Trigger:

    trigger AccountTrigger on Account (before insert, before update) {
        AccountHandler.processAccounts(Trigger.new);
    }
    

    Handler Class:

    public class AccountHandler {
        public static void processAccounts(List<Account> accList) {
            // Process a list of accounts that match business requirements
            for (Account acc : accList) {
                if (acc.Status__c == null) {
                    acc.Status__c = 'New';
                }
                // Additional business logic can be added here if required
            }
        }
    }
    

    Above example approach takes the business logic from the trigger itself, promoting reusability and better use of code that matches the requirements.

  4. 4. Testing and Coverage

    Proper and effective testing is required for any Apex code that suffices critical scenarios. Making sure that trigger logic will be covered by unit tests with various scenarios that we put while writing it, that will include bulk actions, to match with Salesforce’s code coverage requirements.

    Sample Test Class:

    @isTest
    public class AccountTriggerTest {
        @isTest static void testAccountInsert() {
            // We will create test accounts without setting Status__c
            List<Account> testAccounts = new List<Account>{
                new Account(Name = 'Test Account 1'),
                new Account(Name = 'Test Account 2')
            };
            
            // Now, insert accounts to trigger the before insert logic
            insert testAccounts;
            
            // Retrieve the accounts to verify the Status__c field is set correctly
            List<Account> insertedAccounts = [SELECT Status__c FROM Account WHERE Name LIKE '%Test Account%'];
            
            // Assert that the Status__c field was properly set with expected and actual values
            for (Account acc : insertedAccounts) {
                System.assertEquals('New', acc.Status__c);
            }
        }
    }
    

    Unit tests will make sure that the trigger executes and performs as expected when processing multiple records and it should involve negative and positive scenarios. We will discuss more related to test classes in this series of Apex learning.

Conclusion

Apex triggers are an important tool for automating business processes in Salesforce. By understanding what triggers are and when to use them, developers will be able to build automation that enhances data integrity and user productivity. We hope this article provided a clear introduction to writing a simple trigger, showcased how to avoid common risks such as recursion, and highlighted best practices for bulkification, delegation and testing.

On Day 9, we’ll explore Advanced Apex Concepts – Asynchronous Jobs. Stay tuned and happy coding!

Written by

user

Mohit Bansal

Salesforce Technical Architect | Lead | Salesforce Lightning & Integrations Expert | Pardot | 5X Salesforce Certified | App Publisher | Blogger

Contributor of the month
contributor
Gopinath G

Passionate about the intersection of cutting-edge technologies

Get the latest tips, news, updates, advice, inspiration, and more….

...
Boost Your Brand's Visibility

Want to promote your products/services in front of more customers?

...