Top Apex Trigger Interview Questions & Answers (2025) — Real Scenarios & Code

A concise, interview-focused guide to Apex triggers: definitions, real-world scenarios, code examples, bulkification, recursion handling, and best practices every Salesforce developer should know in 2025.

What is an Apex Trigger and when to use it?

An Apex trigger is Apex code that runs before or after DML events (insert, update, delete, undelete). Use triggers when declarative tools cannot enforce complex cross-object business logic or when you need real-time server-side automation (for example, updating related records when a parent record changes).

Trigger Types: Before vs After

Before triggers modify or validate records before they’re saved (good for data normalization). After triggers run after records are committed and are used to access generated fields like Id or to perform actions that require record persistence.

Example

trigger AccountTrigger on Account (before insert, after insert) {
    if(Trigger.isBefore && Trigger.isInsert){
        for(Account acc : Trigger.new){
            acc.Name = acc.Name + ' - Verified';
        }
    }
    if(Trigger.isAfter && Trigger.isInsert){
        System.debug('Account Created with Id: ' + Trigger.new[0].Id);
    }
}

Preventing Recursive Triggers

Recursive triggers cause infinite loops when a trigger updates records that cause the same trigger to run again. Use a static flag in a helper class to prevent re-entry within the same transaction.

public class TriggerHelper {
    public static Boolean isExecuted = false;
}

trigger ContactTrigger on Contact (before update) {
    if(TriggerHelper.isExecuted) return;
    TriggerHelper.isExecuted = true;
    
    for(Contact con : Trigger.new){
        if(con.LastName != 'Test'){
            con.LastName = 'Test';
        }
    }
}

Bulkification: Handling 200 Records

Always assume the trigger will receive up to 200 records. Avoid SOQL/DML inside loops, use collections (Set, Map, List) and aggregate queries when appropriate.

// Bad: SOQL inside loop
for(Account acc : Trigger.new){
   Contact con = [SELECT Id FROM Contact WHERE AccountId = :acc.Id LIMIT 1];
}

// Good: single query, maps
Set accIds = new Set();
for(Account acc : Trigger.new){
    accIds.add(acc.Id);
}
Map> accToContacts = new Map>();
for(Contact con : [SELECT Id, AccountId FROM Contact WHERE AccountId IN :accIds]){
    if(!accToContacts.containsKey(con.AccountId)){
        accToContacts.put(con.AccountId, new List());
    }
    accToContacts.get(con.AccountId).add(con);
}

Context Variables & Order of Execution

Common context variables include Trigger.isInsert, Trigger.isUpdate, Trigger.isBefore, Trigger.isAfter, Trigger.new, Trigger.oldMap, etc. Interviewers often ask for the Order of Execution — be prepared to explain validation rules → before triggers → custom validations → after triggers → workflow/automation → commit → post-commit async logic.

Mixed DML and Asynchronous Workarounds

Performing DML on setup and non-setup objects in the same transaction triggers a Mixed DML Error. Use @future or Queueable Apex to separate transactions.

Best Practices for Trigger Design

  • One trigger per object.
  • Move logic into handler classes for testability and readability.
  • Always write bulk-safe code (Maps, Sets, Lists).
  • Handle recursion with static variables.
  • Prefer Flow declarative automation when it can solve the requirement.
  • Write unit tests with 75%+ coverage and realistic scenarios.

Example: Prevent Deletion of Accounts with Contacts

trigger AccountBeforeDelete on Account (before delete) {
    Set accIds = new Set();
    for(Account acc : Trigger.old){
        accIds.add(acc.Id);
    }
    
    Map accWithContacts = new Map(
        [SELECT AccountId, COUNT(Id) cnt FROM Contact WHERE AccountId IN :accIds GROUP BY AccountId]
    );
    
    for(Account acc : Trigger.old){
        if(accWithContacts.containsKey(acc.Id)){
            acc.addError('Cannot delete Account with Contacts!');
        }
    }
}

Conclusion

Understanding triggers — when to use them, how to bulkify, prevent recursion, and separate concerns — is critical for Salesforce developers and a frequent interview focus. Use handler classes, prefer declarative solutions where possible, and always write clean, testable Apex.

Why this matters: well-designed trigger logic keeps data consistent, reduces deployment risks, and improves system performance — essential for admins maintaining org health, developers building reliable integrations, and business stakeholders relying on accurate data.