DigitalAdaption Book a data risk call
Readiness Review Services Case Studies Guides Blog About Book a data risk call
Guides / Multi-Approver Approvals

Power Automate Approval Workflows With Multiple Approvers: Sequential, Parallel and Escalation

Quick answer

There are three usable multi-approver patterns and one action that delivers all of them. Parallel is a single Start and wait for an approval action with several people in Assigned To, set to Approve/Reject - Everyone must approve or First to respond. Sequential is either the Sequential Approval type or two approval actions with a Condition between them, so a rejection at stage one stops the process. Escalation and reminders are not built in at all: you have to split the work into a flow that creates the approval, a flow that reacts to the response, and a scheduled flow that chases what is still outstanding.

Most multi-approver approvals do not fail. They stall, quietly, in a run that shows no error. This guide covers the three patterns, what the approval action actually hands back, and the specific ways each one breaks in a real organisation.

Book a data risk call Power Automate support

Home / Guides / Approvals With Multiple Approvers

Last updated: 3 August 2026. By Matty Hatton, founder of Digital Adaption.

A purchase requisition for GBP 18,000 has been sitting somewhere for eleven days. Operations think it is with finance. Finance think it went to the plant manager, who was on leave the week it was raised. Someone opens the flow run history expecting a red cross, and finds a blue clock icon next to Start and wait for an approval. No failure, no warning. The flow is doing exactly what it was told to do, which is wait.

That is the normal failure mode of multi-approver approvals. A single-approver flow is a straight line: ask one person, branch on the answer. The moment a second approver appears you have to settle three questions nobody asks out loud. Do they decide together or in order. Does one rejection kill the whole thing. And what happens when one of them simply does not respond. This guide covers what the action returns once more than one person is involved, the three patterns that work in production, and the failure modes that surface months later. If this is your first approval flow, start with the shared mailbox approval flow guide.

Why this happens

The Approvals connector is not a workflow engine in the way people assume. It is a single action that creates a record, sends notifications, then suspends the run on a webhook until a response arrives. Everything that looks like process design, the routing, the ordering, the chasing, is either an approval type you pick from a dropdown or something you build yourself with ordinary flow logic.

The dropdown is the part most people never read properly. Approval type is the first field on the action and it silently determines when the flow resumes and what shape the output takes. Microsoft's everyone must approve documentation sets out the four core types:

Approval typeWhat the action waits for
Approve/Reject - Everyone must approveAll approvers approve, or any single approver rejects
Approve/Reject - First to respondAny one approver decides for everyone
Custom responses - Wait for all responsesAll approvers respond, using your own response options
Custom responses - Wait for one responseAny one approver responds, using your own response options

A fifth option, Sequential Approval, is documented separately under set up sequential approvals and turns the single action into an ordered set of steps. The second reason this goes wrong is that the connector is deliberately thin. There is no reminder setting, no expiry setting in the designer, no delegation and no out-of-office handling. Those are all your problem, and nothing signals that they are missing until a request goes cold.

1. What the approval action actually returns

Before choosing a pattern, understand the output, because this is where multi-approver flows most often produce silently wrong results.

The action surfaces two top-level tokens and one collection. Outcome is the headline result. Response summary is a readable string suitable for an email. Responses is an array with one entry per response received, each carrying the approver's name and email under a responder object, the response, the comments, and both a request date and a response date.

Here is the trap. With one approver, Outcome is the string Approve or Reject and an equality test works. With several it does not. Microsoft describes Outcome for the everyone-must-approve type as "an array of Approve or Reject elements, based on the number of responses to the request", so a condition comparing Outcome to Approve falls down the false branch of logic that looks obviously correct on screen. Test for a rejection instead, or read the collection directly:

@contains(
  string(outputs('Start_and_wait_for_an_approval')?['body/outcome']),
  'Reject'
)

first(outputs('Start_and_wait_for_an_approval')?['body/responses'])?['approverResponse']

first(outputs('Start_and_wait_for_an_approval')?['body/responses'])?['responder']?['email']

formatDateTime(
  first(outputs('Start_and_wait_for_an_approval')?['body/responses'])?['responseDate'],
  'dd/MM/yyyy HH:mm'
)

Three further points catch people out. With everyone-must-approve, Responses does not reliably hold one entry per approver, because a single rejection completes the request immediately and the people who had not yet responded never will, so expect gaps when you loop it. The Approve and Reject strings are case-sensitive. And if you switch to a custom response type, approverResponse holds your own option text, so every condition written against Approve stops working the moment somebody renames a button.

One detail with real consequences for finance teams: approval timestamps are always shown in UTC. Between late March and late October a British approval logged at 09:15 is recorded as 08:15. If an auditor will read the record, convert it explicitly with convertTimeZone.

2. Pattern one: parallel, everyone asked at once

Parallel is the right default when the approvers are peers, the decision is not a hierarchy, and elapsed time matters more than filtering. A capital expenditure request needing sign-off from the department head, the finance business partner and the site engineering manager is a parallel approval. None of them is waiting on the others to form a view.

Use a single Start and wait for an approval action and put every approver into Assigned To, separated by semicolons. The Approvals connector reference confirms the field accepts email addresses (not only the primary address), user principal names and Microsoft Entra ID user IDs, and that you can mix formats in one list. Then pick the approval type against the actual business rule: all three signatures required means Everyone must approve, any one duty manager may authorise means First to respond.

Do not hard-code the list. That is the single biggest cause of dead approval flows a year after go-live. Resolve it at run time from a group or a configuration list and join it:

join(body('Select_approver_emails'), ';')

where Select_approver_emails is a Data Operations Select action mapping the mail column out of an Office 365 Groups list-members call or a SharePoint configuration list. When the panel changes, the change is made in one place by someone allowed to make it, not by editing a production flow.

Parallel branches are a different thing

Microsoft's parallel approvals tutorial uses a different technique: separate approval actions on branches added with Add a parallel branch. Be deliberate about which you want.

One action, several peopleSeveral actions on branches
Records createdOne approval, one request per personOne independent approval per branch
Early exit on rejectionYes, with everyone-must-approveNo, every branch runs to completion
Per-approver follow-on stepsAwkward, requires looping ResponsesNatural, each branch has its own condition
Best forOne decision needing several signaturesIndependent decisions with different downstream work

The published connector limitations bite hardest here. Custom response approvals sent to a large group with everyone-must-approve can fail outright on data size limits, so keep those panels small. Approval emails are only actionable when sent from Microsoft's standard address, so a branded notification produces an email that looks right and cannot be actioned. And the flow creator is always shown in the approval details regardless of the Requestor field, an anti-spoofing measure that confuses every finance team seeing an IT service account named as the requester of a purchase order.

3. Pattern two: sequential, each approver in turn

Sequential is correct when later approvers should not be troubled unless earlier ones agree, or when the stages ask genuinely different questions. Line manager confirms entitlement, finance confirms the budget exists, a director confirms above a threshold. Asking all three at once wastes a director's attention on requests the line manager was always going to refuse.

Option A: the built-in Sequential Approval type

Add Start and wait for an approval, choose Sequential Approval, fill Assigned To - 1 and use Add new item for each further step. Step one is asked first and step two is only raised if step one approves.

The documented limitation is short and important: you cannot assign the same approver to different steps of the same approval. If your path is "manager, then manager's manager" and in a small firm those resolve to the same person, the configuration will not stand. Resolve both with Get manager (V2), compare them, and fall back to a single-step approval when they match.

Option B: two actions with a condition between them

This is the pattern in Microsoft's sequential approvals tutorial, and it remains the right answer whenever stages are conditional. The built-in Sequential type runs every step you configure, so it cannot skip a stage based on value. Two actions and a condition can.

Trigger: When an item is created (SharePoint)
  Get manager (V2)                        -> line manager
  Start and wait for an approval          -> stage 1, line manager
  Condition: contains(string(outcome), 'Reject')
    True  -> mark Rejected, notify requester, terminate
    False -> Condition: Value gt 5000
               True  -> Get manager (V2) 2, Start and wait for an approval 2
               False -> mark Approved

Two habits make this maintainable. Rename every action to what it means, because Start_and_wait_for_an_approval_2 tells the next person nothing and the name is baked into every expression referencing it. And write the stage-one decision to your source record before starting stage two, so a run that dies between stages still leaves evidence of the first signature.

Sequential is the pattern most exposed to elapsed time, because the clock runs in series, and the one where a stalled middle stage is hardest to spot: the requester sees "in progress" and cannot tell which of three people to chase. Write the current stage back to the source record at every step.

4. Pattern three: escalation and reminders

Neither previous pattern handles the most common real complaint, which is that nobody responded at all. Approvers get one notification when the request is raised and nothing afterwards. There is no setting to change that.

The instinct is to add a parallel branch containing a Delay and a reminder email. It does not work, because Power Automate has no concept of one branch winning and cancelling the other. Both run to completion, so the reminder goes out whether or not the approval was granted, and you chase people for decisions they made three days earlier.

Split the process into three flows

Stop trying to hold the whole process inside one run. This mirrors Microsoft's own recommendation for anything long-running, which is to store approvals in Dataverse and use two flows, one to send and one to act on responses.

  1. The initiator. Triggered by the business event. Uses Create an approval rather than Start and wait for an approval, so the run does not suspend. Captures the returned approval ID, writes a tracking row with the item reference, approver and due date, then finishes in seconds.
  2. The responder. Uses Wait for an approval against that approval ID and does the real work when the decision arrives: update the source record, notify the requester, write the audit row, close the tracking row.
  3. The chaser. A scheduled flow, once a working day. Reads the tracking list for rows still open past their due date and acts by age: a reminder at day three, a copy to the approver's manager at day seven, escalation or reassignment at day ten.

Due dates are arithmetic on the tracking row:

addDays(utcNow(), 3, 'yyyy-MM-dd')

The split has a second benefit worth more than the reminders. Each flow is short, so each run is legible, a failure in the chaser cannot leave an approval in limbo, and nothing depends on a single run surviving for weeks.

Actually reassigning an approval

Escalation and reassignment are different things. Notifying a manager is easy. Moving a pending approval to someone else is not exposed in the designer at all.

Two things are true. The action has an Enable reassignment option letting the assigned approver hand the request on from the approvals centre. Turn it on: it costs nothing and solves the holiday case, provided the approver is present enough to use it. If the approver cannot act at all, the only supported route is Dataverse. Approvals live in the environment in the Approval table (msdyn_flow_approval) and the user-owned Approval Request table (msdyn_flow_approvalrequest), which carries an Allow Reassignment flag, a Reassigned From lookup and a Reassigned status reason. Changing the owner of an active Approval Request row moves the pending request.

Action:  List rows (Microsoft Dataverse)
Table:   Approval Requests
Select:  msdyn_flow_approvalrequest_name,statecode,statuscode,ownerid,createdon
Filter:  statecode eq 0

Be clear about the cost first. The Microsoft Dataverse connector is classed as Premium for Power Automate while the Approvals connector is Standard, so the moment your escalation logic touches those tables the flow needs a paid licence it did not need before. How to size that is covered in the Power Automate licensing guide.

5. Choosing between the three

SituationPatternConfiguration
Several signatures, all required, peersParallelOne action, Everyone must approve
Any one of a rota can authoriseParallelOne action, First to respond, membership resolved at run time
Fixed hierarchy, always the same stagesSequentialSequential Approval type
Stages depend on value, risk or categorySequentialTwo actions with a Condition between
Approvers are slow or absentEscalationThree flows: initiator, responder, chaser
Process may run beyond a monthEscalationCreate an approval plus Wait for an approval

Most flows that survive contact with a real organisation are a parallel or sequential core wrapped in the escalation structure. The first two decide who signs. The third decides what happens when they do not.

6. Edge cases and variations

Approvers outside the organisation. You can send approvals to Microsoft Entra B2B guests, but actionable approval emails are not supported for guest users. They receive a notification and must open the Power Automate portal to respond, which most external suppliers will not do unprompted. Send a separate explanatory email alongside.

Group mailboxes. Assigned To is documented as taking user identities, not distribution groups, so expand the membership yourself and pass a semicolon-joined list of individuals with First to respond. That also gives you what a group address never does: a record of which specific person decided. Approvals raised from a shared mailbox have their own quirks, covered in the shared mailbox approval guide.

Custom responses. Options beyond Approve and Reject are often better modelled than a forced binary, particularly for a "return for amendment" state. Two cautions: rewrite every downstream condition, and keep the panel small, because custom responses with everyone-must-approve are documented as able to fail on large groups.

Cancelling and bulk runs. A withdrawn requisition does not cancel its approval; the sender must cancel from Approvals, Sent, Cancel, and cancellation is supported on the Create an approval action. Build that path deliberately if source records can be voided. Separately, the connector throttles approval creation at 50 create requests per flow per 60 seconds, so a month-end job raising 400 approvals in a loop needs concurrency control or a delay inside the loop.

7. Troubleshooting checklist

Work down this list before rebuilding anything. The cause is usually in the first four.

  1. Is the run waiting or failed? A blue clock means the platform is fine and a human is the bottleneck. A red cross means something else entirely. Do not treat them the same.
  2. Is the approval type the one you meant? First to respond on a flow that needs three signatures completes on the first click, and nothing about the run looks wrong.
  3. Is your condition comparing Outcome to a single word? With multiple approvers that fails. Test the Responses collection, or use a contains check against the string form of Outcome.
  4. Does the approver still exist? Requests are owned by a user record. A disabled account holds the request and nobody else can act on it.
  5. Is the approver a person or a group address? If a group went into Assigned To, resolve the membership at run time and pass individuals.
  6. Has the run passed 30 days? Run duration is capped at 30 days including flows with pending steps such as approvals, and pending steps time out once it is reached.
  7. Was the response case-correct? Approve and Reject are case-sensitive, and hand-typed conditions frequently are not.
  8. Are you being throttled? Check for 429 responses on any flow that creates approvals in a loop.
  9. Has the flow been switched off? A cloud flow not triggered within 90 days may be suspended. An annual policy sign-off is exactly the shape that gets caught by this.
  10. Do you have evidence outside the run? If not, the audit trail is on a 30 day clock.

The audit trail problem, specifically

Six months after go-live somebody asks who approved a particular purchase. The natural place to look is the flow run, and it is not there: run history is retained for 30 days from the run start time. The approval records persist in the Dataverse tables, but reading them needs the premium connector and they were never designed as a reporting surface.

The fix is cheap at build time and expensive afterwards. At the moment of decision, write one row of your own to SharePoint, SQL or Dataverse holding the source record reference, the approver's email, the response, the comments, the response date converted out of UTC, and the approval type used. Five minutes per flow, and the difference between answering an auditor in a minute and reconstructing an authorisation from memory.

Most approval work I get called into is not really an approval problem. It is a process nobody wrote down, encoded into a flow by whoever was available, with the approver list typed into a field. If that describes yours, Power Automate consultancy is the place to start: I map what the process actually is, decide which of these three patterns fits, and build it so the approver list is data rather than configuration.

For sign-off routing, escalation design and audit records that outlive the flow run, see approval workflow consultancy. If the flow you are building has just shown you a premium connector warning, the Power Automate licensing guide explains what triggered it and what you need to buy. Where approvals are one symptom of wider manual handoffs, business process automation covers the broader piece. Delivery is ISO 9001 certified, which here mostly means the documentation describes what was built rather than what was intended.

Frequently asked questions

How do I add multiple approvers to a Power Automate approval?

Put every approver into the Assigned To field of the Start and wait for an approval action, separated by semicolons. The field accepts email addresses, user principal names and Microsoft Entra ID user IDs, and you can mix them. Then pick the approval type that matches the rule: Approve/Reject - Everyone must approve if all of them must agree, or Approve/Reject - First to respond if any one of them can decide.

What is the difference between sequential and parallel approvals in Power Automate?

Parallel asks every approver at the same time and waits for either all responses or the first, depending on the approval type. Sequential asks approver one first and only raises approver two if approver one approves, so a rejection at stage one stops the process before later approvers are contacted. Sequential costs elapsed time. Parallel costs the ability to filter out obviously wrong requests early.

Does Power Automate send approval reminders automatically?

No. The Start and wait for an approval action has no reminder or escalation setting in the designer. Approvers get one notification when the request is created and nothing after that. If you need chasing, you have to build it, normally by splitting the process into a flow that creates the approval, a flow that reacts to the response, and a scheduled flow that finds items still outstanding past their due date.

What happens if a Power Automate approver leaves the company?

Nothing visible, which is the problem. Approval requests are owned by an individual user record, so if that account is disabled the request stays with it and nobody else can act. The run waits with no error until it hits the 30 day run duration limit, at which point the pending step times out. Resolve approvers at run time from a group or lookup table rather than typing an address into the action, and enable reassignment.

Why does my condition on the approval Outcome always fail with multiple approvers?

Because Outcome is not a single word once more than one person is involved. Microsoft documents it as an array of Approve or Reject elements based on the number of responses, so a condition testing Outcome is equal to Approve will not match. Test the Responses collection instead, or use a contains check against the string form of Outcome. Custom response types make it worse, because approverResponse then holds your own option text.

How long does Power Automate keep a record of who approved something?

Flow run history is retained for 30 days from the run start time, so the run showing the approver, comment and timestamp is gone before most audits. The approval records live in Dataverse tables in the environment, but querying them needs the premium Microsoft Dataverse connector. For a defensible audit trail, write your own row at the moment of decision, and remember that approval timestamps are always UTC.

Getting this right the first time

The three patterns are not difficult. What makes multi-approver approvals expensive is that the wrong choice does not announce itself. A first-to-respond type on a flow that needed three signatures runs perfectly for a year, and the failure is found by an auditor rather than a user.

If you have an approval process that is stalling, or one you are about to build and want to get right before it becomes load-bearing, get in touch. Half an hour is normally enough to work out which pattern you need and where the current one leaks.

Start with a 30-minute call

Find out where your approval process is leaking before an auditor does.

Book a 30-minute call See Power Automate support