Excelgoodies logo +44 (0)20 3769 3689

LEARN THIS HANDS ON

Power Apps & Power Automate

. Live Online FILLING FAST
View all upcoming batches
Designing Reliable Power Automate Flows for Finance and HR Approvals

Designing Reliable Power Automate Flows for Finance and HR Approvals

Finance and HR approvals can’t afford duplicate payments, lost requests, or stuck workflows. This guide shows how to design reliable Power Automate flows for finance and HR approvals using idempotency, retries, and robust error handling patterns.

We’ll walk through concrete patterns, expressions, and design choices you can apply today. If you want to go beyond single flows and design end‑to‑end automated processes across departments, structured training in business process automation skills can help you scale these ideas safely.


Why Finance and HR Approvals Need Extra Care

Approval flows for finance and HR have a few traits that make reliability non‑negotiable:

  • Money or people are impacted
    • Expense reimbursements
    • Vendor invoices
    • Salary changes
    • New hire onboarding and access
  • Strict audit and compliance requirements
    • You must prove who approved what, when, and based on which data.
  • Multiple systems involved
    • ERP, HRIS, payroll, SharePoint, Teams, email, custom APIs.

Because of this, you need flows that:

  1. Never apply the same change twice (idempotency).
  2. Recover gracefully from transient failures (retries).
  3. Surface issues clearly and allow safe re‑runs (error handling).

The rest of this article focuses on patterns that support those three goals.


Idempotency: Preventing Double Approvals and Duplicate Actions

Idempotency means: running the same operation multiple times has the same effect as running it once.

In Power Automate terms: if your flow gets triggered twice for the same approval, it must not:

  • Post the same journal entry twice.
  • Pay the same invoice twice.
  • Create duplicate user accounts.

Step 1: Define a Stable Business Key

First, choose a business key that uniquely identifies the approval case. Examples:

  • Expense approval: ExpenseReportId
  • Vendor invoice: InvoiceNumber + VendorId
  • HR change: EmployeeId + ChangeRequestId

Store this key in every system you touch:

  • As a column in SharePoint / Dataverse.
  • As a custom field in the ERP/HR system if possible.
  • As a correlation ID in logs.

Step 2: Check Before You Act (Idempotent Guard)

Before committing any side‑effect (posting, paying, updating HR data), add a guard step:

  1. Look up the approval record by business key.
  2. Check if the action was already applied.
  3. Only proceed if it has not.

Example for a SharePoint‑backed approval list:

  • List column BusinessKey (single line of text).
  • List column Status (e.g. Pending, Approved, PostedToERP).

Pattern in the flow:

  1. Trigger: When an item is created or modified.
  2. Compose: Build BusinessKey (if not already stored).
  3. Get items: Filter on BusinessKey eq '<key>' and Status eq 'PostedToERP'.
  4. Condition: If length(body('Get_items')?['value']) is greater than 0 → Terminate (already processed).

Expression example:

length(body('Get_items')?['value'])

If greater than 0, you know this business key has already been posted.

Step 3: Mark Completion Atomically

After you successfully call the downstream system (ERP, HR, payroll):

  • Update your central record (SharePoint, Dataverse) to Status = 'PostedToERP' and store:
    • External document ID
    • Timestamp
    • Any reference numbers

This makes your guard check effective on re‑runs.

Step 4: Idempotent External Calls

When calling external APIs, try to:

  • Pass your business key as their idempotency key if they support it.
  • If not supported, still pass it in a custom header or field and store their response so you can:
    • Detect duplicates on your side.
    • Skip re‑creating the same record.

Retries: Handling Transient Failures Without Breaking the Process

Finance and HR flows often call:

  • On‑premise data gateways
  • Cloud APIs with rate limits
  • Email/Teams/SharePoint

These fail transiently more often than you’d like. The default retry behaviour in Power Automate is helpful, but not always sufficient.

When to Rely on Built‑In Retries

Power Automate automatically retries many connector actions on transient errors. For idempotent operations (e.g. GET, status checks), this is usually fine.

Use built‑in retries when:

  • The action is safe to repeat.
  • You’re not updating money or HR master data.
  • The connector is known to be flaky but eventually consistent.

When to Add Custom Retry Logic

Add your own retry logic for:

  • Critical side effects (posting to ERP, payroll updates).
  • Non‑idempotent APIs.
  • Actions behind an on‑premise data gateway.

A simple retry pattern using Do until:

  1. Initialize variables:

    • retryCount = 0
    • maxRetries = 3
    • lastStatus = 'Pending'
  2. Use Do until with condition: or(equals(variables('lastStatus'),'Success'), greaterOrEquals(variables('retryCount'), variables('maxRetries'))).

  3. Inside the loop:

    • Try the critical action (e.g. HTTP call to ERP).
    • On success:
      • Set lastStatus = 'Success'.
    • On failure (in a Configure run after branch):
      • Increment retryCount.
      • Delay for a few seconds.

Example expressions:

or(
  equals(variables('lastStatus'), 'Success'),
  greaterOrEquals(variables('retryCount'), variables('maxRetries'))
)

Increment retry count:

add(variables('retryCount'), 1)

This pattern gives you:

  • Controlled number of retries.
  • Time‑based backoff.
  • Clear logging of each attempt.

Error Handling Patterns That Work in the Real World

Error handling for approvals is about containment and clarity:

  • Contain the failure to a specific request.
  • Make it obvious what failed and what to do next.

Pattern 1: Try/Catch with Scopes

Use Scopes to group related actions and handle errors cleanly.

Basic structure:

  1. Scope: Main Processing
  2. Scope: On Error

Configure On Error scope to run after Main Processing only on has failed, has timed out, or is skipped.

Inside On Error:

  • Update the record status to Error.
  • Write error details to a log list/table.
  • Notify a support mailbox or Teams channel with a link to the item.

Example for capturing error details in a Compose action in On Error scope:

concat(
  'Flow: ', workflow()?['name'], '
',
  'Run ID: ', workflow()?['run']?['name'], '
',
  'Error time: ', utcNow(), '
',
  'Business key: ', variables('BusinessKey'), '
'
)

You can extend this with outputs() from the failed action if needed.

Pattern 2: Human‑Readable Error Messages for Approvers

Finance and HR approvers should never see raw connector error messages.

Instead, for any user‑facing notification:

  • Translate technical errors into:
    • What went wrong in business terms.
    • Whether their action is recorded.
    • What will happen next.

Example email body:

Your approval for invoice 12345 (Vendor: ABC AS) was recorded, but posting to the finance system failed. The finance team has been notified and will re‑process this invoice. You do not need to approve it again.

Behind the scenes, you’ve:

  • Marked the request as Error – Awaiting Reprocessing.
  • Logged the technical error.

Pattern 3: Safe Re‑Run Mechanism

You will need to re‑run flows for specific approvals. Design for it.

Approach:

  1. Add a manual trigger flow: Reprocess Approval.
  2. Input: Business key or item ID.
  3. The flow:
    • Retrieves the record.
    • Checks current status.
    • If status is Error – Awaiting Reprocessing, re‑executes the posting logic.
    • Reuses the same idempotent guard and retry patterns.

This gives finance/HR or IT a controlled way to fix issues without touching data manually in multiple systems.


Logging and Auditability for Approvals

For finance and HR, logging is not just for debugging – it’s for audit.

What to Log

At minimum, log:

  • Business key
  • Requestor (user principal name)
  • Approver(s)
  • Decision (approved/rejected) and comments
  • Timestamps for key steps:
    • Request submitted
    • Approval completed
    • Posted to ERP/HR
  • External reference IDs (ERP document number, HR transaction ID)
  • Error details (if any)

Where to Log

Common options:

  • SharePoint list: Easy to set up, good for smaller volumes.
  • Dataverse table: Better for relational data and larger volumes.
  • SQL database: For organisations already using SQL for reporting.

Whatever you choose, keep it consistent across finance and HR flows so reporting and auditing are straightforward.

Minimal SQL Logging Pattern

If you’re logging to SQL via the SQL connector, a simple INSERT pattern is often enough.

Example INSERT statement (parameterised via action inputs):

INSERT INTO ApprovalLog
( BusinessKey,
  FlowName,
  RunId,
  Requestor,
  Approver,
  Decision,
  Status,
  ExternalReference,
  CreatedOn,
  LastUpdatedOn )
VALUES
( @BusinessKey,
  @FlowName,
  @RunId,
  @Requestor,
  @Approver,
  @Decision,
  @Status,
  GETUTCDATE(),
  GETUTCDATE() );

You can call this from Power Automate’s SQL action with parameters mapped from dynamic content.


Designing the Approval Model Itself

Idempotency and error handling are easier when the approval model is clean.

Separate Approval From Execution

Avoid flows that both:

  • Collect approvals, and
  • Directly post to ERP/HR in the same run.

Instead:

  1. Flow A: Approval Flow

    • Manages approver notifications and decisions.
    • Writes the final decision and metadata to a central store.
  2. Flow B: Execution Flow

    • Triggered when a record is Approved.
    • Handles posting to ERP/HR.
    • Implements idempotent guards, retries, and error handling.

Benefits:

  • Easier to re‑run only the execution part.
  • Clear separation of responsibilities.
  • Shorter, more focused flows.

Multi‑Level Approvals

For multi‑level approvals (e.g. line manager then finance controller):

  • Store each approval step separately with:
    • Approver
    • Decision
    • Timestamp
    • Comments
  • Only mark the record as Approved when all required steps are complete.

This makes audit trails and troubleshooting much easier.


One Practical Takeaway

Before you build your next finance or HR approval flow, start by defining a business key and designing the idempotent guard around it. Once you have that in place, add retries and error handling on top – your flows will be safer to re‑run, easier to support, and far less likely to create duplicate payments or inconsistent HR records.

Power Automate

New

Next Batches Now Live

Power BIPower BI
SQLSQL
Power AppsPower Apps
Power AutomatePower Automate
Microsoft FabricMicrosoft Fabrics
AzureAzure Data Engineering
Explore Dates & Reserve Your Spot → Reserve Your Spot →