12.2 Implementing Flow Control with Conditions and Loops
Key Takeaways
- A Switch compares one value against up to 25 discrete cases plus a Default branch; Conditions handle ranges and complex multi-field logic.
- Apply to each runs up to 20 iterations in parallel by default; Concurrency Control ranges from 1 to 50, and 1 forces sequential execution.
- Do until exits when its condition is true or a limit is hit — defaults are 60 iterations or a PT1H (one-hour) timeout, with maximums of 5,000 iterations and 30 days.
- The try-catch-finally pattern uses three Scopes plus Configure run after: the Catch scope runs only when the Try scope has failed, has timed out, or is skipped.
- Terminate immediately ends the entire run with status Succeeded, Failed, or Cancelled — nothing after it executes.
Branching and looping decide how a flow reacts to data. AB-410 tests the mechanics precisely: which control to choose for a given scenario, what the numeric limits are, and how to build a proper error-handling pattern with scopes.
Condition vs Switch
A Condition evaluates one boolean expression — is greater than, is equal to, contains, starts with — and splits the flow into If yes and If no branches. Conditions can be nested, but more than two or three levels deep becomes unreadable and the designer caps action nesting depth.
A Switch checks one value against a list of discrete cases (equals comparisons only) and includes a Default branch that runs when no case matches. Reach for a Switch when you would otherwise chain three or more conditions on the same field — for example, routing an approval by department equals Sales, Marketing, Finance, or HR. The documented limit is 25 cases per switch, plus the Default branch.
Exam rule of thumb: range checks or complex multi-field logic → Condition; one field matched against a fixed list of values → Switch.
Apply to each and concurrency control
Apply to each iterates over every item in an array — typically the value output of List rows or a SharePoint Get items call. By default the loop runs up to 20 iterations in parallel. Open the loop's Settings and enable Concurrency Control to change that; the slider ranges from 1 to 50.
Setting the degree to 1 forces sequential execution, one iteration at a time. This matters in Dataverse write scenarios: dozens of parallel branches all calling Update a row can trigger Dataverse service protection throttling (HTTP 429), hit record-lock contention, and create race conditions when later iterations depend on earlier writes. Sequential loops are slower, but they are predictable and throttle-safe — the standard exam answer for 'updates intermittently fail inside a loop.'
Do until
Do until repeats its inner actions until a condition becomes true or a limit is reached. The defaults are documented numbers worth memorizing:
| Setting | Default | Maximum |
|---|---|---|
| Count (iterations) | 60 | 5,000 |
| Timeout | PT1H (1 hour) | 30 days |
Timeout uses ISO 8601 duration format — PT1H is one hour, PT10M is ten minutes. The loop always executes at least once because the exit condition is evaluated after each iteration. A typical use is polling a status column every 30 seconds until an approval completes, giving up gracefully at the timeout.
Exam trap: If the condition is already true before the first pass, Do until still runs its body once. And hitting the Count or Timeout limit ends the loop without raising an error — the flow simply continues to the next action.
Scope and the try-catch-finally pattern
A Scope is a collapsible container that groups actions; it runs its contents in order and reports a single aggregate outcome. On its own a Scope just tidies long flows. Its real power is error handling. The standard try-catch-finally pattern:
- Try — a Scope containing the actions that might fail, such as calling an external API or adding a Dataverse row.
- Catch — a second Scope whose Configure run after on the Try scope is set to has failed, has timed out, and is skipped (everything except is successful). Inside, log the failure or post a Teams or email alert. You can read the Try scope's error detail with the
result()expression:result('Try')returns the status and error message of each action inside it. - Finally — a third Scope configured to run after all four outcomes of the Catch scope, holding cleanup logic that must always execute.
After a Try scope fails, downstream actions that expect success are marked Skipped — which is exactly why the Catch scope needs its run-after settings changed before it will execute.
Terminate
The Terminate action immediately stops the entire flow run with a status of Succeeded, Failed, or Cancelled, plus an optional message. Nothing after it executes. Use Failed when a business rule is violated so the run surfaces in failure reports and resubmit workflows make sense; use Cancelled for a deliberate early exit that is not an error, such as discovering there is no work to do.
Empty arrays and nested loops
If List rows finds nothing, its value output is an empty array. An Apply to each over an empty array performs zero iterations and succeeds — but referencing an output that is null (wrong step, or a failed upstream action) makes the loop fail outright. The defensive pattern is to wrap the loop in a Condition that checks length() or empty() first, or to feed the loop coalesce(..., json('[]')).
Nested loops multiply iteration counts: an outer loop of 200 rows with an inner loop of 50 rows produces 10,000 inner action executions, which burns through daily Power Platform request limits quickly and slows runs to a crawl. Where possible, replace the inner loop with a single Filter array action, or restructure so one List rows call with a well-built OData filter does the matching server-side.
You wrapped your Dataverse create logic in a Scope named Try. What is the correct configuration for a Catch scope that should execute only when the Try scope fails?
A flow loops over 500 Dataverse rows calling Update a row on each, and runs are intermittently failing with HTTP 429 throttling errors. What is the best first fix inside the Apply to each settings?