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.

Briefly: a Loop is only justified when you need to do something different to each record individually. If you are filtering a collection, sorting it, taking the top few, or finding one record, a Collection Filter, a Collection Sort, or a properly filtered Get Records does the same job in one element and no iterations.

Most loops I find in flow reviews are doing one of those four things. They work, they pass testing on three records, and they are the reason the flow dies at volume.

What to use instead, by what you are trying to do

Goal Loop version Element that replaces it
Keep only records matching a condition Loop + Decision + Assignment to a second collection Collection Filter — one element, conditions set on the collection
Order records, or take the top N Loop with comparison variables Collection Sort, with Set the maximum number of items
Find one specific record Loop + Decision + exit assignment Get Records with filters, a sort order, and Only the first record
Count records Loop + counter variable A formula using COUNT() on the collection
Check whether the collection is empty Loop with a “found” boolean Decision on the collection with the Is Null or Is Empty operator
Update the same fields on every record Loop + Update Records inside it Loop to build a collection, one Update Records after the loop

Collection Filter and Collection Sort both operate on a collection you already have in memory. No query, no DML, and the work happens in one element rather than one element per record. Collection Sort modifies the collection variable in place, which trips people up — if you need the original order later, copy the collection first.

When a loop is genuinely the right answer

Three cases, and they are legitimate:

  1. Per-record field values. Each record needs a different value written — a sequence number, a value derived from its own fields, a running total. There is no element that does this.
  2. Per-record branching. Records need to end up in different collections for different treatment, and the split is not expressible as a single Collection Filter condition.
  3. Building something aggregated. Summing currency amounts, concatenating a text summary, finding the maximum of a field that Get Records cannot sort on.

In all three, the loop contains only Assignment and Decision elements. The moment a Get Records, Create Records, Update Records, Delete Records, or an Apex action appears inside a loop, you have a limit problem waiting for a big enough batch.

Nested loops are almost always wrong

The cost of a nested loop is the product of the two collections, not the sum. Two hundred Accounts against two hundred Contacts is 40,000 iterations, and every iteration executes the elements inside. There is no version of this that is fast.

The reason people write them is a genuine gap: Flow has no map or dictionary data type, so there is no way to build a keyed lookup from parent ID to child record. The nested loop is a linear scan standing in for a hash lookup. That is what makes it quadratic.

What to do instead, in order of preference:

  1. Query the relationship instead of matching in memory. One Get Records on the child object filtered by AccountId In your collection of parent IDs gives you exactly the children you need, and the database does the matching on an indexed foreign key. This removes the outer-inner match entirely in a surprising number of cases.
  2. Single loop plus Collection Filter. Loop over the parents, and inside the loop use a Collection Filter on the pre-fetched child collection to select the children of the current parent. Still linear scans, but one element instead of a nested loop’s worth of elements, and no query inside the loop.
  3. Invocable Apex. Twenty lines with a Map<Id, List<Contact>> does the join once and is done. If your collections are in the hundreds and the matching is genuinely keyed, this is the correct answer, and refusing to write it because the project is “clicks not code” is a decision to ship something slow.

I will state the opinion plainly: a nested loop over two record collections in a record-triggered flow is a defect, not a style choice. It will pass UAT and fail the first real data load.

What loops cost you in CPU time

The per-transaction CPU limit is 10,000 ms synchronous, 60,000 ms asynchronous. CPU time counts application-server compute — flow element execution, Apex, validation rules, managed package code. It explicitly excludes the database time spent executing your SOQL and DML, and time spent waiting on a callout.

That exclusion is why loops are the main CPU risk in Flow. A flow that spends four seconds on a badly filtered query barely moves the CPU counter. A flow that runs 40,000 iterations of three elements each is doing 120,000 units of pure application-server work, and that is precisely what the limit measures. When you see a CPU timeout in a flow, look for iteration counts before you look at queries.

There is also a distinct failure mode: the Number of Iterations Exceeded error, which the platform raises when a flow loops far more times than intended. In practice it means either an unbounded collection or a loop whose exit condition never fires, and it is a design bug rather than a tuning problem.

Capping the collection before the loop

If a loop must process a collection whose size you do not control, bound it deliberately rather than hoping. Collection Sort has a Set the maximum number of items option — sort by whatever makes the retained records the important ones, cap at 100 or 200, and loop over that. You have swapped an unpredictable failure for a documented, deliberate limitation, which is the better of the two.

The tradeoff is real and you must handle it: records beyond the cap are silently dropped. If those records need processing, capping the collection is not a fix, it is a bug with a nicer failure mode. Move the work to a scheduled path or a schedule-triggered flow that processes the remainder, and accept that the results are no longer immediate.

Frequently asked

Can I break out of a Flow loop early?

Not with a dedicated element. Route the For Each path to whatever comes after the loop when your condition is met, using a Decision. The loop stops iterating because control has left it. If you find yourself doing this to find a single record, use Get Records with Only the first record instead.

Is Collection Filter faster than a loop with a Decision?

Yes, and the gap grows with the collection. One element evaluating conditions across the collection replaces two or three elements executed per record. For a 500-record collection that is a difference of well over a thousand element executions.

How many iterations is too many?

There is no published threshold, because the cost depends on what is inside the loop. As a working rule, a few hundred iterations of two or three in-memory elements is unremarkable. Tens of thousands of iterations of anything will show up in CPU time. Measure it: run the batch with a debug log and read LIMIT_USAGE_FOR_NS at the end of the log for actual CPU consumption.

Does the Loop element itself consume a query or DML?

No. A Loop iterates over a collection already in memory. What costs you is what you put inside it.

Should I loop over $Record in a record-triggered flow?

$Record is one record, not a collection, so there is nothing to loop over. When 200 records are saved together, the platform runs 200 separate interviews and bulkifies the elements across them. Trying to loop over the batch is a mental model imported from Apex triggers, and it does not apply here.

Is a subflow inside a loop a good way to organise this?

It organises the canvas and changes nothing else. The subflow runs in the same transaction, executes the same elements, and spends the same limits. Once per iteration.


Reference: “Collection Filter Element”, “Collection Sort Element”, “Get Records Element”, and “General Flow Limits”, Salesforce Help; Apex Developer Guide, Execution Governors and Limits.