When a record is saved, Apex runs in this order:
- System validation — required fields, max length, foreign keys.
- All `before` triggers fire (one trigger per object recommended; if multiple exist, ordering is undefined).
- Custom validation rules evaluate.
- Before-save flows run (record-triggered flows configured for fast field updates).
- Database commit-1 — record is saved but not yet committed.
- All `after` triggers fire. Record's Id is now populated.
- Assignment rules (Lead/Case).
- Auto-response rules (Lead/Case).
- After-save record-triggered flows.
- Workflow rules — legacy field updates and outbound messages.
- Process Builder processes.
- If a workflow field update happened, before/after triggers and validation rules fire AGAIN on those affected fields (re-entry).
- Escalation rules (Case).
- Roll-up summary recalculation.
- Sharing rules evaluation.
- Database commit-2 — transaction is now durable.
- Async logic —
@future, queueable, batch, outbound messages, platform events that publish on commit.
Implications for trigger code:
- before triggers can mutate Trigger.new directly without DML.
- after triggers run on records that are already in the DB but pre-commit.
- Outbound messages, async Apex, and platform events fire only after commit-2 — they don't see intermediate state.
- Recursion: if your trigger fires another DML on the same object, the trigger fires again — guard with a static recursion flag.
