Multi-Step Pipeline with Queue Handoffs
Chain multiple flows via Azure Queues - Step 1 validates, Step 2 transforms, Step 3 loads - demonstrating event-driven microflow architecture.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
FlowLibs - Multi-Step Pipeline with Queue Handoffs is a three-flow reference implementation of the event-driven microflow architecture pattern in Power Automate. Each flow performs one stage of a classic ETL pipeline - validate -> transform -> load - and the stages are decoupled with Azure Storage Queues so each step can scale, fail, retry, and evolve independently of the others. The Loader stage gates the final write with a Power Automate Approval so a human stays in the loop on what actually lands in the system of record.
The brief: chain multiple flows via Azure Queues so that Step 1 validates, Step 2 transforms, and Step 3 loads. This solution does exactly that - three separate cloud flows in one Dataverse solution, glued together by two queues (pipeline-validated and pipeline-transformed) and traced end-to-end with a single correlationId GUID.
Use Case
Use this pattern when you need to decouple long, brittle, or differently-scaled stages, survive partial failures, fan out without rewrites, and trace audit-grade lineage through a multi-stage pipeline. A 30-second validation, a 2-second transform, and a 10-minute approval shouldn't share one flow run timer or one connection's throttling budget - splitting them across queue-decoupled stages lets each scale and recover on its own clock. Every message carries the same correlationId from the SharePoint submission all the way through to the final loaded record and the approval response.
The flow is ideal for teams that:
- Decouple long, brittle, or differently-scaled stages so each runs on its own timer and throttling budget
- Survive partial failures - if one stage breaks, upstream stages keep filling the queue and downstream drains the backlog once fixed
- Fan out without rewrites - adding a new stage is a new flow that subscribes to an existing queue, no upstream edits
- Trace audit-grade lineage end-to-end via a single correlationId GUID minted at the front of the pipeline
Flow Architecture
Stage 1 - Validator trigger
SharePoint - When an item is created (GetOnNewItems)5-minute polling on the `FlowLibs - Pipeline Submissions` SharePoint list, with `splitOn @triggerOutputs()?['body/value']` so each new item runs its own flow execution.
Init varCorrelationId
Initialize variableString set to `guid()` - unique trace id minted at the front of the pipeline and carried through every queue message and SharePoint patch.
Init varSubmittedAt
Initialize variableString set to `utcNow()` so the submission timestamp is captured at validation time and embedded in the envelope.
Init varValidationErrors
Initialize variableEmpty array accumulator that the downstream Append blocks push human-readable error messages into.
Init field variables
Initialize variable (varTitle / varAmount / varRequesterEmail / varDepartment / varDescription)Each variable is `coalesce(triggerOutputs()?['body/<col>'], '')` so missing optional columns default to empty and the validator catches them instead of throwing during Init.
If Title is empty
If conditionChecks whether the coalesced Title is blank.
- Append to varValidationErrors — Pushes 'Title is required.' onto the error accumulator.
Empty branch - no action.
If Amount is not positive
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_SharePointSiteURL | String | https://your-tenant.sharepoint.com | Base URL of the SharePoint site hosting the Submissions and Loaded lists. Used by Validator and Loader. |
| flowlibs_PipelineSubmissionsListName | String | FlowLibs - Pipeline Submissions | Display name of the SharePoint list the Validator polls for new submissions. |
| flowlibs_PipelineLoadedListName | String | FlowLibs - Pipeline Loaded | Display name of the SharePoint list the Loader writes approved records into. |
| flowlibs_AzureQueueStorageAccountName | String | <configure> | Name of the Azure Storage account that hosts the two pipeline queues. Set to your actual storage account name. |
| flowlibs_PipelineValidateQueueName | String | pipeline-validated | Azure Storage Queue name that the Validator enqueues to and the Transformer dequeues from. |
| flowlibs_PipelineTransformQueueName | String | pipeline-transformed | Azure Storage Queue name that the Transformer enqueues to and the Loader dequeues from. |
| flowlibs_PipelineApproverEmail | String | you@yourcompany.com | Email address that receives the Approvals `StartAndWaitForAnApproval` request for every transformed message. |
| flowlibs_PipelineHighValueThreshold |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| SharePoint Online | shared_sharepointonline | GetOnNewItems (trigger - Validator) PatchItem (update submission status (Validated/Rejected/Loaded)) PostItem (create loaded record in Loader) |
| Azure Queues | shared_azurequeues | PutMessage_V2 (enqueue validated and transformed envelopes) GetMessages_V2 (dequeue in Transformer and Loader) DeleteMessage_V2 (remove message on successful Scope completion) |
| Office 365 Outlook | shared_office365 | SendEmailV2 (rejection, approval confirmation, and run summary emails) |
| Approvals | shared_approvals | StartAndWaitForAnApproval (Basic approval gating the Loader stage) |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Activate the connections
- Open each flow in the designer once and authorize the four connection references (SharePoint, Azure Queues, Outlook, Approvals). Until then the flows show 'Add an authorized connection' banners - expected for a demo solution shipping Off.
- Provision the Azure Storage Queues
- Create two queues in the Azure Storage account named in flowlibs_AzureQueueStorageAccountName. Default queue names are pipeline-validated and pipeline-transformed. The Azure Queues connector auto-creates queues on first PutMessage_V2, but pre-creating them avoids surprises.
- Re-point the SharePoint lists
- If you don't keep FlowLibs - Pipeline Submissions and FlowLibs - Pipeline Loaded, update the two list-name env vars and let the designer re-bind columns. The Loader's Create_Loaded_Item action contains hardcoded column names (Title, CorrelationId, Amount, RequesterEmail, Department, Priority, ApprovalDecision, Approver, ApprovalComments, SourceListItemId, LoadedAt) - those must match the destination list.
- Tune the recurrences
- Both pollers run every 5 minutes. For higher throughput shorten the cadence; for cost-sensitive deployments lengthen it. The Loader's visibilitytimeout of 1800s assumes the approver responds within 30 minutes; raise it for slow approvers.
- Set the high-value threshold
- flowlibs_PipelineHighValueThreshold defaults to 10000. Items at or above this amount are marked priority: "High" in the transformed envelope. To gate ONLY high-value items, wrap Request_Pipeline_Approval in an If on body('Parse_Transformed_Payload')?['highValue']
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Mint correlation id at the front of the pipeline
Validator `Init_varCorrelationId` - the same GUID is carried through both queue envelopes and every SharePoint patch for audit-grade lineage.
EXPR.02Defensive coalesce on every trigger field
Used in each Init variable so missing optional SharePoint columns default to empty string instead of throwing during initialization - the validator catches the empties downstream.
EXPR.03Three-rung priority computation
Transformer `Compose_Computed_Priority` - nested If for a tri-state output (Low / Standard / High) keyed off the env-var threshold.
EXPR.04Foreach over the queue envelope
Azure Queues `GetMessages_V2` wraps messages in two levels (`QueueMessagesList.QueueMessage`); the `coalesce(..., createArray())` keeps the loop and downstream `length()` calls safe when the queue is empty.
EXPR.05Approval responder extraction
`responses` is an array even on a single-approver Basic approval, so `first(...)` is required to pull the responder email and comments.
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.