
Short answer: variables in Power Automate are scoped to the entire flow run, not to a single loop iteration. When you enable Power Automate concurrency on an Apply to each and use Set variable inside it, twenty iterations write to the same variable at the same time and stomp on each other’s values. Use Compose for per-iteration values, use Append to array variable for collecting results, and only fall back to sequential mode if you genuinely need Set variable.
That is the whole answer. If you just shipped a flow that produces the right output for item 1 and garbage for items 2 through 40, that is almost certainly what happened. The rest of this post explains why, because the failure mode is nastier than it sounds.
Why Power Automate concurrency causes this
By default, Apply to each runs sequentially. One item at a time, in order. Flip on the concurrency control in the loop settings and it runs up to 50 iterations in parallel, with a default degree of 20. Microsoft documents this in the Apply to each reference, but the docs are quieter about what happens to your variables.
Here is the problem. Set variable is a read and write against shared flow state. Iteration 3 sets the variable to its item’s value, and before it can use that value in the next action, iteration 7 has already overwritten it. Your Condition or your email body then reads whatever value happened to land last. Nothing throws an error. The flow run shows green checkmarks all the way down. You only find out when someone asks why customer A received customer B’s invoice.
I burned an afternoon in this rabbit hole once with a flow that formatted a string per item and appended it to an email digest. Sequential test run with three items: perfect. Production run with 60 items and concurrency at 20: the same three names repeated in random order. No failed actions, no signal, nothing to catch. The debugging was miserable precisely because every individual action succeeded.
The second thing concurrency takes away is ordering. Parallel iterations complete whenever they complete. If your logic assumes items are processed in the order they arrived, that assumption is gone the moment you move the slider.
How to fix it
The fix depends on what the variable was doing.
If you were using Set variable to hold a per-item value, replace it with a Compose action. Compose outputs are scoped to the iteration that produced them, so parallel iterations cannot see each other’s outputs. This covers most cases, and it is faster too because Compose does not lock flow state the way variable actions do.
If you were collecting results across iterations, use Append to array variable or Append to string variable. These operations are atomic, so they are safe under concurrency. What you give up is order: items land in the array in completion order, not source order. If order matters, append objects that carry an index and sort afterwards.
If you were transforming every item into a new shape, ask whether you need a loop at all. A Select action maps an entire array in one operation, no loop, no concurrency, no race condition. Same for Filter array when you are only keeping some items. I reach for these first now and only use Apply to each when an action genuinely has to run per item.
And if you truly cannot avoid Set variable inside the loop, set the concurrency degree back to 1. You lose the parallel speedup, but a slow correct flow beats a fast wrong one every time. That trade-off is not close.
Related gotchas
Two more things bite people once the variable problem is fixed. First, throttling. Twenty concurrent iterations means twenty simultaneous connector calls, and SharePoint and Dataverse will start returning 429s well before you expect. The built-in retry policy masks this until volume grows, which is a pattern I covered in my post on error handling patterns. If you see intermittent failures only on large runs, drop the concurrency degree before you touch anything else.
Second, parallel branches are not the same feature and have their own trap. When two branches rejoin, the joining action runs only if its run-after conditions are met, and the default is that every preceding branch succeeded. One branch fails, the join silently skips, and the flow ends looking half green. Check the run-after settings on the first action after any join.
Concurrency is genuinely useful. I have flows where it cut a 40-minute run to under 4. But the platform lets you drag and drop fast, and this is one of those places where you need to plan even faster. I have written more about these production failure modes on LinkedIn if you want the ongoing version.
Frequently Asked Questions
Why do variables break when I enable Power Automate concurrency in an Apply to each loop?
Variables in Power Automate are shared across the entire flow run, not isolated to individual loop iterations. When concurrency is enabled, multiple iterations run at the same time and overwrite the same variable, causing unpredictable values to appear in your actions. No errors are thrown, so the problem can be hard to detect.
How do I safely store per-item values inside a concurrent Apply to each loop?
Replace Set variable with a Compose action, which keeps its output scoped to the iteration that created it. This means parallel iterations cannot overwrite each other’s values, and Compose is also faster because it does not lock shared flow state.
Why does my Power Automate flow produce correct results in testing but wrong results in production?
This often happens because test runs use a small number of items that process sequentially, while production runs have enough items to trigger parallel execution. Once concurrency kicks in, shared variables get overwritten across iterations and the output becomes unreliable.
When should I turn off concurrency in Power Automate instead of refactoring my variables?
Reverting to sequential mode is a reasonable option only if your logic genuinely depends on Set variable and refactoring is not practical. However, running iterations one at a time will be slower, so it should be a fallback rather than a first choice.
Leave a Reply