Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 43

Control Flow Essentials

Recommended resources

Hello! Welcome back to our module on developing with Power Automate Cloud Flows.

In our last lesson, you mastered using expressions and built-in functions to transform data. That was a crucial step in preparing you to build dynamic, intelligent automations. Now, we'll put those skills to work.

This lesson focuses on the learning outcome: Implement control flow logic using conditions, switch cases, and apply-to-each loops. You'll learn how to direct the execution path of your flow based on the data it's processing. Your experience with control structures like if-else, switch-case, and foreach loops in C# will provide a strong foundation for understanding these concepts in Power Automate. We'll start with decision-making actions and then move to iterating over collections of data.

1. Conditional Branching: Making Decisions in Your Flow

Conditional logic allows your flow to perform different actions based on different criteria. Power Automate provides two primary actions for this: Condition and Switch.

The Condition Action (If-Then-Else)

The Condition action is your fundamental if-then-else block. It evaluates an expression that must resolve to either true or false. Based on the result, the flow proceeds down one of two branches: "If yes" or "If no". This is ideal for binary decisions.

The Switch Action (Multi-Case Logic)

The Switch action is designed for scenarios where you need to check a single value against multiple possible outcomes. This is analogous to a switch statement in C#. It evaluates an input value and executes the actions within the Case that matches the value. If no cases match, the Default case is executed. A key limitation to remember is that the Switch action only performs equality checks.

Power Automate: Condition and Switch Controls [Power Automate Basics Series - Ep. 3]

This video from Pragmatic Works provides a clear, practical demonstration of both the Condition and Switch controls. It's a great starting point for seeing how to configure these actions.

Please watch these two segments: Condition Demo (01:17 - 05:47): Focus on how dynamic content and an expression (is greater than 500) are used to create the condition and how the flow branches into 'yes' and 'no' paths. Switch Demo (08:09 - 12:09): Observe how the Switch is configured with an 'On' value (the account name) and multiple 'Case' blocks for specific names, plus a 'Default' block for all other scenarios.

Advanced Pattern: "Else If" with Arrays and Filtering

What if you need to build logic with multiple conditions that aren't simple equality checks (e.g., contains, starts with, greater than)? Chaining multiple Condition actions can become messy. The Switch action won't work because it's limited to "equals".

A more scalable and elegant solution, which will feel familiar from a programming perspective, is to use a configuration array and the Filter array action.

If, Else If, Else in Power Automate Simplified

This article from DamoBird365 presents a powerful technique for implementing complex conditional logic. It essentially creates a dynamic 'if-else if-else' structure that is much cleaner than nested conditions.

Please read the article from the beginning down to the 'Conclusion'. Pay attention to these key steps: The Problem: Note the challenges with using Switch or parallel Conditions for complex checks. The Solution: See how a JSON array is defined in a Compose action to hold the different conditions and their corresponding parameter values (like the recipient's email). The Implementation: Understand how the Filter array action is used with an expression (indexOf) to find the matching object in the array. The flow then checks if the filtered array has any items to decide which path to take.

This pattern of storing configuration logic in a JSON object within your flow is a best practice for creating maintainable and extensible automations.


2. Processing Collections with Apply to each

When your flow retrieves multiple items—for example, from a Dataverse 'List rows' action or a SharePoint 'Get items' action—it receives an array of data. To process each item in the array individually, you use the Apply to each loop.

Power Automate Cloud Flow with OData Query and Nested Loops
This diagram illustrates a common pattern where an outer loop retrieves categories, and a nested inner loop retrieves the products within each category.

Understanding and Controlling the Loop

Power Automate often adds an Apply to each loop automatically when you select a dynamic content field that belongs to an array. While helpful for beginners, as a developer, you need to understand and control this behavior.

Avoid Unwanted Apply to Each in Power Automate with Arrays & Select Actions – SharePoint Lists

This video from DamoBird365 is excellent for developers. It explains not only how to work with loops but, more importantly, how to avoid them when they are inefficient.

Please watch these two key segments: Why Loops Appear (02:53 - 06:30): This explains how retrieving multiple items results in an array and why Power Automate inserts the loop. Accessing Items Directly (11:20 - 15:56): This is the crucial part. Pay close attention to using expressions with first() or array indexers (e.g., [0]) to access specific items in an array without needing a loop. This is far more efficient if you only need the first item or a specific item.

Professional Consideration: Concurrency Control

This is one of the most important concepts for a developer working with Apply to each loops. By default, Apply to each runs in parallel. It can process multiple items from the array simultaneously (up to 50 by default) to improve performance.

However, this parallelism can cause major problems—specifically, race conditions—if your loop modifies a shared resource, such as a global variable. For example, if you initialize a variable TotalCost to 0 and then try to increment it inside a parallel loop, multiple iterations might read the same initial value, perform their addition, and then overwrite each other's results.

To manage this, you must use Concurrency Control.

Mastering Concurrency Implementation in Power Automate

This article, 'Mastering Concurrency Implementation in Power Automate,' directly addresses the pitfalls of parallel loops and provides the solution.

Read the sections titled 'The Problem: Global Variables in Apply to Each Loops' and 'Why Global Variables and Apply to Each Don’t Mix Well' to understand the race condition issue. Then, review the subsection 'Concurrency Control' under 'Advanced Techniques' and the 'Troubleshooting Guide' for incorrect totals. These sections explain how to enable and configure this setting.

To configure this, click the ellipses (...) on your Apply to each action, go to Settings, and enable Concurrency Control. You can then set the Degree of Parallelism. To force the loop to run sequentially (one item after another), set this value to 1. This is essential for any scenario involving aggregation or stateful operations inside a loop.

Test your understanding!

You are building a flow to process new "Leave Requests" submitted to a SharePoint list. The trigger returns an array of requests. Each request has a 'Category' ('Vacation', 'Sick', 'Personal') and 'NumberOfDays' (a number).

  1. Inside your Apply to each loop, you need to route the request. If the 'Category' is 'Vacation', it goes to an approval flow. If it's 'Sick', it sends an email to HR. If it's 'Personal', it's added to a Dataverse table. What is the most appropriate control action for this routing logic?

  2. You need to calculate the total number of days requested across all items retrieved by the trigger. You've initialized a variable TotalDays to 0 before the loop and are using an Increment variable action inside the Apply to each loop. What critical setting must you configure on the loop to ensure your final TotalDays count is accurate?

  3. The trigger for the flow is a schedule that runs once a day. Before entering the loop, you want to check if the 'Get items' action returned any requests at all. If not, the flow should stop. What control action would you use, and what would the expression look like?

Show answer
  1. A Switch action is best here. You would switch on the item()?['Category'] value, with cases for "Vacation", "Sick", and "Personal".

  2. You must enable Concurrency Control on the Apply to each loop and set the Degree of Parallelism to 1. This forces the loop to run sequentially, preventing the race condition where multiple loop iterations try to update the TotalDays variable at the same time.

  3. You would use a Condition action. The condition would check if the array of items is empty. The expression would use the length() function, like this: length(outputs('Get_items')?['body/value']) is greater than 0. If true, the flow proceeds to the loop. If false, you can use a Terminate action in the 'no' branch.


Conclusion

You've now learned how to control the execution path of your flows, a fundamental skill for building any non-trivial automation. You can make decisions and process entire collections of data with confidence.

Key Takeaways:

  • Use the Condition action for binary if-then-else logic.
  • Use the Switch action for multi-path logic based on a single value's equality.
  • For complex else-if scenarios (like 'contains' or 'greater than'), use the array filtering pattern for a cleaner, more scalable solution.
  • The Apply to each loop iterates over arrays. You can often avoid unnecessary loops by accessing array items directly with expressions (first() or [index]).
  • Crucially, you must manage the Concurrency Control setting in Apply to each loops, setting parallelism to 1 when performing aggregations or modifying shared variables to prevent race conditions.

What's Next

In this lesson, we focused on the "happy paths"—the intended routes your flow should take. But what happens when an action fails or data is not in the expected format? In the next lesson, we will cover configuring robust error handling using scopes, 'configure run after' settings, and try-catch patterns. This will enable you to build resilient, production-ready automations.