Live training: next batches coming soon. Join the waitlist:Waitlists open:Developer Training →Developer →Copilot Studio Training →Copilot Studio →

Power Automate Do Until: Conditions, Count, Timeout and Real Examples

A project manager I work with wanted a flow that waits until her director approves a project in a SharePoint list, then emails the team. There’s no trigger for “wait until this column changes” inside a running flow, so the flow has to check, wait, and check again. That’s exactly what the Do until loop is for.

Below I’ll explain how Do until runs, how to write its condition in basic and advanced mode, how to combine multiple conditions, what the Count and Timeout limits really are (PT1H, P30D and friends), how to read the iteration number, and the mistakes that cause endless loops or timeouts.

Quick answer: Add Control > Do until, set the Loop Until condition (for example varApproved is equal to true), and put the actions to repeat inside it, usually a Delay, a Get item and a Set variable. The actions run first and the condition is checked after each pass. The loop also stops at Count (default 60, max 5,000) or Timeout (default PT1H, ISO 8601).

What Do until does in Power Automate

Do until repeats a group of actions until a condition becomes true. It’s the “loop until” of cloud flows, and you’ll find it under the Control connector next to Condition, Switch and Apply to each. If you’re new to the building blocks, the Power Automate tutorials hub walks through them.

The detail that trips people up: Do until checks its condition after each pass, not before. Microsoft describes it as running all the actions in the loop first and then checking. So the body always runs at least once, even when the condition is already true when the flow reaches the loop.

The loop ends in one of three ways:

  • The Loop Until condition evaluates to true.
  • The loop reaches the Count limit (number of passes).
  • The loop reaches the Timeout limit (total time).

If you need a true “while” loop that may run zero times, put a Condition in front of the Do until and only enter the loop when the work is actually needed.

Set the Do until condition: basic and advanced mode

Let’s start with a simple counter so you can see the mechanics. In an instant flow, initialize an integer variable named Number with the value 10.

Initialize variable action creating the integer variable Number with value 10

Add Do until below it. In basic mode the condition has three parts, just like a Condition action: pick Number from dynamic content on the left, choose is equal to, and type 100 on the right.

Do until Loop Until condition Number is equal to 100 in basic mode

Inside the loop, add a Compose that shows the current value, then an Increment variable action that adds 10 to Number. Without that increment, the condition can never become true.

Compose action inside the Do until loop showing the Number variable
Increment variable action inside Do until adding 10 to Number

Run the flow and the loop stops as soon as Number reaches 100. The run history shows one entry per pass, and you can page through them with the arrows on the Do until card.

Do until run history showing the iterations of the counter loop

Advanced mode lets you type the whole condition as an expression. Select Edit in advanced mode under Loop Until and enter it with a leading @. The basic condition above becomes:

@equals(variables('Number'), 100)

Use advanced mode when you need functions the basic builder can’t express, such as empty(), coalesce(), int() or a mix of and/or groups.

Multiple conditions with and() and or()

Do until accepts any expression that returns true or false, so and() and or() work as they do anywhere else. Both take two or more expressions. I go deeper into grouping in multiple conditions in Power Automate.

Here’s a real case. When someone uploads a file to a Project Documents library, the manager, Adele Vance, has to set Review Status (a Choice column) to Completed and add Reviewer Comments. The loop should keep reminding her until both are done:

@and(equals(outputs('Get_file_properties')?['body/ReviewStatus/Value'], 'Completed'), not(empty(coalesce(outputs('Get_file_properties')?['body/ReviewerComments'], ''))))
Do until Loop until expression in advanced mode combining and(), equals() and empty(coalesce())

Two details matter. A Choice column is an object, so compare its Value. A blank comments column can arrive as null rather than an empty string, so empty(coalesce(x, '')) catches both. More blank-value patterns are in checking if a field is blank in Power Automate.

Inside the loop, the order is: Get file properties (so each pass reads fresh values), Send an email reminder, then Delay. The reminder body looks like this:

Hi Adele,

Please finish the review for @{triggerBody()?['{FilenameWithExtension}']}.
Set Review Status to Completed and add your reviewer comments.

Thanks,
Power Automate
Send an email reminder action inside the Do until loop for the document review
Delay action inside Do until set to wait between review reminders

For an “either” exit, use or(). This one stops when the item is approved or rejected, whichever happens first:

@or(equals(outputs('Get_item')?['body/Status/Value'], 'Approved'), equals(outputs('Get_item')?['body/Status/Value'], 'Rejected'))

After the loop, add the email to the file’s author confirming the review is done.

Review completed email sent to the document author after the Do until loop ends

Do until Count and Timeout limits (PT1H, P30D)

Every Do until has two safety limits. In the new designer you’ll find them under Advanced parameters on the loop; in the classic designer, select Change limits.

Do until advanced parameters with Count set to 5000 and Timeout set to P30D
SettingDefaultMaximumWhat it limits
Count605,000Number of passes through the loop
TimeoutPT1H (1 hour)P30D in practiceTotal time for all passes, in ISO 8601

Microsoft documents the 60 and 5,000 iteration numbers for Power Automate. For Timeout it documents the PT1H default, and the hard ceiling comes from the 30-day limit on any flow run, which is why P30D is the practical maximum. I’d avoid P1M, because a month isn’t a fixed number of days.

ISO 8601 durations start with P. Date units come before T and time units after it, all uppercase:

ValueMeans
PT5M5 minutes
PT1H1 hour (the default)
PT12H12 hours
P1D1 day
P7D7 days
P4DT4H4M4 days, 4 hours, 4 minutes
P30D30 days (the run limit)

Two behaviors are worth knowing. First, Timeout is checked before each new pass, so a long action already running isn’t cut off; the next pass just doesn’t start.

Second, hitting Count or Timeout doesn’t fail the loop. If the last pass succeeded, Do until shows Succeeded and the flow carries on, even though your condition never became true. Add a Condition after the loop to check, and use try catch error handling with Scopes if you want the run to fail loudly.

I tested this with a document review loop limited to 3 passes. The review never finished, so the loop stopped at pass 3, and both the Do until and the flow still show Succeeded:

Do until run that stopped at the Count limit of 3 passes with status Succeeded

Get the current pass number with iterationIndexes()

You don’t always need a counter variable. The iterationIndexes() function returns the index of the current pass inside an Until loop, and it takes the loop’s internal name, which is its display name with spaces replaced by underscores:

Pass @{iterationIndexes('Do_until')} of the review check

The index starts at 0, so the first pass returns 0 and the third pass returns 2, as the run below shows. Wrap it in add(..., 1) if you want the count to start at 1 in emails or log entries.

If you rename the loop to “Wait for review”, the reference becomes iterationIndexes('Wait_for_review'). Microsoft documents it for Until loops, including nested ones.

Compose output inside Do until showing Pass 2 of the review check on the third pass

I use it in reminder emails (“this is reminder 3”) and to escalate after a few passes. For an escalation that needs both a count and a status, a counter variable is easier to read. This condition stops after approval or after 12 checks:

@or(equals(outputs('Get_item')?['body/Status/Value'], 'Approved'), greaterOrEquals(variables('varChecks'), 12))

Real scenario: wait until a SharePoint item is approved

Back to the project manager’s request. The Project Approvals list has an Is Approved Yes/No column that starts as No (an empty box in the list view). When a project is added, the flow should wait until the director sets Is Approved to Yes, then email the project owner.

Project Approvals SharePoint list with owners Megan Bowen and Alex Wilber and Is Approved not yet set

Start with When an item is created on the list, then add a Boolean variable named varApproved set to false.

Initialize variable action creating the Boolean varApproved set to false

Add Do until with the condition varApproved is equal to true and set Count to 10 for testing. In advanced mode the condition is:

@equals(variables('varApproved'), true)
Do until condition varApproved is equal to true with Count set to 10

Inside the loop, add a Delay first. In production I use 15 minutes to an hour; for testing, a few seconds is fine. Then get the SharePoint item by the trigger’s ID so every pass reads the latest value.

Delay action inside the Do until loop with count and unit

Add a Condition that checks Is Approved is equal to true. In the True branch, set varApproved to true and send the email.

Condition inside Do until checking whether Is Approved is equal to true
Set variable action setting varApproved to true in the True branch
Send an email V2 action notifying the project owner about the approval

Create an item, then change Is Approved to Yes a few minutes later. Here the director approved Customer Portal Upgrade on 10/14/2026, and the next pass picked it up:

Project Approvals list after Is Approved is set to Yes for Customer Portal Upgrade

The run history shows how many passes it took before the condition was met.

Run history of the Do until loop showing four iterations before approval

If you only need someone to approve something, though, you don’t need a loop. Start and wait for an approval already waits for the response, and handling approval timeout in Power Automate covers the 30-day limit.

Do until vs Apply to each

Do untilApply to each
RunsUntil a condition is trueOnce per item in an array
Number of passesUnknown up front, capped by Count (max 5,000)Fixed by the array length
Minimum passesAt least 10 if the array is empty
Runs in parallelNo, one pass at a timeOptional, concurrency up to 50
Typical usePolling, waiting for a status, pagingProcessing list items, files, rows

Rule of thumb: if you already have the items, use Apply to each. If you’re waiting for something to change, or you don’t know how many passes you’ll need, use Do until. If two things should happen at the same time instead, look at parallel branches in Power Automate.

Common Do until mistakes and how to fix them

  • No Delay inside the loop. Without one, the loop burns through all 60 passes in seconds and every pass counts against your daily request limits. Always pause between checks when you’re polling.
  • The value is never refreshed. If Get item or Get file properties sits before the loop, the condition keeps testing the same old value. Move the read inside the loop.
  • The variable isn’t updated inside the loop. A condition on varApproved needs a Set variable (or Increment variable) inside the loop, or it can never become true.
  • Type mismatch. Comparing a Choice column object with ‘Approved’, a Yes/No column with the text ‘true’, or a text number with 100 never matches. Use [‘Value’] for Choice, enter true as an expression, and convert text with int().
  • equals() overshoots. If a counter jumps from 95 to 105, equals(x, 100) is never true. Use greaterOrEquals() for counters.
  • Timeout too short. With the PT1H default and a 15-minute Delay, you get about four checks. Raise Timeout to PT12H or P7D when people need time to respond.
  • Assuming a limit means failure. When Count or Timeout ends the loop, it still shows Succeeded. Check the status after the loop.
  • An approval inside the loop. Every pass sends a new approval request. Send it once before the loop, or skip the loop entirely.

When a run does fail, it helps to get alerted quickly. I set that up with an email with the failed flow run link. And if the flow shouldn’t start for every item in the first place, trigger conditions in Power Automate keep it from running at all.

If you’re building approval and waiting logic into your flows, these step-by-step guides are good next reads:

Frequently Asked Questions

Does Do until run at least once in Power Automate?

Yes. Do until runs the actions inside the loop first and checks the condition after each pass, so the body always runs once. Put a Condition before the loop if it shouldn’t run when the condition is already true.

What is the maximum Count for a Power Automate Do until loop?

The default is 60 passes and the maximum is 5,000. If you need more, split the work into several runs or use a child flow.

What does PT1H mean in a Do until timeout?

PT1H is an ISO 8601 duration for 1 hour and is the default Timeout. P starts the duration, T separates date units from time units, and H means hours. PT30M is 30 minutes and P7D is 7 days.

Can a Do until loop run for 30 days?

Yes, set Timeout to P30D and give it enough Count passes with a Delay inside. A flow run can’t last longer than 30 days, so that’s the practical ceiling.

How do I add multiple conditions to a Do until loop?

Select Edit in advanced mode and combine expressions with and() or or(), for example @and(equals(a, 1), equals(b, 2)). Microsoft lists the current loop limits on the Power Automate limits and configuration page.

Leave a Comment