Briefly: five flows on one object is not five small problems, it is one ordering problem you cannot see. Consolidate them, but do it in stages — inventory, map every write, find the overlaps, build the replacement in a sandbox, then cut over by deactivating the old and activating the new in a single deployment. Keep the old versions deactivated rather than deleted, because the rollback plan is reactivating them.
Be clear-eyed: consolidation is a rewrite of working automation with no test suite to prove equivalence. Most of what follows is about making that survivable.
Why many small flows is the problem, not the solution
Splitting logic across five flows feels tidy and reads as modular. Two things go wrong, and a third question stops having an answer: what happens when I save this record.
Order becomes implicit. Flows on the same object with the same timing run by trigger order value, then by created date for the ones with no value. Most orgs set no values, which makes the execution order of your business logic a side effect of when each flow was first saved. Rebuild one in a new sandbox and its created date (and its position) changes.
They share one transaction budget. All five flows, plus every Apex trigger, validation rule and managed-package component on that save, share 10,000 ms of synchronous CPU, 100 SOQL queries, 150 DML statements, and 10,000 records processed by DML. CPU bites first: it counts application-server compute, including flow interview overhead, and excludes database time for the queries themselves. Five flows on a 200-record load is a thousand interviews, each with its own element-by-element cost.
Stage 1: inventory what is actually there
Start at Setup → Object Manager → your object → Flow Triggers, or open Flow Trigger Explorer from the Flows list. It shows record-triggered flows grouped by object and timing, in run order.
For a whole-org picture, query the flow definitions instead of clicking through every object:
sf data query --target-org myorg --query "SELECT ApiName, Label, TriggerType, TriggerOrder FROM FlowDefinitionView WHERE IsActive = true"
Adjust the field list if your API version rejects any of it, then group by object. In the same pass, list the object’s Apex triggers, active workflow rules and validation rules — old workflow rules are the most commonly forgotten participant in an object’s save behaviour.
Stage 2: map the writes, not the flows
Build a table with one row per flow: timing, entry conditions, whether it is set to run only when a record is updated to meet those conditions, every field it sets on the triggering record, every other object it creates or updates, every Get Records it performs, whether it calls Apex or a callout, and whether it has scheduled paths.
Two questions fall out of it. Which flows write the same field — that is your overlap, and probably a live bug. And which flows read a field another flow on the same object writes — that is an order dependency, and if trigger order values do not enforce it, you have found why something intermittently produces the wrong value.
Stage 3: separate genuine overlap from coincidence
Not everything should be merged. Sort each flow into one of three buckets.
Merge: same timing, same object, overlapping entry conditions or shared fields. This is the whole point of the exercise.
Move: after-save flows that only set fields on the triggering record. Those belong in the before-save flow, and moving them removes an entire additional save from every transaction. This is usually where the biggest performance win is, independent of consolidation.
Leave alone: flows with scheduled paths, flows that isolate a callout, and anything owned by a managed package. Scheduled paths do not merge cleanly. The flow’s whole execution model changes.
Stage 4: build the replacement without improving anything
Port the logic as it is, including the parts you think are wrong. Every “while I am in here” fix widens the diff between old and new behaviour, and that diff is the only thing standing between you and a silent data problem. Fix the bad logic in a separate change after cutover, when you can attribute a regression to one thing.
Structure it as one before-save flow with a Decision at the top routing to each set of assignments, and one after-save flow doing the same for the record-creating work. Set trigger order values. 10 and 20, leaving room to slot something between them later. Put the list of merged flows in the new flow’s description field. Someone will need it in a year.
Stage 5: run the comparison before you cut over
You cannot run old and new simultaneously in production: both would write, and you would get double effects. Compare in a sandbox instead, ideally a partial copy with real-shaped data.
- Assemble records that exercise every branch, including the awkward ones: nulls in the fields your conditions test, records already meeting the conditions, and a 200-record bulk load.
- With only the old flows active, run the scenarios and export the affected fields (on the object and on every object the flows write to) with Data Loader.
- Deactivate all old flows, activate the new one, reset the data, run the identical scenarios, export again.
- Diff the two exports. Every difference is either a bug in the new flow or a behaviour you decided to change. There is no third category, and “probably fine” is not an answer.
Watch limits on the bulk run. Setup → Debug Logs with Workflow at FINER, then read the cumulative limits at the end of the log. The consolidated flow should use fewer queries and less CPU than the five it replaces. If it does not, you have a Get Records inside a loop.
Stage 6: cut over as one change
Deploy the deactivation of the old flows and the activation of the new one together. Doing it by hand in production means a window where both are active, or neither is. The first double-writes, the second drops updates.
Then, in the first hours after cutover:
- Check Setup → Paused and Failed Flow Interviews. Failures cluster there before anyone reports them.
- Do not assume deactivating a flow cancels work its scheduled paths already queued. Check for pending executions before cutover, not after.
- Leave the old flow versions in place, deactivated. Reactivating them is a two-minute rollback. Rebuilding a deleted flow is not.
The tradeoff, stated plainly
People defend five flows on the grounds of isolation, and that isolation is mostly imaginary. An unhandled fault in any record-triggered flow rolls back the whole transaction, so one broken flow already breaks the save.
One real thing is lost. With five flows you can deactivate the misbehaving one in thirty seconds and leave the other four working. With one consolidated flow you edit it, save a new version and activate. Under pressure, with users waiting. The answer to that is not five flows. It is keeping the consolidated flow simple enough that its branches are obvious, and making sure more than one person knows how it is structured.
Frequently asked
How many flows should one object have?
One before-save and one after-save is the target worth defending. Add a separate flow only for something structurally different. A scheduled path, an isolated callout, not because the logic feels like a different topic.
Will consolidating actually improve performance?
Usually yes, and most of the gain comes from moving same-record field updates into a before-save flow rather than from the merge itself. Merging reduces interview overhead and duplicate Get Records. It does nothing for a query inside a loop.
Can I run the old and new flows in parallel in production?
Not for anything that writes. Both would apply their effects. Parallel comparison belongs in a sandbox, where you can run each side against the same reset data and diff the results.
Do I have to consolidate at all?
No. If the flows have distinct entry conditions, never write the same fields, and never read each other’s output, they are not causing an ordering problem and consolidation is cosmetic. The mapping exercise in stage 2 is what tells you which situation you are in. Do that part even if you stop there.
Reference: Triggers and Order of Execution, Apex Developer Guide, Salesforce; governor limits per “Execution Governors and Limits,” Apex Developer Guide; run order behaviour per “Guidelines for Defining the Run Order of Record-Triggered Flows,” Salesforce Help.