Not verified hands-on. This article was written from primary documentation rather than reproduced in an org, so it carries no tested-release badge. If you run it and something differs, say so in the comments and it gets tested and corrected.

The two facts people get wrong: before-save record-triggered flows run before your before triggers, and after-save record-triggered flows run after workflow rules, not next to your after triggers. Everything else in the save order follows from those two positions.

What follows is the documented sequence from “Triggers and Order of Execution” in the Apex Developer Guide, with the flow steps in place. The numbering is the documentation’s own, because one of the important notes refers to steps by number.

The sequence, in order

# What runs Notes
1 Loads the original record from the database, or initialises it for an upsert This is what becomes Trigger.old.
2 Loads new field values from the request and overwrites the old ones System validation here depends on the source. From a standard UI edit page: layout rules, required fields, field formats, maximum length. From the API or Apex: foreign keys, field formats, maximum field lengths, and restricted picklists.
3 Before-save record-triggered flows First automation of any kind to see the record. Edits $Record in memory; no DML.
4 All before triggers Trigger.new already contains whatever the before-save flow set.
5 Most system validation again, plus custom validation rules Layout-specific rules are the one thing not re-checked for UI requests.
6 Duplicate rules A duplicate rule with the block action stops the save here. No after triggers, no workflow rules, nothing downstream.
7 Saves the record to the database, not committed The record now has an ID and is queryable inside the transaction.
8 All after triggers Trigger.new is read-only. Changing the same record means issuing DML, which starts a nested save.
9 Assignment rules Leads and Cases.
10 Auto-response rules
11 Workflow rules If there are workflow field updates, the record is updated again, system validations run again, and before update and after update triggers execute one more time, and only one more time. Custom validation rules, flows, duplicate rules, processes, and escalation rules do not run again on that pass.
12 Escalation rules
13 Processes built with Process Builder, and flows launched by workflow rules Documented as running in no guaranteed order among themselves.
14 After-save record-triggered flows Runs after everything above. In API version 53.0 and earlier these ran after entitlement rules instead.
15 Entitlement rules
16 Roll-up summary fields on the parent record The parent then goes through this whole save procedure itself.
17 Roll-up summary fields on the grandparent record Same again, one level up.
18 Criteria-based sharing evaluation
19 Commits all DML to the database Locks release here.
20 Post-commit logic Email sends, enqueued asynchronous Apex including Queueable and future methods, and asynchronous paths from record-triggered flows.

What re-runs, and how many times

Three different things get called “it ran twice,” and they are not the same event.

The workflow field update pass

A workflow rule with a field update writes to the record after it was already saved at step 7. That produces one more pass through the update triggers — before update and after update, once more and only once more, regardless of whether the original operation was an insert or an update. Validation rules, flows, duplicate rules, and escalation rules are deliberately excluded from that pass. This is the narrowest of the three cases and the only one with a hard cap built into it.

The recursive save

When something inside the save order writes to a record and that write causes the save order to run again, the documentation calls it a recursive save, and it does not run the full twenty steps. Salesforce skips steps 9 through 17 — assignment rules, auto-response rules, workflow rules, escalation rules, processes, after-save flows, entitlement rules, and both levels of roll-up summary recalculation.

That is worth reading twice, because it is the reason a roll-up or an assignment rule sometimes appears not to fire on nested updates. It is not broken. It is skipped by design.

The same-record update from an after-save flow

This is the common one. An after-save flow uses an Update Records element on $Record. That is a DML statement, so the record starts a new save: steps 1 through 8 again, including your before-save flows and both sets of triggers, with steps 9 to 17 skipped as a recursive save. Flow’s own recursion control stops the flow re-firing itself, but it does nothing about the second save it caused, so the Apex trigger on that object runs again.

The fix is not a guard variable. It is to move the field assignment into a before-save flow, where it happens at step 3 with no additional DML.

What this means in practice

Validation rules cannot see what an after-save flow does. Validation is step 5. After-save flows are step 14. If you need a save blocked based on derived values, derive them in a before-save flow at step 3, or block the save with a Custom Error element in the flow itself.

An after trigger cannot hand a value to an after-save flow in memory. After triggers get a read-only Trigger.new. To change the record they must issue DML, and that nested save completes synchronously inside the trigger — before step 14 ever happens. The after-save flow’s $Record was populated for the original save, so a decision in that flow can be made on values the database no longer holds. If you have flow and Apex on the same object, capture a debug log and confirm which values each one actually sees rather than assuming.

Parent roll-ups are full saves. Step 16 puts the parent record through the entire sequence, triggers and flows included. A master-detail insert of 200 children can therefore run the Account automation 200 times’ worth of work in one transaction, sharing the same 10,000 ms of synchronous CPU, 100 SOQL queries, and 150 DML statements.

Nothing before step 19 is durable. If anything after your trigger throws, your writes disappear with the rest. Related: a callout after DML in the same transaction throws “You have uncommitted work pending”. The platform will not let you hold a transaction open across a callout.

Multiple Apex triggers on one object have no guaranteed order. Same for the processes and workflow-launched flows at step 13. If two things must happen in a known order, they belong in the same piece of code.

Frequently asked

Do before-save flows run before validation rules?

Yes. Step 3 versus step 5. A value your before-save flow sets is what validation rules evaluate, which is exactly why before-save flows are a good place to derive fields that validation depends on.

Where do roll-up summary fields recalculate?

Steps 16 and 17, after all synchronous automation on the child and before commit. The parent’s own save order then runs in full, which is why a roll-up on a heavily automated parent object is expensive.

Can I control the order of two after-save flows?

Only against each other, using the flow trigger order value, and only for flows on the same object with the same timing. You cannot order a flow against an Apex trigger, or against a flow on a different object.

Does the save order apply to updates from Apex and the API?

Yes, the same sequence. What differs is step 2: a UI edit page checks layout rules, required fields, formats and lengths, while an API or Apex request validates foreign keys, field formats, maximum field lengths, and restricted picklists.

When exactly does an asynchronous flow path run?

At step 20, after commit, in its own transaction with a fresh set of limits. That is the point of it, and the tradeoff is that the user’s screen refreshes before the work has happened.

Do platform events published from a flow follow this order?

Events published with the publish-after-commit behaviour fire at step 20 with post-commit logic, so their subscribers see committed data. Events published immediately do not wait for the commit, which means a subscriber can act on a record change that is later rolled back.


Reference: Triggers and Order of Execution, Apex Developer Guide, Salesforce.