Triggers fire twice. Retries happen. Concurrency exists.
Thatβs how you end up with duplicate records, double emails, or repeated approvals.
Idempotent flows fix this by guaranteeing that each business event is processed only once, even if the flow is triggered multiple times.
The core idea
Claim the event before doing any real work. If itβs already claimed, stop the flow.
Example: avoid duplicate invoice creation
Scenario
A flow triggers when a new order is created. Due to retries or parallel runs, the same order may trigger the flow more than once.
Goal
Ensure each order is processed only once.
The pattern
- Choose a unique business key
Something that uniquely identifies the event, for example:- OrderId
- MessageId
- Create a lightweight ProcessedEvents store
Dataverse, SharePoint, or SQL with:- UniqueKey
- ProcessedOn
-
First action = claim the event
Create (or upsert) a row using the unique key.β Success β first time processing
β Duplicate key β already processed - Handle duplicates gracefully
On the duplicate path (Configure run after):- Terminate the flow early
- No retries. No side effects.
This is a standard event-driven architecture pattern β applied in Power Automate.
Try this now
- Pick a flow that must never run twice for the same item
- Identify a stable business key
- Add a claim step as the first action
- Terminate immediately if the key already exists
π‘ Tip
Idempotency is much easier to design upfront than to debug later. Once you use it once, youβll start using it everywhere.
Why this matters
Every production flow eventually faces one of these: a webhook that retries on failure, a polling trigger that fires twice during a service blip, a maker who manually re-runs a failed run βjust to be sure.β Without idempotency, every one of those events becomes a duplicate side effect β a duplicate invoice, a duplicate email, a duplicate approval. With a 30-second claim step at the start of the flow, all of those scenarios become safe by construction.
Common business keys to claim on
- OrderId for order-driven flows.
- MessageId for Service Bus / Event Grid / queue triggers.
- CorrelationId propagated from upstream systems.
- A hash of
(entityId + eventType + truncatedTimestamp)when no natural key exists.
Pick the key that matches the business event, not the trigger payload. βThe same OrderId arriving twiceβ is a duplicate β but βthe same OrderId at a different lifecycle stageβ is not. Your unique key should reflect that distinction (often OrderId + Stage).
Choosing where to store the claim
- Dataverse: best when the flow already touches Dataverse. Use an alternate key on the unique column to get atomic upsert behavior.
- SharePoint list: easy and free, but rate-limited. Fine for low-volume flows.
- Azure Storage Table: cheap, fast, atomic insert with
ETagchecks. Great for high-volume scenarios. - SQL: if you already have it, a unique constraint + INSERT-fail-on-duplicate is rock solid.
Whatever you pick, the rule is the same: the claim must be atomic β two parallel runs cannot both succeed in claiming the same key.
π¬ Comments & Suggestions
Share your thoughts, tips, or drop a useful link below.