I don’t buy “Flow is slow” as a blanket statement. Most of the time it’s our flow design that’s slow.
The good news: the fixes are usually boring—entry criteria, fewer updates, fewer queries, and not doing batch work in a record-triggered flow.
Here’s how I diagnose it and what I change first.
The biggest win: entry criteria
If your flow cares about StageName, don’t run it when Description changes.
Rules:
- restrict by record type / lifecycle stage when you can
- use “is changed” checks
- avoid catch-all flows that try to handle every case
If you can’t explain when this flow runs in one sentence, tighten it.
Aim for one query, one update
Common anti-pattern:
- Update Records after every branch
Better:
- set variables and decisions
- update once, at the end
Same for queries:
- query once
- reuse the variable
Recursion: treat it as a defect
If an after-save flow updates the triggering record, assume recursion risk.
Preferred pattern:
- before-save for field updates on the record itself
- after-save for related records, notifications, integrations
If you must update the triggering record after-save:
- update only when the value truly changes
- don’t “write the same value” (yes, it happens)
If synchronous work is the problem
If you’re:
- recalculating many related records
- iterating over large child sets
- doing expensive decisions per record
Switch patterns:
- scheduled path
- async Apex (invocable designed for bulk)
- platform-event pattern (if your org uses it)
Record-triggered flows run per record. Don’t pretend they’re batch jobs.
Debugging that produces answers
- Use Flow Trigger Explorer to see what fires and in what order
- Turn on debug logs for the actual running user (integration users matter)
- Reproduce with a small batch that still hits the same logic
Look for:
- unexpected flow interviews
- repeated updates
- “Get Records” elements hit multiple times
Quick checklist
- entry criteria is tight
- before-save used for same-record field updates
- one query per object where practical
- one update per flow where practical
- recursion risk removed or guarded
- heavy work moved async/scheduled
- tested under integration user context