Skip to content
Back to skills

Flow Transaction Finalizer Patterns

ASecurity

Use when a Flow needs to do work that must survive the triggering transaction — post-commit notifications, callouts, audit rows, or compensating actions. Covers Flow Transaction Control element, scheduled paths, Platform Event + finalizer. NOT for general Flow async decisions (see async-selection) — use apex/apex-transaction-finalizers.

  • 15 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 6, 2026
ai-agentsgospringawsdebugging

Security analysis

A100/100

Pro scans all 7 files and shows the line behind each finding

Scanned September 6, 2026

npx -y skills add PranavNagrecha/AwesomeSalesforceSkills --skill flow-transaction-finalizer-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Flow Transaction Finalizer Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Flow Transaction Finalizer Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/pranavnagrecha-flow-transaction-finalizer-patterns/badge)](https://www.skillsdirectory.com/skills/pranavnagrecha-flow-transaction-finalizer-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: flow-transaction-finalizer-patterns
description: "Use when a Flow needs to do work that must survive the triggering transaction — post-commit notifications, callouts, audit rows, or compensating actions. Covers Flow Transaction Control element, scheduled paths, Platform Event + finalizer. NOT for general Flow async decisions (see async-selection) — use apex/apex-transaction-finalizers."
category: flow
salesforce-version: "Spring '25+"
well-architected-pillars:
  - Reliability
  - Operational Excellence
  - Scalability
triggers:
  - "flow post commit action"
  - "run flow logic after save"
  - "flow transaction control element"
  - "guaranteed post-commit step"
  - "flow callout after transaction"
tags:
  - flow
  - transaction
  - finalizer
  - reliability
  - post-commit
inputs:
  - Flow that currently does pre- or in-transaction work
  - Work that must happen post-commit (email, callout, event emit, compensating update)
  - Failure tolerance for the post-commit step
outputs:
  - Post-commit execution pattern (scheduled path, platform event, Apex Queueable finalizer)
  - Retry / durability story
  - Monitoring hook
dependencies: []
version: 1.0.1
author: Pranav Nagrecha
updated: 2026-08-14
---

# Flow Transaction Finalizer Patterns

## Purpose

Salesforce transactions are atomic: either every DML commits or none does.
But some work should only run AFTER commit — sending an email, firing a
webhook, writing an audit log to an external system, or issuing a
compensating action if a callout later fails. Getting this wrong produces
two common failures: "email sent but record rolled back," or "record saved
but downstream never notified." This skill codifies the patterns Flow
designers should use for reliable post-transaction behavior, and when to
escalate to Apex Queueable with a Finalizer.

## Recommended Workflow

1. **Classify the step.** Pre-commit (validation), in-transaction (DML), or
   post-commit (notify / callout / external effect)?
2. **Separate two guarantees that sound alike.** *Post-commit execution* — the
   work runs only if the transaction committed — is available three ways in Flow.
   *Post-outcome execution* — a callback that runs whether the work succeeded or
   threw — is not available in Flow at all.
3. **For post-commit work, default to the Run Asynchronously path.** It runs
   after the original transaction for the triggering record is successfully
   committed, in its own transaction, and it is what makes a callout legal. It is
   available only on after-save record-triggered flows, and you cannot give it a
   time.
4. **Use Platform Events when the consumers should be decoupled,** not merely
   deferred — three independent subscribers where adding a fourth should not
   touch the publisher. Confirm the definition is set to Publish After Commit.
5. **Cross into Apex when the work must report its own outcome or retry with a
   bound.** A Queueable's `System.Finalizer` reads `ParentJobResult.SUCCESS` or
   `UNHANDLED_EXCEPTION` and can re-enqueue a failed job up to five times.
6. **Design idempotency at the boundary.** Every mechanism here can run twice.
   The key must be deterministic and derived from the record — never
   `$Flow.InterviewGuid`, which differs on exactly the run you are guarding
   against.
7. **Log every run and every give-up.** Nobody is watching post-commit work. A
   silent stop at the platform's retry ceiling is indistinguishable from success.

## Available Mechanisms

| Mechanism | Runs | Survives rollback | Callouts | Reports its own outcome |
|---|---|---|---|---|
| Pre-commit Flow step | Same txn | No | No | No |
| After-save flow, immediate path | Same txn, before commit | No | No | No |
| **Run Asynchronously path** | New txn, after commit | Yes | Yes | No |
| Platform Event (Publish After Commit) → subscriber | New txn | Yes | Yes, in the subscriber | No |
| Queueable + `System.Finalizer` | Async, after commit | Yes | Yes | **Yes** |

The last column is the whole decision. Everything above the bottom row defers
work; only the bottom row tells you what happened to it.

## Patterns

### Pattern A: Run Asynchronously Path

The default for "must not fire on rollback" and for any callout. Open the
after-save record-triggered flow → **Start** element → include a Run
Asynchronously path. The path runs after the original transaction for the
triggering record commits, so the external system is never told about a record
that rolled back. Add a fault connector to a log record — it is the only evidence
the path ran.

Subject to the asynchronous per-transaction Apex limits (200 SOQL, 60,000 ms CPU,
12 MB heap): higher than synchronous, not absent. Queued entries are visible on
the Time-Based Workflow page in Setup.

### Pattern B: Platform Event For Fan-Out

Choose this over three asynchronous paths when the consumers are genuinely
independent — the benefit is that adding a fourth subscriber does not touch the
publisher, not extra durability. Verify Publish Behavior on the event definition:
Publish Immediately fires even on rollback, and it draws on a different governor
allocation. See `flow/flow-and-platform-events`.

### Pattern C: Apex Queueable + Finalizer

Reach for this when the requirement is to know *whether* the work succeeded and
act on the answer. Flow calls an Invocable Action that enqueues a Queueable; the
Queueable attaches a finalizer that writes the outcome and, on failure, decides
whether to retry.

The ceilings that shape the design: one finalizer per Queueable job; a failed job
can be re-enqueued five times and the count resets on success; the finalizer may
enqueue a single asynchronous job; callouts are allowed. Re-enqueue replays the
**whole** Queueable body, so everything before the failure point runs again.

`templates/apex/` has no canonical `QueueableWithFinalizer` today — the
illustrative shape is in `references/examples.md`, and this is a flagged template
gap rather than an oversight.

## Durability Cheatsheet

- "After commit, one consumer, possibly a callout" → **Run Asynchronously** path.
- "After commit, several independent consumers" → Platform Event, Publish After
  Commit.
- "After commit, and I need to record whether it worked and retry with a bound"
  → Queueable + Finalizer.
- "The user must not be able to save without this" → not a post-commit problem.
  Block the save with a **Custom Error** element.

## Anti-Patterns (see `references/llm-anti-patterns.md`)

- The zero-minute scheduled path standing in for the asynchronous path.
- A callout on the immediate path of an after-save flow.
- Describing a fault path as "the flow's finalizer".
- Assuming a finalizer retries indefinitely.
- `$Flow.InterviewGuid` as an idempotency key.
- Using the fault path as a compensating transaction.
- "Async means no governor limits."

## Related

- `flow/flow-transactional-boundaries` — what commits when.
- `flow/flow-and-platform-events` — publish and subscribe mechanics.
- `flow/flow-interview-debugging` — instrumenting work nobody watches.
- `flow/flow-batch-processing-alternatives` — when the async ceilings also fail.
- `apex/apex-transaction-finalizers` — the Apex side in full.
- `standards/decision-trees/async-selection.md` — the formal engine choice. Cite
  the branch that resolved it rather than re-deriving it.

## Official Sources Used

- Transaction Finalizers — https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_transaction_finalizers.htm
- Connect a Record-Triggered Flow to an External System Using an Asynchronous Path — https://help.salesforce.com/s/articleView?id=release-notes.rn_automate_flow_builder_asynchronous_path.htm&release=234&type=5
- Scheduled Paths — https://help.salesforce.com/s/articleView?id=platform.flow_concepts_trigger_scheduled_path.htm&type=5
- Publish Platform Event Messages Using Apex — https://developer.salesforce.com/docs/atlas.en-us.platform_events.meta/platform_events/platform_events_publish_apex.htm
- Per-Transaction Apex Governor Limits — https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm

The full annotated list is in `references/well-architected.md`.

Files in this skill

  • SKILL.md8 KB
  • references/examples.md13.7 KB
  • references/gotchas.md9.4 KB
  • references/llm-anti-patterns.md7.6 KB
  • references/well-architected.md6.1 KB
  • scripts/check_flow_transaction_finalizer_patterns.py2 KB
  • templates/post-commit-plan.md834 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…