Queue-Based Order Processing Pipeline
Place new orders on an Azure Queue, then process them sequentially — validate, update Dataverse, and send confirmation email.
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
This flow is the consumer side of an event-driven order processing pipeline. It polls an Azure Queue at a fixed interval, dequeues a batch of order messages, validates each one, persists it as an activity record in Dataverse, and emails the customer a confirmation. Failures and validation rejections are routed to the operations team for triage.
Queue-based decoupling is the core pattern: a separate producer (a Power App, a website checkout, an upstream Power Automate flow, or an external system) drops new orders onto an Azure Storage Queue, and this flow processes them in its own cadence. That separation lets the order intake survive bursts and absorbs downstream slowness without losing data.
Use Case
A retail or B2B operations team wants every new order — whether it comes from a web checkout, a sales rep submission, or an EDI feed — funneled through a single processing pipeline that survives spikes in volume, logs every order for audit, notifies the customer immediately, surfaces malformed orders to operations, and can be extended with new downstream actions without touching the queue plumbing.
The flow is ideal for teams that:
- Survives spikes in volume without Power Automate hitting per-flow concurrency limits
- Logs every order for audit before downstream systems touch it
- Notifies the customer immediately so they have a paper trail
- Surfaces invalid or malformed orders to the operations inbox instead of silently dropping them
- Can be extended (warehouse update, payment capture, shipping label) by adding actions inside the per-message Scope without touching the queue plumbing
Flow Architecture
Every_15_Minutes
Recurrence (built-in)Fires every 15 minutes starting 2026-04-26T09:00:00 EST. Sequential downstream flow keeps counter accumulation race-free.
Init_varQueueName
Initialize VariableString, bound to env var flowlibs_AzureQueueOrderQueueName (default order-processing).
Init_varStorageAccount
Initialize VariableString, bound to env var flowlibs_AzureQueueStorageAccountName. Documentation only — the connection holds the actual auth.
Init_varOperationsEmail
Initialize VariableString, bound to env var flowlibs_OperationsTeamEmail.
Init_varConfirmationCc
Initialize VariableString, bound to env var flowlibs_OrderConfirmationEmailRecipient (audit CC on customer confirmations).
Init_varConfirmationSubject
Initialize VariableString, bound to env var flowlibs_OrderConfirmationSubject.
Init_varProcessedCount
Initialize VariableInteger counter set to 0; incremented per successfully processed order.
Init_varInvalidCount
Initialize VariableInteger counter set to 0; incremented per validation rejection.
Init_varFailedCount
Initialize VariableInteger counter set to 0; incremented per scope failure.
Get_Messages_From_Queue
Azure Queues GetMessagesEnvironment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_AzureQueueStorageAccountName | String | <configure> | Documents which Azure Storage account hosts the queue. Read by the flow but the actual connection auth lives in the Azure Queues connection reference. Set to your storage account name (e.g. mycompanyqueues). |
| flowlibs_AzureQueueOrderQueueName | String | order-processing | Name of the queue this flow polls. The queue must already exist in the storage account before the flow runs. |
| flowlibs_OrderConfirmationEmailRecipient | String | <configure> | CC'd on every customer confirmation email so the business has an audit copy. Set to your internal audit/orders inbox. |
| flowlibs_OperationsTeamEmail | String | alerts@yourcompany.com | Distribution list that receives invalid-order alerts and the post-run summary. |
| flowlibs_OrderConfirmationSubject | String | Your order has been received and is being processed | Base subject line for customer confirmations. The flow appends ' (#orderId)' to identify the order. |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| Azure Queues | shared_azurequeues | GetMessages (Pulls up to 20 messages with 300s visibility timeout) DeleteMessage (Requires both MessageId and PopReceipt from the lease) |
| Microsoft Dataverse | shared_commondataserviceforapps | CreateRecord (Writes to the built-in tasks activity entity) |
| Office 365 Outlook | shared_office365 | SendEmailV2 (Customer confirmation, invalid-order alert, and run summary) |
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.
- Producer side (out of scope for this flow)
- This flow only consumes the queue. To produce orders, build a separate flow or app that calls the Azure Queues PutMessage action with a JSON payload containing orderId, customerName, customerEmail, amount, and items[]. Match the queue name to flowlibs_AzureQueueOrderQueueName and use the same Azure Queues connection (or a different one pointed at the same storage account).
- Adjusting the polling cadence
- Edit the Every_15_Minutes recurrence trigger. For high-volume scenarios, drop the interval to 1 minute and increase numofmessages from 20 to the 32-message-per-call cap. For low-volume B2B feeds, raise to 1 hour and keep numofmessages at 20. Remember that Azure Storage Queue messages have a default 7-day TTL — make sure your polling cadence times the visibility timeout doesn't allow messages to expire while waiting.
- Targeting a real orders table instead of tasks
- The flow creates a Dataverse tasks activity record per order. To target your own table: (1) replace entityName: 'tasks' in Create_Order_Task_In_Dataverse with your entity set name (e.g. flowlibs_orders); (2) replace item/subject, item/description, item/scheduledend, item/prioritycode with the slash-path keys for your table's columns (e.g. item/flowlibs_orderid, item/flowlibs_customeremail, item/flowlibs_amount); (3) hardcode the entity name directly — do not bind it to an env var, because variable-driven entityName causes false-positive Flow Checker errors.
- Adding downstream steps
- Inside the Try_Process_Order Scope, after Send_Customer_Confirmation_Email and before Increment_Processed_Count, add any of: inventory check / reserve (HTTP or Dataverse UpdateRecord against an inventory table); payment capture (Stripe / Authorize.net / Adyen connector or HTTP); shipping label generation (HTTP to your 3PL's REST API); Slack or Teams notification to the fulfillment channel. Wrap each new step in its own Scope only if its failure should NOT block the rest of the order processing — otherwise let it fail naturally and let the outer Scope handle the retry-on-next-poll behavior.
- Routing invalid messages to a dead-letter queue
- The current flow alerts the operations team on validation failure but still deletes the message. To preserve the bad payload for forensics, add a PutMessage action to a separate dead-letter queue inside the validation 'no' branch, before Increment_Invalid_Count. Use a flowlibs_DeadLetterQueueName env var (e.g. default 'flowlibs-orders-deadletter') to drive the queue name.
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.01Defensive Foreach iterator
Returns an empty array when the queue had no messages so the loop is a no-op rather than failing.
EXPR.02Coerce order amount to float
Coerces the JSON amount to a float, defaulting to 0 if missing. Avoids InvalidTemplate: cannot convert null to float when the producer sends incomplete payloads.
EXPR.03Three-rule validation expression
Flat operator format for the Validate_Order_Fields If condition — the outer object has exactly one top-level key (and).
EXPR.04Queue message identifiers used by DeleteMessage
Fields on each queue-message item that the DeleteMessage action needs. The popreceipt parameter on DeleteMessage is lowercase per the connector swagger — don't reference it as PopReceipt in the parameter name.
EXPR.05Customer confirmation subject line
Appends the order ID in parentheses, e.g. 'Your order has been received and is being processed (#ORD-2026-00042)'.
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.