This is my own solution which helps to controll trigger execution.

It is simple to use. See Trigger template with execution control for more details.

Class: TriggerExecutionController

/**
 * @author      Pawel Wozniak
 * @created     2018-11-05
 * @updated     2018-11-06 v1.1
*/

/** HOW TO USE: 
  1. Define Rules in Custom Metadata "Trigger Execution Control" (Trigger_Execution_Control__mdt), create new record with those values:
  - Profile Id (Profile_Id__c) - leave blank for all profiles or specify 18 characters profile Id.
  - Trigger Class Name (Trigger_Class_Name__c) - your apex trigger class name
  - Trigger Operation (Trigger_Operation__c) - possible values: BEFORE_INSERT, AFTER_INSERT, BEFORE_UPDATE, AFTER_UPDATE, BEFORE_DELETE, AFTER_DELETE, AFTER_UNDELETE
  - Is Disabled (Is_Disabled__c) - check it to disable operation execution.
 
  IMPORTANT: If no records are found then execution is enabled by default. With this approach you don't need to have rule for every trigger and operation type.
 
  2. Usage in trigger:
  a) Speed optimized way, if short execution time is important (recommended).
  - in first line of trigger body insert --> TriggerExecutionController tec = new TriggerExecutionController('HerePutTriggerClassName'); <--
  - in trigger logic use --> if (tec.eventTypeDisabled) { return; } <-- this will stop execution if operation is disabled.
 
  b) Comfortable way, class name and operation type are recognized automatically:
  - in first line of trigger body insert --> TriggerExecutionController tec = new TriggerExecutionController(this); <--
  - in trigger logic use --> if (tec.isDisabled()) { return; } <-- this will stop execution if operation is disabled.
 
 **/

public class TriggerExecutionController {

    private String triggerClassName = null;
    // Cache for limiting SOQL queries. Map key is a ApexClassName as tecCache is shared across all triggers that are in execution context.
    private static Map<String, List<Trigger_Execution_Control__mdt>> tecCache = new Map<String, List<Trigger_Execution_Control__mdt>> ();

    public Boolean beforeInsertDisabled = false;
    public Boolean afterInsertDisabled = false;
    public Boolean beforeUpdateDisabled = false;
    public Boolean afterUpdateDisabled = false;
    public Boolean beforeDeleteDisabled = false;
    public Boolean afterDeleteDisabled = false;
    public Boolean afterUnDeleteDisabled = false;

    // Class name as String
    public TriggerExecutionController(String triggerClassName) {
        this.triggerClassName = triggerClassName;
        getSettingsFromCustomMetadata();
    }

    // Class itself passed as paremeter using this keyword
    public TriggerExecutionController(Object triggerClass) {
        this.triggerClassName = String.valueOf(triggerClass).split(':') [0].trim();
        getSettingsFromCustomMetadata();
    }

    // Public methods
    public Boolean isDisabled() {
        System.TriggerOperation triggerEvent = Trigger.operationType;
        switch on triggerEvent {
            when BEFORE_INSERT { return this.beforeInsertDisabled; }
            when AFTER_INSERT { return this.afterInsertDisabled; }
            when BEFORE_UPDATE { return this.beforeUpdateDisabled; }
            when AFTER_UPDATE { return this.afterUpdateDisabled; }
            when BEFORE_DELETE { return this.beforeDeleteDisabled; }
            when AFTER_DELETE { return this.afterDeleteDisabled; }
            when AFTER_UNDELETE { return this.afterUnDeleteDisabled; }
        }
        return false;
    }

    // Private methods - helpers
    private void getSettingsFromCustomMetadata() {
        Id runningUserProfileId = UserInfo.getProfileId();

        if (!tecCache.containsKey(this.triggerClassName)) {
            tecCache.put(this.triggerClassName,
                         [SELECT Profile_Id__c, Trigger_Class_Name__c, Trigger_Operation__c, Is_Disabled__c
                         FROM Trigger_Execution_Control__mdt
                         WHERE Trigger_Class_Name__c = : this.triggerClassName AND Is_Disabled__c = TRUE
                         AND(Profile_Id__c = NULL OR Profile_Id__c = : runningUserProfileId)]);

        }

        for (Trigger_Execution_Control__mdt tec : tecCache.get(this.triggerClassName)) {
            if (tec.Trigger_Operation__c == 'BEFORE_INSERT') { this.beforeInsertDisabled = true; notifyInDebug(tec.Trigger_Operation__c); }
            if (tec.Trigger_Operation__c == 'AFTER_INSERT') { this.afterInsertDisabled = true; notifyInDebug(tec.Trigger_Operation__c); }
            if (tec.Trigger_Operation__c == 'BEFORE_UPDATE') { this.beforeUpdateDisabled = true; notifyInDebug(tec.Trigger_Operation__c); }
            if (tec.Trigger_Operation__c == 'AFTER_UPDATE') { this.afterUpdateDisabled = true; notifyInDebug(tec.Trigger_Operation__c); }
            if (tec.Trigger_Operation__c == 'BEFORE_DELETE') { this.beforeDeleteDisabled = true; notifyInDebug(tec.Trigger_Operation__c); }
            if (tec.Trigger_Operation__c == 'AFTER_DELETE') { this.afterDeleteDisabled = true; notifyInDebug(tec.Trigger_Operation__c); }
            if (tec.Trigger_Operation__c == 'AFTER_UNDELETE') { this.afterUnDeleteDisabled = true; notifyInDebug(tec.Trigger_Operation__c); }

        }
    }

    private void notifyInDebug(String triggerEvent) {
        // Add info in debug log to clearly state that trigger was disabled. Save time in case something should work but it isn't.
        System.debug('#INFO# In trigger ' + this.triggerClassName + ' operation ' + triggerEvent + ' is DISABLED. #INFO#');
    }
}

 

Custom metadata object: Trigger_Execution_Control__mdt

<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <fields>
        <fullName>Is_Disabled__c</fullName>
        <defaultValue>false</defaultValue>
        <externalId>false</externalId>
        <fieldManageability>SubscriberControlled</fieldManageability>
        <label>Is Disabled</label>
        <type>Checkbox</type>
    </fields>
    <fields>
        <fullName>Profile_Id__c</fullName>
        <externalId>false</externalId>
        <fieldManageability>SubscriberControlled</fieldManageability>
        <inlineHelpText>Salesforce 18 characters Profile Id. Empty value = For all users</inlineHelpText>
        <label>Profile Id</label>
        <length>18</length>
        <required>false</required>
        <type>Text</type>
        <unique>false</unique>
    </fields>
    <fields>
        <fullName>Trigger_Class_Name__c</fullName>
        <externalId>false</externalId>
        <fieldManageability>SubscriberControlled</fieldManageability>
        <inlineHelpText>Settings used for disabling trigger operation execution.</inlineHelpText>
        <label>Trigger Class Name</label>
        <length>80</length>
        <required>true</required>
        <type>Text</type>
        <unique>false</unique>
    </fields>
    <fields>
        <fullName>Trigger_Operation__c</fullName>
        <defaultValue>&apos;&apos;</defaultValue>
        <externalId>false</externalId>
        <fieldManageability>SubscriberControlled</fieldManageability>
        <label>Trigger Operation</label>
        <required>false</required>
        <type>Picklist</type>
        <valueSet>
            <restricted>true</restricted>
            <valueSetDefinition>
                <sorted>false</sorted>
                <value>
                    <fullName>BEFORE_INSERT</fullName>
                    <default>true</default>
                    <label>BEFORE_INSERT</label>
                </value>
                <value>
                    <fullName>AFTER_INSERT</fullName>
                    <default>false</default>
                    <label>AFTER_INSERT</label>
                </value>
                <value>
                    <fullName>BEFORE_UPDATE</fullName>
                    <default>false</default>
                    <label>BEFORE_UPDATE</label>
                </value>
                <value>
                    <fullName>AFTER_UPDATE</fullName>
                    <default>false</default>
                    <label>AFTER_UPDATE</label>
                </value>
                <value>
                    <fullName>BEFORE_DELETE</fullName>
                    <default>false</default>
                    <label>BEFORE_DELETE</label>
                </value>
                <value>
                    <fullName>AFTER_DELETE</fullName>
                    <default>false</default>
                    <label>AFTER_DELETE</label>
                </value>
                <value>
                    <fullName>AFTER_UNDELETE</fullName>
                    <default>false</default>
                    <label>AFTER_UNDELETE</label>
                </value>
            </valueSetDefinition>
        </valueSet>
    </fields>
    <label>Trigger Execution Control</label>
    <listViews>
        <fullName>All</fullName>
        <columns>DeveloperName</columns>
        <columns>Profile_Id__c</columns>
        <columns>Trigger_Class_Name__c</columns>
        <columns>Trigger_Operation__c</columns>
        <columns>Is_Disabled__c</columns>
        <filterScope>Everything</filterScope>
        <label>All</label>
        <language>en_US</language>
    </listViews>
    <pluralLabel>Trigger Execution Controls</pluralLabel>
    <validationRules>
        <fullName>Profile_Id_must_be_18_characters_long</fullName>
        <active>true</active>
        <errorConditionFormula>LEN(Profile_Id__c) &lt; 18 &amp;&amp; NOT(ISBLANK(Profile_Id__c))</errorConditionFormula>
        <errorDisplayField>Profile_Id__c</errorDisplayField>
        <errorMessage>Profile Id must be 18 characters long or null if rule is for all users.</errorMessage>
    </validationRules>
    <visibility>Public</visibility>
</CustomObject>

 

Example entry: Trigger_Execution_Control.Opportunity_Trigger_Before_Update.md

<?xml version="1.0" encoding="UTF-8"?>
<CustomMetadata xmlns="http://soap.sforce.com/2006/04/metadata" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <label>Opportunity Trigger Before Update</label>
    <protected>false</protected>
    <values>
        <field>Is_Disabled__c</field>
        <value xsi:type="xsd:boolean">false</value>
    </values>
    <values>
        <field>Profile_Id__c</field>
        <value xsi:type="xsd:string">00e0Y0000014BSgQAM</value>
    </values>
    <values>
        <field>Trigger_Class_Name__c</field>
        <value xsi:type="xsd:string">Opportunity_Trigger</value>
    </values>
    <values>
        <field>Trigger_Operation__c</field>
        <value xsi:type="xsd:string">BEFORE_UPDATE</value>
    </values>
</CustomMetadata>

.

   
© Paweł Woźniak