home Homebuild Toolsbug_report Errorsmenu_book Guideslightbulb Tips
search
info

Why this matters: When automation doesn't behave as expected — validation firing at the wrong time, triggers seeing stale data, workflows not updating related records — the answer is almost always in the order of execution.

The Full Order of Execution

When a record save is initiated (insert, update, upsert, delete, undelete), Salesforce processes the following steps in order:

Order
 1.  Load the original record from the database (or initialize for new inserts)
 2.  Apply new field values from the request
 3.  Execute system validation (required fields, field formats, max lengths)
 4.  Run before-save Record-Triggered Flows
 5.  Run before Apex triggers
 6.  Run custom validation rules
 7.  Run duplicate rules
 8.  Save the record to the database — NOT yet committed
 9.  Run after Apex triggers
10.  Run assignment rules (Leads, Cases)
11.  Run auto-response rules (Cases, Leads)
12.  Run workflow rules (deprecated — prefer Flow)
13.  Run processes (Process Builder — deprecated — prefer Flow)
14.  Run escalation rules
15.  Run after-save Record-Triggered Flows
16.  Run entitlement rules
17.  Roll up summary fields to parent records
18.  Run criteria-based sharing rules
19.  Commit all changes to the database
20.  Run post-commit logic (emails, async Apex, platform events)

Before-Save vs After-Save

This distinction is critical for both triggers and Record-Triggered Flows.

Before-save

Runs before the record is written to the database. You can modify field values directly on the record in context without an additional DML call. This is more efficient and is the preferred approach for field updates on the triggering record.

Apex
// Before trigger — no DML needed to update the triggering record
trigger AccountTrigger on Account (before insert, before update) {
    for (Account acc : Trigger.new) {
        // Direct field assignment — efficient, no extra DML
        acc.Description = 'Updated by trigger';
    }
}

After-save

Runs after the record is saved to the database but before the transaction is committed. The record now has its Id (for inserts). Use this when you need to query the saved record or perform DML on related records.

lightbulb

Rule of thumb: Update the triggering record in a before trigger or before-save Flow. Touch related records or run queries on the saved record in an after trigger or after-save Flow.

Where Triggers Fit vs Flows

Before-save Record-Triggered Flows run before before-triggers. This means if both exist on the same object, the Flow fires first. Salesforce's recommendation is to keep automation consolidated — one tool per object where possible.

Execution Snapshot
Record save initiated
  └─ [Step 4]  Before-save Record-Triggered Flow ← runs first
  └─ [Step 5]  Before Apex Trigger              ← runs second
  └─ [Step 6]  Custom Validation Rules
  └─ [Step 8]  Record saved to DB (uncommitted)
  └─ [Step 9]  After Apex Trigger
  └─ [Step 15] After-save Record-Triggered Flow
  └─ [Step 19] COMMIT

Validation Rule Timing

Validation rules run at step 6 — after before-save Flows and before-triggers. This is why a before-trigger can set a field value that a validation rule then evaluates. If a validation rule fails, the entire transaction rolls back and no further steps execute.

What Triggers a Rollback

Any unhandled exception or validation failure at any step rolls back the entire transaction to its last savepoint. This includes:

  • Validation rule failures
  • Unhandled Apex exceptions in triggers
  • Flow faults without a fault path configured
  • DML errors (e.g., duplicate key, required field missing)

Key Developer Tips

lightbulb

Debugging order of execution issues: Enable debug logs with APEX_CODE FINEST and WORKFLOW FINER. The log will show each step firing and the order in real time.

Common gotchas to watch for:

  • Querying Trigger.new records in an after-trigger returns the saved values including the auto-assigned Id.
  • Roll-up summary field recalculation (step 17) can fire its own triggers on the parent — watch for unintended recursion.
  • Post-commit email sends (step 20) will still complete even if subsequent code throws — emails can't be recalled once committed.
  • Platform events published in a trigger are delivered post-commit. They cannot be rolled back.