Create loops that repeat workflow actions or process arrays in Azure Logic Apps
Applies to: Azure Logic Apps (Consumption)
To process an array in your logic app workflow, you can create a For each loop. This loop repeats one or more actions on each item in the array. For the limit on the number of array items that a "For each" loop can process, see Concurrency, looping, and debatching limits.
To repeat actions until a condition gets met or a state changes, you can create an Until loop. Your workflow first runs all the actions inside the loop, and then checks the condition or state. If the condition is met, the loop stops. Otherwise, the loop repeats. For the default and maximum limits on the number of "Until" loops that a workflow can have, see Concurrency, looping, and debatching limits.
Tip
If you have a trigger that receives an array and want to run a workflow for each array item, you can debatch that array with the SplitOn trigger property.
Prerequisites
An Azure account and subscription. If you don't have a subscription, sign up for a free Azure account.
Basic knowledge about logic app workflows
"For each" loop
A "For each" loop repeats one or more actions on each array item and works only on arrays. Here are some considerations when you use "For each" loops:
The "For each" loop can process a limited number of array items. For this limit, see Concurrency, looping, and debatching limits.
By default, iterations in a "For each" loop run at the same time, or in parallel. This behavior differs from Power Automate's Apply to each loop where iterations run one at a time, or sequentially. However, you can set up sequential "For each" loop iterations. For example, if you want to pause the next iteration in a "Foreach" loop by using the Delay action, you need to set the loop to run sequentially.
The exception to the default behavior are nested loops where iterations always run sequentially, not in parallel. To run operations in parallel for items in a nested loop, create and call a child logic app workflow.
To get predictable results from operations on variables during each loop iteration, run those loops sequentially. For example, when a concurrently running loop ends, the increment, decrement, and append to variable operations return predictable results. However, during each iteration in the concurrently running loop, these operations might return unpredictable results.
Actions in a "For each" loop use the
@item()
expression to reference and process each item in the array. If you specify data that's not in an array, the logic app workflow fails.
This example logic app workflow sends a daily summary for a website RSS feed. The workflow uses a "For each" loop that sends an email for each new item.
Create this example Consumption logic app workflow with an Outlook.com account or a work or school account.
Between the RSS trigger and send email action, add a "For each" loop.
To add a loop between steps, move your pointer over the arrow between those steps. Select the plus sign (+) that appears, then select Add an action.
Under the search box, select All. In the search box, enter for each. From the actions list, select the Control action named For each.
Now build the loop. Under Select an output from previous steps after the Add dynamic content list appears, select the Feed links array, which is output from the RSS trigger.
Note
You can select only array outputs from the previous step.
The selected array now appears here:
To run an action on each array item, drag the Send an email action into the loop.
Your workflow might look something like this example:
Save your workflow. To manually test your logic app, on the designer toolbar, select Run Trigger > Run.
"Foreach" loop definition (JSON)
If you're working in code view for your logic app,
you can define the Foreach
loop in your
logic app's JSON definition instead, for example:
"actions": {
"myForEachLoopName": {
"type": "Foreach",
"actions": {
"Send_an_email": {
"type": "ApiConnection",
"inputs": {
"body": {
"Body": "@{item()}",
"Subject": "New CNN post @{triggerBody()?['publishDate']}",
"To": "me@contoso.com"
},
"host": {
"api": {
"runtimeUrl": "https://logic-apis-westus.azure-apim.net/apim/office365"
},
"connection": {
"name": "@parameters('$connections')['office365']['connectionId']"
}
},
"method": "post",
"path": "/Mail"
},
"runAfter": {}
}
},
"foreach": "@triggerBody()?['links']",
"runAfter": {}
}
}
"Foreach" loop: Sequential
By default, cycles in a "Foreach" loop run in parallel. To run each cycle sequentially, set the loop's Sequential option. "Foreach" loops must run sequentially when you have nested loops or variables inside loops where you expect predictable results.
In the loop's upper right corner, choose ellipses (...) > Settings.
Under Concurrency Control, turn the Concurrency Control setting to On. Move the Degree of Parallelism slider to 1, and choose Done.
If you're working with your logic app's JSON definition,
you can use the Sequential
option by adding the
operationOptions
parameter, for example:
"actions": {
"myForEachLoopName": {
"type": "Foreach",
"actions": {
"Send_an_email": { }
},
"foreach": "@triggerBody()?['links']",
"runAfter": {},
"operationOptions": "Sequential"
}
}
"Until" loop
To run and repeat actions until a condition gets met or a state changes, put those actions in an "Until" loop. Your logic app first runs any and all actions inside the loop, and then checks the condition or state. If the condition is met, the loop stops. Otherwise, the loop repeats. For the default and maximum limits on the number of "Until" loops that a logic app run can have, see Concurrency, looping, and debatching limits.
Here are some common scenarios where you can use an "Until" loop:
Call an endpoint until you get the response you want.
Create a record in a database. Wait until a specific field in that record gets approved. Continue processing.
Starting at 8:00 AM each day, this example logic app increments a variable until the variable's value equals 10. The logic app then sends an email that confirms the current value.
Note
These steps use Office 365 Outlook, but you can use any email provider that Logic Apps supports. Check the connectors list here. If you use another email account, the general steps stay the same, but your UI might look slightly different.
Create a blank logic app. In Logic App Designer, under the search box, choose All. Search for "recurrence". From the triggers list, select this trigger: Recurrence - Schedule
Specify when the trigger fires by setting the interval, frequency, and hour of the day. To set the hour, choose Show advanced options.
Property Value Interval 1 Frequency Day At these hours 8 Under the trigger, choose New step. Search for "variables", and select this action: Initialize variable - Variables
Set up your variable with these values:
Property Value Description Name Limit Your variable's name Type Integer Your variable's data type Value 0 Your variable's starting value Under the Initialize variable action, choose New step.
Under the search box, choose All. Search for "until", and select this action: Until - Control
Build the loop's exit condition by selecting the Limit variable and the is equal operator. Enter 10 as the comparison value.
Inside the loop, choose Add an action.
Under the search box, choose All. Search for "variables", and select this action: Increment variable - Variables
For Name, select the Limit variable. For Value, enter "1".
Outside and under the loop, choose New step.
Under the search box, choose All. Find and add an action that sends email, for example:
If prompted, sign in to your email account.
Set the email action's properties. Add the Limit variable to the subject. That way, you can confirm the variable's current value meets your specified condition, for example:
Property Value Description To <email-address@domain> The recipient's email address. For testing, use your own email address. Subject Current value for "Limit" is Limit Specify the email subject. For this example, make sure that you include the Limit variable. Body <email-content> Specify the email message content you want to send. For this example, enter whatever text you like. Save your logic app. To manually test your logic app, on the designer toolbar, choose Run.
After your logic starts running, you get an email with the content that you specified:
Prevent endless loops
The "Until" loop stops execution based on these properties, so make sure that you set their values accordingly:
Count: This value is the highest number of loops that run before the loop exits. For the default and maximum limits on the number of "Until" loops that a logic app run can have, see Concurrency, looping, and debatching limits.
Timeout: This value is the most amount of time that the "Until" action, including all the loops, runs before exiting and is specified in ISO 8601 format. For the default and maximum limits on the Timeout value, see Concurrency, looping, and debatching limits.
The timeout value is evaluated for each loop cycle. If any action in the loop takes longer than the timeout limit, the current cycle doesn't stop. However, the next cycle doesn't start because the limit condition isn't met.
To change these limits, in the loop action, select Change limits.
"Until" definition (JSON)
If you're working in code view for your logic app,
you can define an Until
loop in your logic app's
JSON definition instead, for example:
"actions": {
"Initialize_variable": {
// Definition for initialize variable action
},
"Send_an_email": {
// Definition for send email action
},
"Until": {
"type": "Until",
"actions": {
"Increment_variable": {
"type": "IncrementVariable",
"inputs": {
"name": "Limit",
"value": 1
},
"runAfter": {}
}
},
"expression": "@equals(variables('Limit'), 10)",
// To prevent endless loops, an "Until" loop
// includes these default limits that stop the loop.
"limit": {
"count": 60,
"timeout": "PT1H"
},
"runAfter": {
"Initialize_variable": [
"Succeeded"
]
}
}
}
This example "Until" loop calls an HTTP endpoint,
which creates a resource. The loop stops when the
HTTP response body returns with Completed
status.
To prevent endless loops, the loop also stops
if any of these conditions happen:
The loop ran 10 times as specified by the
count
attribute. The default is 60 times.The loop ran for two hours as specified by the
timeout
attribute in ISO 8601 format. The default is one hour.
"actions": {
"myUntilLoopName": {
"type": "Until",
"actions": {
"Create_new_resource": {
"type": "Http",
"inputs": {
"body": {
"resourceId": "@triggerBody()"
},
"url": "https://domain.com/provisionResource/create-resource",
"body": {
"resourceId": "@triggerBody()"
}
},
"runAfter": {},
"type": "ApiConnection"
}
},
"expression": "@equals(triggerBody(), 'Completed')",
"limit": {
"count": 10,
"timeout": "PT2H"
},
"runAfter": {}
}
}
Get support
- For questions, visit the Microsoft Q&A question page for Azure Logic Apps.
- To submit or vote on features and suggestions, Azure Logic Apps user feedback site.
Next steps
Feedback
Submit and view feedback for