Salesforce Flow has gone from "the slow option" to "the default option" over the past four releases. As of Winter '23, Workflow Rules and Process Builder are deprecated for new builds. This pillar links every Flow guide on the site, organized by the questions you'll actually have.
What is Salesforce Flow?
Salesforce Flow is the platform's declarative automation tool, a visual canvas where admins build business logic without writing Apex. It runs on the same multi-tenant runtime as Apex, respects the same governor limits, and works against every Salesforce object.
Since Winter '23, Flow officially replaces Workflow Rules and Process Builder. Both jobs now go to a Record-Triggered Flow. Approval Processes can still stand on their own, but Flow is the modern alternative for new approval logic.
Lightning Web Components remain for UI and Apex remains for complex code. For most "when X happens, do Y" patterns, though, Flow is now the right answer.
The four flow types
| Type | Trigger | UI? | Common use |
|---|---|---|---|
| Screen Flow | User clicks a button or follows a guided link | Yes | Wizards, forms, guided record creation |
| Auto-Launched | Called from Apex, another flow, REST API | No | Reusable subroutines, integrations |
| Record-Triggered | A record is inserted, updated, or deleted | No | Replaces most workflow rules / process builders |
| Schedule-Triggered | A cron schedule | No | Nightly cleanup, batch updates |
Most orgs use all four eventually. Pick by who or what triggers the work.
Record-Triggered Flow: the workhorse
This type replaces what Workflow Rules and Process Builder did. There are two timing options.
Before-Save (Fast Field Update) runs before the database save. It can only modify fields on the same record being saved, and it is roughly 10x faster than after-save because there is no second save cycle. Use it for default values, normalization, and calculated fields.
After-Save runs after the database save. It can update related records, send emails, call Apex, and invoke approval processes, and the records have an Id by then, which matters on inserts. It is slower, and it is the only one of the two that can act across records.
My rule: same-record edits go before-save, everything else goes after-save.
Best practices
Bulkification, fault paths, and trigger choice decide whether your flows survive production. The full list of 12 rules: Salesforce Flow Best Practices: 12 Rules That Prevent 90% of Errors.
The non-negotiables:
- Never put a Get, Create, Update, or Delete element inside a loop. Build collections, then operate on them once.
- Always add a fault path to every DML element. Without one, failures are invisible to users.
- Pick before-save or after-save deliberately. Before for self-record edits, after for everything else.
- Test with 200 records. A flow that works for one record can crash on a Data Loader job.
The Transform element (Spring '24+)
The Transform element does collection mapping without a loop. Instead of building a new collection one iteration at a time, you describe the input to output mapping:
Input collection: List of Cases
For each Case → output a CaseResult with {
CaseId = case.Id,
Subject = case.Subject + ' [PRIORITY]',
AssignedTo = case.OwnerId
}
The runtime executes that in a single pass. You end up with fewer elements, less governor-limit exposure, and something you can still read six months later. See: Salesforce Flow Transform: Collections Without Loops.
For aggregate-style transformations (sum/count over a collection), see Salesforce Flow Transform Aggregations: Sum & Count.
Debugging flows
Three tools, in the order I reach for them:
- Flow Builder's Debug button runs the flow with test inputs and shows the value of every variable at every step. This is where I start, every time.
- Process Automation debug logs. Setup → Process Automation → Process Automation Settings → enable. Captures full state on every flow run for selected users.
- Setup → Apex Jobs. Triggered flow exceptions surface here, which catches people out. For the "the flow ran but did nothing" mysteries, this is where the answer usually hides.
For the deeper debugging playbook including silent-failure patterns, see the Flow best practices post linked above.
Order of execution
Flows sit in a specific spot in the save lifecycle:
- Before triggers
- Custom validation rules
- Record commits to buffer
- After triggers
- Assignment / auto-response rules
- Workflow field updates (legacy; can re-trigger steps 1-6 once)
- Process Builder / Flow trigger automations
- Roll-up summary recalcs
- Sharing rules
- DB commit
- Post-commit (emails, async, Platform Events)
Trigger automations run after after-triggers. That is why a flow can't easily react to a change a trigger just made: the trigger fires, then the flow runs, and the two are often going for the same fields. The full reference: Salesforce Order of Execution.
Deep-dive guides
- Salesforce Flow Best Practices: 12 Rules That Prevent 90% of Errors
- Salesforce Flow Transform: Collections Without Loops
- Salesforce Flow Transform Aggregations: Sum & Count
- Salesforce Flow Bulkification
- Apex vs Flow: When to Use Code
- Salesforce Order of Execution
- How to Trigger a Record-Triggered Flow
- Screen Flow Business Logic: Advanced Workarounds
- Salesforce Flow Bulkification
Common Flow mistakes
- DML inside a loop. Same as Apex: build collections, operate once.
- Forgetting fault paths. The failure is silent, so the user just watches nothing happen.
- One mega-flow per object. Split by intent (validation vs notification) and by trigger event (insert vs update).
- Skipping bulk testing. A flow that works for one record can crash on a 200-row import.
- Not picking before-save when it applies. That 10x difference adds up.
- Recursion via workflow re-triggers. Use the
$Flow.CurrentRecordrecursion guard or check stamp fields.
Flow is quicker to build than Apex, easier for the next admin to pick up, and fast enough now for production work that matters. Pick the right type, keep it bulk-safe, and give every DML element a fault path.
Leave a Comment