Skip to content

AfterDelete

Runs in after delete, after records are deleted and before the transaction commits. Only the old values exist. Change other records with a Writer or hand work to a job with a Dispatcher.

Roles

  • Writer: create, update or delete other records through a unit of work.
  • Dispatcher: enqueue a job, send an email or publish events once per chunk.

Add-ons

  • PriorParentQuery: load the parent the old row pointed to; read it with getOldParent.
  • 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.AfterDelete on the orchestrator and return the handlers from afterDeleteHandlers(). List order is run order. The trigger must list after delete and call TriggerOrchestrator.run(new ContactTriggerOrchestrator()).

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

Good to Know

  • The rows are gone. getId() returns the deleted Id, but SOQL no longer finds the row. Key queries by the old lookups: records.getIdsOf(Contact.AccountId).
  • Merge losers arrive here. The records that lose a merge fire the delete triggers with MasterRecordId set. Skip them with record.isNull(Contact.MasterRecordId).
  • Cascade deletes never arrive. Records that the platform deletes with their parent, such as master-detail children, fire no delete triggers. Put that logic on the parent's delete.
  • Stop deletes in BeforeDelete. getOldSObject().addError(…) here rolls the delete back, but only after earlier handlers did their work. Use a BeforeDelete.Handler.
  • One role per class. A class that implements both roles runs only as a Writer.