
Each flow interview runs in the context of a transaction. A transaction is a collection of operations that are performed as a single unit. In addition to a flow interview, a transaction can execute Apex triggers and escalation rules.
💼 Use Case
You’ve developed a flow that executes whenever something changes in the Account object and you’re updating its associated contact object. There is an Apex Trigger written on the contact object, which you do not want to execute when updating records from the flow.
✅ Solution
Create an Apex class
/*********************************************************************************** | |
Class Name : TriggerSwitchCls | |
Description : This class can be used to stop the trigger execution for a transaction. | |
Created By : SFDC Lessons | |
Created Date : 09/06/2022 | |
Modification Logs: | |
------------------------------------------------------------------------------------ | |
Developer Date Descriptions | |
------------------------------------------------------------------------------------- | |
Arun Kumar 09/06/2022 Initial version | |
*************************************************************************************/ | |
public class TriggerSwitchCls { | |
public static Boolean accountTriggerRunFlag = true; | |
public static Boolean opportunityTriggerRunFlag = true; | |
public static Boolean contactTriggerRunFlag = true; | |
public static Boolean opportunityLineItemTriggerRunFlag = true; | |
public static Boolean userTriggerRunFlag = true; | |
public static Boolean leadTriggerRunFlag = true; | |
//Account Trigger Switch Logic | |
public static Boolean canAccountTriggerExecute(){ | |
return accountTriggerRunFlag; | |
} | |
public static void stopAccccountTrigger(){ | |
accountTriggerRunFlag = false; | |
} | |
public static void allowAccountTrigger(){ | |
accountTriggerRunFlag = true; | |
} | |
//Opportunity Trigger Switch Logic | |
public static Boolean canOpportunityTriggerExecute(){ | |
return opportunityTriggerRunFlag; | |
} | |
public static void stopOpportunityTrigger(){ | |
opportunityTriggerRunFlag = false; | |
} | |
public static void allowOpportunityTrigger(){ | |
opportunityTriggerRunFlag = true; | |
} | |
//Contact Trigger Switch Logic | |
public static Boolean canContactTriggerExecute(){ | |
return contactTriggerRunFlag; | |
} | |
public static void stopContactTrigger(){ | |
contactTriggerRunFlag = false; | |
} | |
public static void allowContactTrigger(){ | |
contactTriggerRunFlag = true; | |
} | |
//OpportunityLineItem Trigger Switch Logic | |
public static Boolean canOLITriggerExecute(){ | |
return opportunityLineItemTriggerRunFlag; | |
} | |
public static void stopOLITrigger(){ | |
opportunityLineItemTriggerRunFlag = false; | |
} | |
public static void allowOLITrigger(){ | |
opportunityLineItemTriggerRunFlag = true; | |
} | |
//User Trigger Switch Logic | |
public static Boolean canUserTriggerExecute(){ | |
return userTriggerRunFlag; | |
} | |
public static void stopUserTrigger(){ | |
userTriggerRunFlag = false; | |
} | |
public static void allowUserTrigger(){ | |
userTriggerRunFlag = true; | |
} | |
//Lead Trigger Switch Logic | |
public static Boolean canLeadTriggerExecute(){ | |
return leadTriggerRunFlag; | |
} | |
public static void stopLeadTrigger(){ | |
leadTriggerRunFlag = false; | |
} | |
public static void allowLeadTrigger(){ | |
leadTriggerRunFlag = true; | |
} | |
//** Duplicate the above methods for other objects */ | |
} |
The above class method can be used to stop the trigger execution.
Contact Trigger
In line 11, you can see that I used the TriggerSwitchCls method to determine whether the trigger code should be executed or not. This method returns TRUE or FALSE depending on the static boolean variable set in the method.
/** | |
* @description ContactTrigger. | |
* @Created By: Arun Kumar | |
* @Created Date : 26-06-2022 | |
* @Last Modified Date : 26-06-2022 | |
*/ | |
trigger ContactTrigger on Contact (before insert,before update, before delete, after insert, after update, after delete,after undelete) { | |
// This "TriggerSwitchCls.canContactTriggerExecute()" will return TRUE or FALSE. By default it will return TRUE and | |
//if we bypass this in flow then it will return FALSE and trigger will be bypassed. | |
if(TriggerSwitchCls.canContactTriggerExecute()){ | |
System.debug('Inside Contact Trigger'); | |
TriggerHandler handler = new ContactTriggerHandler(Trigger.isExecuting, Trigger.size); | |
switch on Trigger.operationType { | |
when BEFORE_INSERT { | |
//call before insert handler method | |
handler.beforeInsert(Trigger.new); | |
} | |
when BEFORE_UPDATE { | |
//call before update handler method | |
handler.beforeUpdate(Trigger.new, Trigger.old, Trigger.newMap, Trigger.oldMap); | |
} | |
when BEFORE_DELETE{ | |
//call before delete handler method | |
handler.beforeDelete(Trigger.old, Trigger.oldMap); | |
} | |
when AFTER_INSERT{ | |
//call after insert handler method | |
handler.afterInsert(Trigger.new,Trigger.newMap); | |
} | |
when AFTER_UPDATE{ | |
//call after update handler method | |
handler.afterUpdate(Trigger.new, Trigger.old, Trigger.newMap, Trigger.oldMap); | |
} | |
when AFTER_DELETE{ | |
//call after delete handler method | |
handler.afterDelete(trigger.old, Trigger.oldMap); | |
} | |
when AFTER_UNDELETE{ | |
//call after undelete handler method | |
handler.afterUndelete(trigger.new, Trigger.newMap); | |
} | |
} | |
} | |
} |
Now create two different classes to stop and allow the trigger from flow transaction. Each class will have an invocable method that calls the TriggerSwitchCls method to set the static boolean variable to TRUE or FALSE.
/*********************************************************************************** | |
Class Name : StopTriggerHandler | |
Description : This class can be used in the PB, flow to do the actions defined in the methods. | |
Created By : SFDC Lessons | |
Created Date : 09/06/2022 | |
Modification Logs: | |
------------------------------------------------------------------------------------ | |
Developer Date Descriptions | |
------------------------------------------------------------------------------------- | |
Arun Kumar 09/06/2022 Initial version | |
*************************************************************************************/ | |
public class StopTriggerHandler { | |
/** | |
* @description stopTrigger method can be called from PB/FLOWs to stop the object trigger for a transaction. | |
* @param triggerNameToStop | |
*/ | |
@InvocableMethod(label='Stop sObject Trigger' description='Stop the sObject trigger for this transaction') | |
Public static void stopTrigger(List<List<String>> triggerNameToStop){ | |
for(String varTrggrName: triggerNameToStop[0]){ | |
//switch statement checking trigger name and stoping the triggers | |
switch on varTrggrName { | |
when 'Account' { | |
TriggerSwitchCls.stopAccccountTrigger(); | |
} | |
when 'Opportunity' { | |
TriggerSwitchCls.stopOpportunityTrigger(); | |
} | |
when 'Contact' { | |
TriggerSwitchCls.stopContactTrigger(); | |
} | |
when 'OpportunityLineItem' { | |
TriggerSwitchCls.stopOLITrigger(); | |
} | |
when 'User' { | |
TriggerSwitchCls.stopUserTrigger(); | |
} | |
when 'Lead' { | |
TriggerSwitchCls.stopLeadTrigger(); | |
} | |
}//switch statement block ends here | |
}//for loop ends here | |
system.debug('Can Opportnity Trigger Execute ? : ' + TriggerSwitchCls.canAccountTriggerExecute()); | |
}//mehod ends here | |
} |
/*********************************************************************************** | |
Class Name : AllowTriggerHandler | |
Description : This class can be used in the PB, flow to do the actions defined in the methods. | |
Created By : SFDC Lessons | |
Created Date : 09/06/2022 | |
Modification Logs: | |
------------------------------------------------------------------------------------ | |
Developer Date Descriptions | |
------------------------------------------------------------------------------------- | |
Arun Kumar 09/06/2022 Initial version | |
*************************************************************************************/ | |
public class AllowTriggerHandler { | |
/** | |
* @description stopTrigger method can be called from PB/FLOWs to allow the sObject trigger for a transaction. | |
* @param triggerNameToAllow | |
*/ | |
@InvocableMethod(label='Allow sObject Trigger to execute' description='Allow the sObject trigger for this transaction') | |
Public static void allowTrigger(List<List<String>> triggerNameToAllow){ | |
for(String varTrggrName: triggerNameToAllow[0]){ | |
//switch statement checking trigger name and stoping the triggers | |
switch on varTrggrName { | |
when 'Account' { | |
TriggerSwitchCls.allowAccountTrigger(); | |
} | |
when 'Opportunity' { | |
TriggerSwitchCls.allowOpportunityTrigger(); | |
} | |
when 'Contact' { | |
TriggerSwitchCls.allowContactTrigger(); | |
} | |
when 'OpportunityLineItem' { | |
TriggerSwitchCls.allowOLITrigger(); | |
} | |
when 'User' { | |
TriggerSwitchCls.allowUserTrigger(); | |
} | |
when 'Lead' { | |
TriggerSwitchCls.allowLeadTrigger(); | |
} | |
}//switch statement block ends here | |
}//for loop ends here | |
}//mehod ends here | |
} |
To stop the object trigger execution, call the invocable method stopTrigger(objectName) in the flow. You simply need to pass the name of the object for which you want to bypass the trigger.
🚶Steps to Implement the Solution in Flow
Click on the New Resources button in the flow builder and create a collection variable to store the object name.

Enter the API Name, description and select the checkbox to allow multiple values (collection).

The next step is to add values to this collection.
Select the assignment element and add the string ‘Contact‘ to this variable.

Add an Action element before the Update Record element.

In the Action lookup field selects the “Stop sObject Trigger” invocable action.

Enter the label and API name, then enable the toggle button and select the collection variable in the triggerNameToStop field.

After Update Records element, add Apex action to allow the Contact trigger to execute.
Select ‘Allow sObject Trigger to execute‘ apex action.

Enter the label and API name, then enable the toggle button and select the collection variable in the triggerNameToStop field.


Finally, the flow will look like the screenshot below.

When flow updates a contact record, the contact trigger no longer executes.
Summary
You may have encountered the CPU time limit exceeded if you doing a bulk record upload. This is usually due to multiple automation tools (Flow, PB, Trigger) running and not being developed properly. If you look at the debug log, you might notice that the DML you’re doing in the flow again calls the apex trigger/PB. We can bypass and allow apex trigger in flow transactions with the help of the apex invocable method a boolean static variable. However, automation tools should be written in such a way that they do not call each other back and forth, and proper conditions should be added to trigger code to execute the code in the exact use case.