Nesting in Power Automate is when actions are added inside containers (Condtion,Apply to Each, Do Until, Switch, Scope).
LowCode/NoCode technology in the big picture is still relatively new, so I often look to ProCode for learnings and best practices, and one of the established best practices is to avoid nesting.
The Secret to Clean and Efficient Code: How to Denest Your Code
But why is it bad for Power Automate, well there are a lot of the same reasons
- Hard to read
- Hard to scale/expand
- Hard to debug
But there is a big one specific to Power Automate and its visual UI, it makes it hard to use the studio.
- The browser becomes slow and unresponsive
- You have to do endless clicks to see the process
So we agree, nesting bad, but how do we build our flows to avoid nesting.
Well for starters we do need nesting, but we just have to follow these 2 golden rules:
- Only if necessary
- Multi-level nesting only if really really really really necessary
Luckily there are a few techniques to help follow those rules π
Easy Wins
These techniques/behaviours are super simple and should be used by even junior devs.
Scopes
Scopes should only be used for 2 reasons, exception handling and build.
Exception Handling
Scopes allow blocks of code to use same exception handling, it is the core reason we have scopes (in my opinion).
Build
During the flow build scopes can help organise your development, with added benefits of easy moving/duplication. It is also a good way to identify if a childflow is needed. But just like composes (used for console.log()/Debug.Print), they should be removed as early as possible and always before production.
Conditions
Want another golden rule, a super more platinum rule, "Expressions before Actions". Power Automate uses the Logic App expression language, its established and feature rich, so can do a lot more then you often realise.
You should never be using a condition to set a string/integer value (variables or action inputs), you should use the if() function in the input.
Apply to Each
Power Automate is missing a key action, a lookup, so we often filter our data to get that one record. Unfortunately this returns the data as an array, which forces an Apply to Each.
Luckily our platinum rule is here, we can select items from an array. You can use the:
first() expression
first(outputs('Get_items')?['body/value'])
or my prefered array position
outputs('Get_items')?['body/value'][0]
Complex
Now the easy ones are out of the way, lets hit the pro dev ones π
Conditions in Conditions
ProCode learnings again, the coolest technique is what are called Guard Clauses.
Guard Clauses: How to clean up Conditionals
In a nutshell they change the approach from branches to linear checks. So you have a condition per option, instead of condition per 2 options. This only works because the options are wrapped in a function, and once the condition is met it escapes the function. This stops multiple matches, when we only wanted the first.
In Power Automate we can replicate this by using escape conditions, I've gone into a lot more detail in this previous blog (Power Automate - Switch, Condition and If()), but it allows use to treat the flow as the function and leave when the condition is met by using a terminate.
It works really well by stopping the bulk of the flow been nested in a condition when the other branch is empty and normally runs to the end to complete.
But we can also expand on our escape clauses and take the other principle, single sided conditions.
Above is how we would do multiple conditions, with lots of the pesky nesting. But there is a way around it, we only use the yes branch. We then run the conditions in series, with each condition either being triggered or skipped. The key thing to add is that for each lower condition, we need to leverage the 'And', and add a condition that says it has to not match the previous conditions (unless you want it to).
A good example of this is the Power Automate game I made (Canyon Escape, its pretty cool so why not check it ou π), I used the technique to handle all of the conditions, and just imagine how hard that would have been all nested.
Conditions in Loops
This one is all about perspective, what's the best way to do a list containing 2 tasks:
- One list, swapping between tasks as you complete one
- Sort it into 2 piles and work one task at a time
If you say the first one we are not friends anymore!
With that in mind that's how we should do our conditions in loops. We should use the filter action, that way we group all our tasks and process them in one loop. The filter for task 2 and do a second loop.
And we get a few more benefits doing it this way:
- Easier to debug (as you can find specific actions and smaller groups to search)
- Uses less api calls (that's right, as the condition uses a api call in the loop it scales up)
Loops in Loops
Loops within loops in probably the most difficult to avoid, but also has the biggest benefits of burning api calls. There are 2 ways to approach the problem.
Office Scripts
Office scripts are great because they are so much better at loops then Power Automate. We can either delegate the nested loops, or pass all the looping requirements. The only issue we have is the payload and timeout. You can send a maximum of 2mb (or maybe 5mb, I forget), and the script can only run for max 2 minutes. So we can't send too much data.
Hidden Arrays
The other approach is to leverage the hidden actions and then use string manipulation to union the results.
What do I mean by hidden actions, well actions inside loops do not show outside of the loop in the Dynamic Value list.
But we can add it manually by typing in the expression:
This creates an array of the action outputs, so we need to turn them into a unified array, and we can do that with string manipulation.
String manipulation is when you turn the json to a string, then use functions like replace() or split() to rebuilt the json. Then we convert it back with the json() function, the expression we need in this case is:
json(
replace(
replace(
substring(replace(replace(string(Outputs('Select')),'{"body":[]},',''),',{"body":[]}',''),
9
,
sub(length(replace(replace(string(Outputs('Select')),'{"body":[]},',''),',{"body":[]}','')),11)
)
,
']},{"body":['
,
','
)
,
',,'
,
','
)
)
And we end up with all of the items in one array:
If you would like to get notified every new blog (I also do a few in the Power Platform Community), subscribe below
Top comments (3)
Superb article and being from a Java/C# background, I always try and apply coding principals. Things like single responsibility (child flows), nested ifs, variables etc. I personally wouldnβt use an if function inside a set as itβs confusing principals, especially in a visual editor. That would be like doing string x = if(something) {do something} which is bad code.
Iβll definitely be passing this onto my team though.
Thank you, its definitely a balancing act, from the visual sied and the log sode. I personally find less actions and clicking easier to read, but you are probably right that in most cases makes using condition may be easier with minum drawbacks.
Scopes always improves the data processing with a good context