This pattern will help you write Process Builder that can be activated or deactivated based on Profile or Permission Set assigned to user.
Naming Pattern
Component | Name |
Main Process Builder | ObjectName_PBXXX_Main Ex: Account_PB001_Main |
Invocable Sub Process Builder | ObjectName_PBXXX_Sub_XXX Ex: Account_PB001_Sub_003 |
Guidelines
Number | Rule |
---|---|
1 | 1 Main Process Builder per Object |
2 | 1 developer working on 1 Process Builder at a time |
3 | Avoid deleting Process Builder, deactivate them |
4 | Draft should not be deployed |
5 | Draft should be deleted to maintain consistency in version number |
6 | Modify Process Builder only on development sandbox |
7 | Have a reference sandbox to easily align Process Builder list |
8 | Process Builder should replace everything covered by workflow whenever possible |
9 | Invocable Process Builder must be created and activated first in order to use it in Main Process Builder |
10 | The order and the number affect to invocable is not important, only the main Process Builder has knowledge on which order they are called |
11 | The main Process Builder is like an orchestrator, logics should be as simple as possible, complexity is handle by invocable |
12 | The main Process Builder should handle decision block based on object status, a step, on crud operation or a particular field with lifecycle element. the whole has to be consistent. |
13 | Avoid chainable blocs with “evaluate next” and avoid having many crud blocs, because each bloc is an individual process that will fire trigger and consume lot of resources. |
14 | Avoid updating the object that start the process as it will fire triggers again, better is to do it in Before events. |
15 | Don’t mix too much Process Builder, Flow and triggers, it will complexify the whole solution. |
Step 1
Create 3 Custom Permissions to handle activation and deactivation of the rule.
Name | |
Permission 1 | BP_ALL_PB |
Permission 2 | BP_ACC_PB001_MAIN |
Permission 3 | BP_ACC_PB001_SUB_001 |
The first one will be used to deactivate all Process Builder when the Custom Permission is assigned Profile or Permission Set.
The second one will be used to deactivate only this Main Process Builder.
The third one will be used to deactivate only the first Invocable Process Builder.
Step 2
Before creating the process, we need to build our bypassing framework. I will create 2 types of bypass, one based on Custom Permission and another based on a specific criteria, in this example it will be country based.
First of all, go and create an APEX Class like this one:
public inherited sharing class PIC001_Void{
@InvocableMethod(label='Void' description='Void')
public static void doVoid(){}
}
Void, this class and method are meant to do nothing. It’s an empty action that will be useful to bypass our Process Builder. A Process Builder can call an Apex method with the annotation @InvocableMethod.
Step 3
Start creating a Custom Metadata Type that we will call “ProcessBuilders”. The reason behind is that it helps configuration to be deployed easily between orgs which is not the case of custom settings records that need to be handle manually. In the past we were adding this kind of information in the user Object but it doesn’t give the flexibility we have with this new settings implementation.
Alternatively, you can move this to Custom setting (hierarchical or not) but it implies more steps and more hard-coding from my point of view.
Step 4
Create a Text Field with length of 255 that we will call “Countries”. Picklist or Multi-Picklist are currently not supported in Custom Metadata types.
Step 5
Populate some records for our first Process Builder that we are going to write.
Label | Name | Countries |
---|---|---|
Account_PB001_Main | Account_PB001_Main | FR;GB |
Account_PB001_Sub_001 | Account_PB001_Sub_001 | FR |
If your rule is meant to be applied to all countries then you can leave the field blank or add a default value ‘*’ for example.
Use a separator like ‘;’ between each country.
Step 6
We are going to write a simple Process Builder for the Account object.
Name | Account_PB001_Sub_001 |
Description | This is a POC. |
Process Type | Invocable |
Object | Account |

The first decision bloc will evaluate the bypass criteria, notice that we first check the global bypass, then the main bypass, then the local bypass and then any special criteria like country code.
$Permission.BP_ALL_PB
|| $Permission.BP_ACC_PB001_MAIN
|| $Permission.BP_ACC_PB001_SUB_001
||NOT( CONTAINS($CustomMetadata.ProcessBuilder__mdt.Account_PB001_Sub_001.Countries__c ,'*' ) ||
CONTAINS($CustomMetadata.ProcessBuilder__mdt.Account_PB001_Sub_001.Countries__c , [Account].BillingCountry )
)
Now you can assign an action for the bypass decision block, you can use an action to call Apex Class and in this case we will choose the previously created Void method. To test things working, I have implemented a decision block which will be always evaluated to true (like a ELSE) and which will post a message to record feed.
The Invocable Process Builder should run and post a message :
- The user has no global or local bypass assigned
- The record Billingcountry is FR
Important: If you update the API name of the record of the Custom Metadata Type, it WILL NOT update automatically the reference in your Process Builder like it will do with Validation Rules.
Step 7
Let’s write now the main Process Builder that will trigger the invocable one.
Name | Account_PB001_Main |
Description | This is a POC. |
Process Type | Record Change |
Object | Account |

The first decision bloc will evaluate the bypass criteria, notice that we first check the global bypass, then the main bypass and then any special criteria like country code.
$Permission.BP_ALL_PB
|| $Permission.BP_ACC_PB001_MAIN
|| NOT(
CONTAINS($CustomMetadata.ProcessBuilder__mdt.Account_PB001_Main.Countries__c,'*')
|| CONTAINS($CustomMetadata.ProcessBuilder__mdt.Account_PB001_Main.Countries__c,[Account].BillingCountry ))
Now you can assign an action for the bypass decision block, you can use an action to call Apex Class and in this case we will choose the previously created Void method. To test things working,
The 2 other decision blocks are the way we design Process Builder, in this case the orchestrator will handle 1 sub process for new records and 1 sub process for updated records. Instead of new and update decision blocks, you could have the main steps of a process (Ex: Opportunity sales path).
Conclusion
Now you are able to control every step of your Process Builder and bring high level of flexibility in the design. Working on process builder is tricky for many reasons (large teams, dependent features, maintenance, flexibility…) but with a good consistent design you will overcome those issues.
Hope you enjoy reading this article, see you soon for the next one ...