Skip to main content

Disabling Automations

Salesforce automation is any code/logic that is run automatically when a record is created/updated/deleted. There are many type of such automations as listed below.

  • Apex Trigger
  • Validation Rule
  • Workflow Rule
  • Process Builder
  • Flow

These automations are great to implement business logic but a hindrance if we want to dataload some data without having to run any of these automations. If it is a sandbox we could possibly disable these one by one and dataload but that is not an acceptable solution for production systems.

We need a mechanism skip these automations for one or more users (For ex., system user which is used to dataload). This page details one such framework that helps with disabling these automations at User level.

In all cases, we need to update our components to embed logic to short-cut the automation based on the user level configuration. While this page gives examples for each of these, it is responsibility of each Developer to ensure these short-cut logic is embedded either as new components is introduced or retroactively for past-items.

info

This page documents one such framework to disable automations, this is not only the way to implement such mechanism. Your org/team may have their own, and it is fine. Important thing is being consistent in approach and adopting this across all component.

New Field - One Time

  • Create User object checkbox field Disable_Automations__c.
  • Grant Read access to all profiles and edit access to System Administrator profile

If this field is checked, then it is intended that automations should be skipped for that user. Since changes to User record are tracked in Setup trial, you will have a record each time it is enabled/disabled for a User

Apex Trigger

Apex triggers needs bit of framework code which is one time change. After that, each trigger needs to be updated with same snippet of which bypasses the trigger.

Apex Trigger - One Time

  • Create following main class
public without sharing class TriggerService {
public static TriggerService instance = new TriggerService();
private static Boolean disabledForUser = null;

public Boolean isDisabled() {
if (isDisabledForUser()) {
System.debug('Triggers are disabled for user [' + UserInfo.getUsername() + ']');
return true;
}

return false;
}

private Boolean isDisabledForUser() {
if (disabledForUser == null) {
User user = [select Disable_Automations__c from User where Id = :UserInfo.getUserId()];
disabledForUser = user.Disable_Automations__c;
}

return disabledForUser;
}
}
  • Add following test class
tba;

Apex Trigger - For Each

Add following piece of code each of your Triggers

if (TriggerService.instance.isDisabled()) {
return;
}

For ex., your trigger class should look like this after adding the snippet

trigger OpportunityTrigger on Opportunity (before insert, after insert, before update, after update, before delete , after delete, after undelete) {
if (TriggerService.instance.isDisabled()) {
return;
}

// other trigger logic
}
caution

There will be one SOQL execution for each Transaction (irrespective of number of triggers are run in that transaction), this will count towards your limit. If you are already in the verge of reaching the SOQL limit, then you can consider making use of Platform Cache to cache the status for each user, which can be cached for upto 2 days.

Validation Rule - For Each

Add below logic as first operator in your validation rule.

AND(NOT($User.Disable_Automations__c), <exiting val rule>)

For ex., here is sample Validation before and after adding the short-cut logic.

Before

AND(
OR(
ISPICKVAL(Stage__c, "Expired"),
ISPICKVAL(Stage__c, "Inactive"),
ISPICKVAL(Stage__c, "Replaced"),
ISPICKVAL(Stage__c, "Voided"),
ISPICKVAL(Stage__c, "Withdrawn")
),
ISPICKVAL(Actions__c, "On Hold")
);

After

AND(
NOT($User.Disable_Automations__c),
AND(
OR(
ISPICKVAL(Stage__c, "Expired"),
ISPICKVAL(Stage__c, "Inactive"),
ISPICKVAL(Stage__c, "Replaced"),
ISPICKVAL(Stage__c, "Voided"),
ISPICKVAL(Stage__c, "Withdrawn")
),
ISPICKVAL(Actions__c, "On Hold")
)
);

Workflow Rule - For Each

Workflows have three different ways of specifying the conditional logic.

  • Filters without Filter Logic
  • Filters with Filter Logic
  • Formula

Each of these needs to be addressed little differently.

Workflow Rule - Filters without Filter Logic

Add a new condition which checks User flag along with other conditions.

Before

After

Workflow Rule - Filters with Filter Logic

Before

After

Workflow Rule - Formula

If it is formula, enclose the whole formula with following construct

AND(NOT($User.Disable_Automations__c), <exiting logic>)

Process Builder

Process builder needs two aspects to be able to bypass it. A criteria which checks if current user has automations disabled and dummy action which does nothing. To facilitate the dummy action, we created apex class with invocable apex method called DoNothingAction which we can use as Process Builder Action.

Select the Process Builder/Version that you want to edit. If it has been activated prior, you can make a copy of it and follow these steps to add bypass logic.

Process Builder - One Time

  • Create Following main class (DoNothingAction.cls)
public class DoNothingAction {
@InvocableMethod
public static void doNothing() {
// As name indicates this method is used in Workflows to bypass automations.
// This method must do nothing.
}
}
  • And its corresponding test class (DoNothingActionTest.cls)
@Istest
public class DoNothingActionTest {

@IsTest
public static void doNothingTest() {
DoNothingAction.doNothing();
}

}
  • Grant access to DoNothingAction apex class to all profiles

Process Builder - For Each

Go through the steps and add a decision which checks if it is disabled for current user and if it is executes DoNothigAction

  • Let’s say we want to change below process builder.

  • Add a new criteria at the bottom and set Condition as Formula as $User.Disable_Automations__c

  • Add Apex Action to that criteria and select Apex class DoNothingAction

  • Drag the criteria and drop it as First in the list.

  • That’s it, now process would be terminated immediately soon after it was started.

Flows - For Each

We need to update only auto-launched flows as Screen Flows are usually manually invoked. Follow these steps to edit one such automated-flow.

  • Open the Flow you want to edit (in this, we are using an example flow we tested for this demo)

  • Add Decision Element just after Start and Configure to check for User.Disable_Automations__c field

  • After configuring the above example flow should look like this

  • That’s it, now flow would be terminated immediately soon after it was started.