
This guide to Apex Triggers in Salesforce is designed for developers who want to automate business processes using custom logic. You’ll learn the basics of how triggers work, how to write and structure them properly, and how to avoid common mistakes—all with clear examples and updated best practices for 2025.
🧠 What is an Apex Trigger?
An Apex Trigger in Salesforce is a piece of code that executes automatically before or after data manipulation language (DML) operations — like insert
, update
, delete
, or undelete
. Triggers help automate tasks by responding to changes in your data model.
Example use cases:
- Automatically update a related record when a new Opportunity is created
- Validate or auto-fill missing values before a record is saved
- Block record deletion under specific conditions
📊 When to Use Apex Triggers vs Flow

Choosing between Flow and Apex Triggers can be tricky, especially when performance and scalability matter. This comparison chart outlines key capabilities and limitations across different automation types, helping you decide when Apex Triggers are the right tool for the job.
📚 Apex Triggers Syntax and Structure
Understanding the syntax and structure of Apex Triggers is the foundation of mastering automation in Salesforce. In this section of the guide to Apex Triggers, we’ll break down how a basic trigger is written and what its core components do. Whether you’re new to development or transitioning from Flow, this overview will help you get comfortable with how triggers are defined and executed.
trigger AccountTrigger on Account (before insert, before update) {
for (Account acc : Trigger.new) {
if (acc.Name == null) {
acc.Name = 'Default Account Name';
}
}
}
Key Components:
Trigger.new
: New versions of the records being processedTrigger.old
: Prior versions (only in update/delete contexts)- Context variables like
Trigger.isInsert
,Trigger.isUpdate
✅ Apex Trigger Best Practices
In this section of the guide to Apex Triggers, we’ll cover best practices that ensure your code runs efficiently, scales well, and avoids hitting governor limits. Following these tips will help you write production-ready triggers that align with Salesforce development standards:
- Use a single Trigger per object – Organize logic in a Trigger Handler class
- Bulkify your code – Always account for multiple records
- Avoid SOQL/DML in loops – Query or update outside loops
- Use context variables – Ensure logic only runs when appropriate
- Prevent recursion – Use static variables to block repeated execution
💡 Common Patterns in Apex Triggers
Understanding common patterns in Apex Triggers can help you build more maintainable and scalable code. This part of the guide to Apex Triggers outlines three proven patterns developers rely on:
- Trigger Handler Pattern: Delegate business logic to separate Apex classes
- Bulk-safe Pattern: Design to handle batch operations effectively
- Framework Use: Some developers adopt frameworks like
fflib
for structure and reusability Some developers adopt frameworks likefflib
for structure and reusability
🧨 Pitfalls to Avoid in Apex Triggers
Even experienced developers can run into issues with Apex Triggers if they overlook key architectural and performance considerations. Here are common pitfalls to avoid in any guide to Apex Triggers:
- Cramming too much logic inside the trigger body
- Forgetting to test with bulk data
- Failing to account for recursion
- Running SOQL or DML statements inside
for
loops inside the trigger body - Forgetting to test with bulk data
- Failing to account for recursion
- Running SOQL or DML statements inside
for
loops
📌 Apex Trigger Examples (With Handler)
Now that you’ve seen the structure and best practices from this guide to Apex Triggers, let’s take a look at a complete example. Below is a simple trigger that uses a handler class to separate logic. This pattern makes your code easier to manage and scale as your org grows.
trigger ContactTrigger on Contact (before insert, before update) {
ContactTriggerHandler.handle(Trigger.new, Trigger.oldMap);
}
public class ContactTriggerHandler {
public static void handle(List<Contact> newList, Map<Id, Contact> oldMap) {
for (Contact c : newList) {
if (c.Email == null) {
c.Email = '[email protected]';
}
}
}
}
🧠 What is CLI and How It Relates to Apex

The Salesforce CLI (Command Line Interface) is a terminal-based developer tool used to deploy code, create orgs, run tests, and manage metadata. For Apex Triggers, developers often use the CLI to push trigger files and Apex classes to a sandbox or scratch org. While powerful, CLI is more suited for experienced developers and continuous integration setups. You can read more about the CLI and alternatives here.
🏁 Apex Triggers Conclusion
Apex Triggers are essential for automating complex business processes in Salesforce. By understanding their structure, following best practices, and avoiding common pitfalls, even beginners can write clean, scalable code that performs well in real-world scenarios. Whether you’re writing your first Trigger or looking to improve existing ones, this guide gives you the foundation you need to succeed.
Need help building out a scalable Trigger framework? Drop a comment or explore more Salesforce developer tutorials.
🔗 Internal Resources
🌐 External Resources
📖 FAQs
❓How do I know whether to use a before or after trigger in Salesforce
Use a before trigger when you need to modify field values before they are saved to the database. Use an after trigger when you need to access record IDs or perform actions that require the record to be committed.
❓Can I have multiple triggers on the same Salesforce object
Technically yes, but it’s a best practice to use only one trigger per object and delegate logic to handler classes. This improves readability and reduces the risk of unexpected behavior.
❓What is the difference between Trigger.new and Trigger.old
Trigger.new holds the new versions of the records being processed, while Trigger.old holds the previous versions. Trigger.old is only available in update and delete contexts.
❓How do I make my Apex Trigger bulk-safe
Avoid using SOQL or DML statements inside loops. Instead, collect data in collections like sets or lists, then perform queries and updates outside the loop.
❓Why is recursion a problem in Apex Triggers
Recursion can cause infinite loops or exceed governor limits if a trigger causes another trigger to fire repeatedly. Use static variables to detect and prevent recursive execution.