The Salesforce Apex Order of Execution

Salesforce Apex Order of Execution — The Complete Guide | CertifySF

The Salesforce Apex Order of Execution

Every save in Salesforce travels a deterministic path — from JavaScript validation in the browser to post-commit asynchronous Apex. Here is the complete sequence, the traps that catch admins and developers, and the modern positions of flows after the Workflow Rules retirement.

Apex & Automation Verified: Spring ’26 ~16 min read

Why the order of execution matters

When a record is saved with an insert, update, or upsert statement, Salesforce performs a fixed sequence of events. The sequence is the same whether the save originates from the UI, the REST API, an Apex DML statement, or a flow. That determinism is the contract: if you understand where each tool runs, you can predict — and debug — any save.

The order of execution sits underneath every customization decision. A validation rule that fires before a trigger has a chance to fix the data. A workflow field update that re-fires triggers but skips custom validation. A roll-up summary that updates a parent record, which then runs its own triggers and flows. None of this is documented inside the rule, trigger, or flow itself — the behavior is dictated by the position the tool occupies in the save sequence.

Key concept

The order of execution is not a guideline. It is a deterministic contract. Every save runs the same steps, in the same order, every time — whether triggered by a click, an integration, a flow, or another trigger.

The browser phase: JavaScript validation

Before anything reaches Salesforce servers, the browser runs JavaScript validation on dependent picklist fields. This is the only client-side validation the platform performs, and it limits each dependent picklist to the values controlled by its parent. No other validation — no required-field check, no formula, no validation rule — runs in the browser.

This step never appears for API-initiated saves, Apex DML, or flow DML. It exists exclusively for users editing records in the standard UI.

The complete server-side sequence

Once the request reaches the server, Salesforce executes the following events in order. The list reflects the current Spring ’26 documented behavior.

  1. Load the original record from the database, or initialize a new record for an upsert/insert.
  2. Overwrite old field values with new values from the request.
  3. System validation — for UI saves: page-layout-specific rules, required fields at layout level, field formats, and maximum field length. For API, SOAP, and Apex saves: foreign keys, field formats, maximum field lengths, and restricted picklists; before executing a trigger, Salesforce verifies that any custom foreign keys do not refer to the object itself. Custom validation rules also run here for multiline items such as quote line items and opportunity line items, and for User object saves from a standard UI edit page.
  4. Execute before-save record-triggered flows.
  5. Execute all before triggers.
  6. Run most system validation again (required fields, formats) plus custom validation rules. Layout-specific rules from step 3 are not re-run.
  7. Execute duplicate rules. If a rule with the block action identifies the record as a duplicate, the save halts here — no after triggers, no workflow rules, nothing further runs.
  8. Save the record to the database — but do not commit yet.
  9. Execute all after triggers.
  10. Execute assignment rules.
  11. Execute auto-response rules.
  12. Execute workflow rules.
  13. Apply workflow field updates — if any exist, the record is updated again.
  14. Re-fire before update and after update triggers exactly one more time, plus standard validations. Custom validation rules, duplicate rules, and escalation rules are not re-run.
  15. Execute escalation rules.
  16. Execute Salesforce Flow automations — processes built with Process Builder and flows launched by workflow rules (flow trigger workflow actions pilot). These run in no guaranteed order. To control ordering, use record-triggered flows.
  17. Execute after-save record-triggered flows.
  18. Execute entitlement rules.
  19. Recalculate roll-up summaries on the parent if the record is part of a master-detail or cross-object workflow. The parent record then enters its own save procedure.
  20. Recalculate roll-up summaries on the grandparent if applicable. The grandparent then enters its own save procedure.
  21. Evaluate criteria-based sharing rules.
  22. Commit all DML operations to the database.
  23. Execute post-commit logic — outbound emails, asynchronous Apex (queueable jobs and future methods), asynchronous paths in record-triggered flows, and “publish after commit” platform events.

The sequence above can be grouped into four phases that map cleanly to how the platform actually behaves:

PHASE 1 Pre-save validation. Steps 1–7. The record exists only in memory. Failures roll back instantly.
PHASE 2 Save (uncommitted). Step 8. Record has an Id but is not yet permanent.
PHASE 3 Post-save automation. Steps 9–20. Triggers, workflows, flows, rollups, sharing — all running on the saved-but-uncommitted record.
PHASE 4 Commit and post-commit. Steps 21–22. Data is permanent. Async work begins.
Exam alert

The distinction between save (step 8) and commit (step 22) is the single most tested concept in this topic. A record can have an Id, exist in the database, and still be rolled back if anything later in the sequence fails.

Before triggers vs. after triggers

The two trigger contexts are not interchangeable. Each one runs at a specific point in the save sequence, has access to different fields, and supports different operations.

Before triggers

  • Run at step 5, before the record is saved to the database
  • Modify field values directly on Trigger.new — no DML required
  • Record does not yet have an Id on insert
  • Cannot reference related records that depend on the new record’s Id
  • Use for: data cleanup, defaulting fields, cross-field validation

After triggers

  • Run at step 9, after the record is saved (but before commit)
  • Cannot modify Trigger.new directly — fields are read-only
  • Record has an Id on insert
  • Can create, update, or delete related records via DML
  • Use for: cross-object updates, roll-up logic, integrations
Best practice

Use before triggers for changes to the same record. Use after triggers for changes to related records. Mixing the two contexts in a single trigger framework is fine — the framework dispatches to handler methods that match each context’s capabilities.

Multiple triggers on the same object

When two or more triggers exist for the same object and event, Salesforce does not guarantee the order in which they fire. This is a fundamental property of the platform and is unchanged across all releases. The accepted solution is the one-trigger-per-object pattern: a single trigger that delegates to a handler class, with the handler class controlling explicit sub-method ordering.

Where flows fit (before-save vs. after-save)

Record-triggered flows occupy two distinct positions in the save sequence depending on how they are configured.

Flow typeStepBest for
Before-save record-triggered flow Step 4 — runs before all before triggers Same-record field updates with no DML cost
After-save record-triggered flow Step 17 — runs after escalation rules and Salesforce Flow automations Cross-object updates, calling subflows, async paths
Schedule-triggered flow Outside the save sequence — runs on a cron schedule Batch operations against records meeting criteria
Platform-event-triggered flow Runs in a separate transaction triggered by event delivery Reacting to events from other transactions or external systems

Before-save flows are the most efficient declarative option for same-record updates because they avoid the extra DML that an after-save flow or workflow field update would require. They run before before-triggers, which means a before-save flow can set a field that a before trigger then reads.

Order matters

A before-save flow runs before any before trigger. If your trigger logic depends on a field set by a flow, this ordering works in your favor. If your flow logic depends on a value set by a before trigger, the flow will see the original value, not the trigger’s modification.

The workflow field-update re-fire trap

Workflow field updates introduce one of the most subtle behaviors in the entire save sequence. When a workflow field update modifies a record, before update and after update triggers fire one more time — and only one more time, regardless of how many field updates ran. Several things do not re-run during this second pass:

  • Custom validation rules
  • Flows (record-triggered flows of any kind)
  • Duplicate rules
  • Processes built with Process Builder
  • Escalation rules

Standard system validations do re-run during this pass, but custom validation does not — so a custom validation rule cannot block a workflow-driven update.

This selective re-fire creates a category of bugs that look impossible. A field set by a workflow update will appear in the second trigger pass, but Trigger.old still reflects the value before the user’s edit, not the value before the workflow update. A trigger that compares Trigger.new to Trigger.old will see a “change” that happened during the workflow phase, not the user’s original change.

Subtle behavior

If you have an after update trigger that fires on a field, and a workflow field update changes that field, the trigger fires twice for a single user save. Idempotent trigger logic is not optional in this context — it is required.

Recursive saves and what gets skipped

A recursive save happens when a save triggers another save on the same record — most often through a trigger or flow that performs a DML update on the record being saved. To prevent runaway loops, Salesforce skips a large block of steps during a recursive save: assignment rules, auto-response rules, workflow rules, escalation rules, after-save flows, entitlement rules, and parent and grandparent roll-up summary recalculation.

What still runs in a recursive save: before-save flows, before triggers, validation, the save itself, and after triggers. The recursive save is a real save with full validation — it is the post-save automation block that gets bypassed.

Step in recursive saveRuns?
Before-save flows, before triggers, validation, duplicate rulesYes
Save to databaseYes
After triggersYes
Assignment, auto-response, workflow, escalation rulesSkipped
After-save flows, entitlement rulesSkipped
Roll-up summaries (parent and grandparent)Skipped
Criteria-based sharing, commit, post-commitYes

Post-commit: emails, async Apex, platform events

Step 23 is where work that does not affect the current transaction gets to run. By the time post-commit logic begins, the database is permanent and no further changes can roll back.

Outbound emails

Email alerts queued by workflow rules, processes, flows, approval processes, and the Messaging.sendEmail() method are sent here. If the transaction had failed before commit, none of these emails would have been sent.

Asynchronous Apex

Queueable jobs enqueued via System.enqueueJob(), future methods called via @future, and batch jobs started via Database.executeBatch() all begin in the post-commit phase. Each runs in its own transaction with its own governor limits — and its own pass through the order of execution for any DML it performs.

Asynchronous paths in record-triggered flows

After-save record-triggered flows can include asynchronous paths that run in a separate transaction after the originating save commits. These behave like queueable Apex from a transactional standpoint: the parent save is already permanent, and any DML in the async path triggers its own full pass through the order of execution.

Platform events

Platform events have two publish behaviors that determine where in the save sequence they fire. The Salesforce Architects guide describes them clearly: Publish Immediately publishes during the transaction before commit, with no order guarantee. Publish After Commit publishes only after a successful commit, with strict ordering preserved. Choose Publish After Commit when subscribers depend on data committed by the publisher; choose Publish Immediately for use cases like logging, where the event should fire even if the transaction rolls back.

Architecture pattern

If a piece of work cannot affect the current save and cannot block the user, move it to post-commit. Async Apex and platform events isolate slow or risky logic — callouts, complex calculations, third-party integrations — from the synchronous save. A faster, more reliable user experience is the result.

Workflow Rules and Process Builder after end of support

Salesforce ended support for Workflow Rules and Process Builder on December 31, 2025. New Workflow Rules and Process Builders cannot be created as of the Spring ’25 release. Existing automation continues to run — including the workflow field-update re-fire behavior at step 14 — but Salesforce no longer provides bug fixes or enhancements for these tools.

The order of execution diagram has not changed. Workflow rules still occupy step 12, workflow field updates still trigger the one-time re-fire at step 14, and processes still run alongside other after-save automation. The change is operational: legacy automation runs on borrowed time.

Legacy

Workflow Rules & Process Builder

  • End of support: December 31, 2025
  • No new rules creatable since Spring ’25
  • Existing rules continue to run
  • No bug fixes or enhancements
  • Migrate via the Migrate to Flow tool or rebuild in Flow

Common pitfalls and best practices

Bulkify everything

The order of execution applies to whatever batch size invoked the save. Triggers fire once for the batch, not once per record. SOQL queries inside loops will exceed governor limits in production volumes regardless of how the save was initiated.

Validate after fixing, not before

Custom validation rules run at step 6 — after before triggers and after before-save flows. A trigger or flow that cleans up data does so before the validation runs against it. Validation rules should focus on business rules the user must satisfy, not on data hygiene that automation can handle.

Use one trigger per object

Multiple triggers on the same object have no guaranteed firing order. The one-trigger-per-object pattern, with a handler class that explicitly orders sub-methods, is the only way to control execution order across an organization.

Move slow work to async

Callouts, large data processing, and integrations belong in queueable, future, or batch Apex. They run after commit, do not block the save, and isolate failures from the user-facing transaction.

Track recursion explicitly

Static class variables are the standard pattern for preventing trigger recursion. The platform does not provide built-in recursion protection — every trigger framework needs its own guard.

Migration note

If you are converting Workflow Rules to Flows, prefer before-save flows for same-record updates. They run earlier in the sequence than the original Workflow position and avoid the re-fire of triggers that workflow field updates cause. The converted automation will often perform better than the original.

High-yield exam tips

  1. Before-save flows run first. They execute at step 4, before any before trigger. This is the most efficient declarative path for same-record updates and a frequent multiple-choice distractor.
  2. System validation runs twice in UI saves. Once at step 3 (including layout-specific rules) and again at step 6 (most checks, but layout rules do not re-run).
  3. Custom validation runs after before-triggers. Triggers that clean up data succeed; triggers that try to bypass validation fail. Validation cannot be skipped from Apex except by re-writing the rule itself.
  4. Duplicate rules can halt the save. A duplicate rule with the block action at step 7 prevents all later steps — no after triggers, no workflow rules, no flows.
  5. Save is not commit. Step 8 saves; step 22 commits. Any failure between the two rolls back the entire transaction, including changes from after triggers and flows.
  6. Workflow field updates re-fire triggers exactly once. Before update and after update triggers fire one more time at step 14, plus standard validations. Custom validation, flows, duplicate rules, processes, and escalation rules do not re-run.
  7. Trigger.old does not see workflow updates. In the workflow re-fire pass, Trigger.old still holds the value before the user’s edit, not the value before the workflow field update.
  8. Multiple triggers, no guaranteed order. Two triggers on the same object and event fire in undefined order. The one-trigger-per-object pattern is the canonical fix.
  9. Recursive saves skip the post-save block. Assignment, auto-response, workflow, escalation, after-save flows, entitlements, and rollups are skipped. Validation and triggers still run.
  10. Post-commit fires async Apex. Queueable, future, batch, outbound emails, async paths in record-triggered flows, and platform events with Publish After Commit behavior all run at step 23 — after the database is permanent.
  11. Workflow Rules ended support December 31, 2025. Existing rules still run, but no new rules can be created and no fixes will be issued. Position in the save sequence is unchanged.

Test your knowledge of the order of execution

This topic appears across Platform Developer I, Platform Developer II, Platform App Builder, Administrator, and Application Architect exams. Practice the scenario questions that span all five.

Browse practice exams →

Frequently asked questions

Where do record-triggered flows fit in the order of execution?

Before-save record-triggered flows run before before-triggers, very early in the save process. After-save record-triggered flows run after workflow field updates and after escalation rules but before rollup summary recalculation. The split makes before-save flows the most efficient declarative option for same-record updates because they avoid an extra DML.

Do workflow field updates re-fire triggers?

Yes. If a workflow field update modifies the record, before update and after update triggers fire one more time — and only one more time, regardless of how many field updates occurred. Custom validation rules, flows, duplicate rules, processes built with Process Builder, and escalation rules are not re-evaluated, but standard system validations are.

What is the difference between save and commit?

After the save step, the record is written to the database in a transient state. After all automation completes, DML operations are committed. Any failure between save and commit rolls back the entire transaction, including changes made by after triggers, workflows, and flows.

What runs in the post-commit phase?

Outbound emails, asynchronous Apex jobs such as queueable, future, and batch, and platform events configured with Publish After Commit behavior. None of this logic can affect the data already committed in the current transaction.

Does the order of execution guarantee trigger order when multiple triggers exist for the same object?

No. When two or more triggers exist for the same object and event, Salesforce does not guarantee the firing order. Use a trigger framework or one-trigger-per-object pattern to make execution order explicit and controllable.

Are Workflow Rules and Process Builder still part of the order of execution?

Existing Workflow Rules and Process Builders continue to run, but Salesforce ended support on December 31, 2025 and stopped allowing creation of new ones in Spring ’25. They still occupy their original positions in the save sequence, but new automation should be built in Flow Builder.

What gets skipped during a recursive save?

When a save triggers another save on the same record (a recursive save), Salesforce skips the steps from assignment rules through grandparent rollup summary recalculation. This prevents runaway loops while still honoring before-triggers, validation, after-triggers, and the eventual commit.

All information verified against the Salesforce Apex Developer Guide, Salesforce Architects decision guides, and Spring ’26 release documentation. Study smarter at CertifySF.com.

Shopping Cart