Skip to content

AfterInsert

Runs in after insert, after new records are saved. The records have Ids and are read-only. Write other records with a Writer or start async work with a Dispatcher.

Roles

  • Writer: create, update or delete other records, or publish events, through a unit of work that commits with the save.
  • Dispatcher: make one bulk call per chunk, such as enqueueing a Queueable.

Add-ons

  • ParentQuery: load parent (lookup) fields before the first handler runs; read them with getNewParent.
  • RelatedQuery: query children, siblings or any other records once per chunk; read them with getRelated.
  • OwnUnitOfWork: give the handler its own unit of work, committed right after it. Writer only.
  • Bypassable: skip this handler for the whole chunk when a condition holds.
  • Finalizer: run once after this handler’s records, with the records that qualified.
  • ContinueOnError: log and swallow this handler’s exceptions, so the save goes on.

Register

Implement TriggerOrchestrator.AfterInsert on the orchestrator and return the handlers from afterInsertHandlers(). List order is run order. The trigger must list after insert and call TriggerOrchestrator.run(new ContactTriggerOrchestrator()).

apex
public with sharing class ContactTriggerOrchestrator implements TriggerOrchestrator.AfterInsert {
    public List<AfterInsert.Handler> afterInsertHandlers() {
        return new List<AfterInsert.Handler>{ new ContactWriter(), new ContactDispatcher() };
    }
}

Good to Know

  • Read-only rows. record.put(…) compiles, but it throws a System.FinalException that nothing can catch, and the insert fails. Set fields on the new record in a BeforeInsert.Populator.
  • Lookups hold only the Id. ((Contact) record.getNewSObject()).Account is null. Declare a ParentQuery and read record.getNewParent('Account').
  • Updating the new record saves it again. A Writer's toUpdate(new Contact(Id = record.getId(), …)) runs before update and after update for it. When the value is known before the save, set it in a BeforeInsert.Populator instead.
  • One role per class. A class that implements both roles runs only as a Writer.
  • Called per chunk. A 1,000-record insert is 5 runs, so each Dispatcher and Finalizer can run 5 times. Static fields keep their values across chunks.