Skip to content

AfterInsert.Bypassable

Skips a Writer or Dispatcher for the whole chunk when a condition holds, such as a static flag or a custom permission. The handler's other contexts are not affected.

Interface

apex
public class AfterInsert {
    public interface Bypassable {
        Boolean bypassOnAfterInsertWhen();
    }
}
  • bypassOnAfterInsertWhen(): called once per chunk, before parents load; not called when metadata or TriggerOrchestrator.bypass() already skips the handler. Returns true to skip this handler for this chunk.

Example

apex
public with sharing class ContactWriter implements AfterInsert.Writer, AfterInsert.Bypassable {
    public static Boolean isDisabled = false;

    public Boolean bypassOnAfterInsertWhen() {
        return ContactWriter.isDisabled;
    }

    public Boolean writeOnAfterInsertWhen(TriggerHandler.InsertRecord record) {
        return record.isNotNull(Contact.AccountId);
    }

    public void writeOnAfterInsert(TriggerHandler.InsertRecord record, TriggerHandler.UnitOfWork unitOfWork) {
        unitOfWork.toInsert(new Task(WhatId = ((Contact) record.getNewSObject()).AccountId, Subject = 'Review contact'));
    }
}
cls
public with sharing class ContactOwnerAlignmentWriter implements AfterInsert.Writer, AfterInsert.ParentQuery, AfterInsert.Bypassable {
    public static Boolean isDisabled = false;

    public Map<SObjectField, TriggerHandler.ParentFields> queryParentsOnAfterInsert() {
        return new Map<SObjectField, TriggerHandler.ParentFields>{ Contact.AccountId => TriggerHandler.ParentFields.with(Account.OwnerId).with('Owner', User.IsActive) };
    }

    public Boolean bypassOnAfterInsertWhen() {
        return ContactOwnerAlignmentWriter.isDisabled;
    }

    public Boolean writeOnAfterInsertWhen(TriggerHandler.InsertRecord record) {
        Contact contactRecord = (Contact) record.getNewSObject();
        Account accountRecord = (Account) record.getNewParent('Account');

        return accountRecord?.Owner?.IsActive == true && accountRecord.OwnerId != contactRecord.OwnerId;
    }

    public void writeOnAfterInsert(TriggerHandler.InsertRecord record, TriggerHandler.UnitOfWork unitOfWork) {
        Account accountRecord = (Account) record.getNewParent('Account');

        unitOfWork.toUpdate(new Contact(Id = record.getId(), OwnerId = accountRecord.OwnerId));
    }
}

Good to Know

  • Skip single records in the predicate. Bypassable switches off the whole handler.
  • Checked before the first handler runs. A flag that an earlier handler sets takes effect from the next chunk.
  • Outside the error handling. An exception from bypassOnAfterInsertWhen() is not logged, ContinueOnError does not apply, and the insert fails.
  • Static flags last the transaction. ContactOwnerAlignmentWriter.isDisabled = true stays set for every later chunk and nested save until you reset it.
  • Class switches miss inner classes. TriggerOrchestrator.bypass().handler(X.class) and .orchestrator(X.class) do not match an inner class. Use a TriggerHandler__mdt record or this interface. See Bypassing.