← Back to Architecture
ARCH-022 Architecture 20 min read For: Solution Architects

Record-Triggered Flows

VS

Vishal Sharma

Salesforce Architecture Specialist · Updated May 2026

What you will learn in this tutorial
  • Why Salesforce positioned Record-Triggered Flows as the replacement for Apex triggers — and what that means architecturally
  • The critical difference between Before-Save and After-Save flows and how to choose correctly
  • Where Record-Triggered Flows fit in the order of execution and their interaction with Apex triggers
  • When Flow complexity becomes a maintainability and governance problem
  • How to build a governance model that prevents orgs from becoming unmanageable Flow environments

Why Salesforce Called Flows "The New Apex"

In 2021, Salesforce officially declared Record-Triggered Flows as the preferred automation mechanism and positioned Apex triggers as the fallback for use cases flows couldn't handle. This wasn't just product positioning — it reflected genuine architectural parity. Record-Triggered Flows can now query records, perform DML, call external services (via Apex actions), publish platform events, and execute conditional logic with the same capability that an Apex trigger provides.

The business case for the shift is clear: flows are maintained by admins, not just developers. A business analyst with Flow Builder knowledge can modify automation logic without a developer code review cycle. For organisations where development capacity is a bottleneck, declarative automation that can be maintained by a broader skill base is a genuine velocity improvement — provided the governance is in place.

💡
The skill set shift has architecture implications

When flows replace Apex triggers, the maintainer of that logic changes. A developer reviewing a Flow in Flow Builder is reviewing XML-represented logic in a visual environment — not the same as code review in an IDE with linting, static analysis, and version-controlled diffs. The governance model for declarative automation must account for this: lower barrier to change means higher risk of unintended interaction between flows.

Before-Save vs After-Save: The Most Important Decision

Record-Triggered Flows come in two varieties: Before-Save (runs before the record is committed to the database) and After-Save (runs after the record is committed). This is the most architecturally significant decision in Flow design, and it's frequently made incorrectly.

Before-Save Flows

Before-Save flows run before the record write. They can modify the record being saved using the $Record variable — and those modifications are included in the same database write, without using a DML statement. This makes Before-Save flows extremely efficient for field update logic: no additional DML operation, no separate record save, no Governor Limit consumption from a second DML statement.

Use Before-Save for: updating fields on the record being saved, field derivation logic (calculate a field from other fields on the same record), cross-field validation that should fire before save, and stamping values that must be set atomically with the record creation.

After-Save Flows

After-Save flows run after the record is committed. They have access to the committed record values and can perform operations that require the record to exist in the database: DML on other records, queries against the saved record, callout actions, and platform event publishing. They consume DML Governor Limits for any record changes they make.

Use After-Save for: creating or updating related records, sending notifications, publishing events, callouts to external systems, and logic that requires querying the database against the committed record.

// Before-Save Flow: field derivation (no Apex code needed)
// Equivalent to this Apex trigger — but zero DML consumed:

// Apex version (requires DML):
trigger AccountTrigger on Account (before insert, before update) {
    for (Account acc : Trigger.new) {
        // Derive SLA tier from Annual Revenue
        if (acc.AnnualRevenue >= 1000000) {
            acc.SLA_Tier__c = 'Platinum';
        } else if (acc.AnnualRevenue >= 100000) {
            acc.SLA_Tier__c = 'Gold';
        } else {
            acc.SLA_Tier__c = 'Standard';
        }
    }
}

// Before-Save Flow equivalent: Decision element with field update
// No DML statement required — modifies $Record directly
// Same Governor Limit profile as the before-trigger equivalent
🔑
Before-Save is almost always the right choice for field updates

If your Flow logic only updates fields on the record being saved, use Before-Save. The performance difference is significant: Before-Save consumes no DML statements; After-Save consumes one per record updated. In a 200-record bulk operation, After-Save consuming 200 DML statements on the triggering object approaches Governor Limits fast. Before-Save consumes zero. Default to Before-Save for field logic and only move to After-Save when you genuinely need post-commit capabilities.

Order of Execution: Where Flows Fit

Record-Triggered Flows run within Salesforce's order of execution — understanding where they fit relative to validation rules, Apex triggers, and workflow rules is essential for debugging unexpected behaviour.

The relevant order: System Validation → Before Triggers (Apex) → Before-Save Record-Triggered Flows → Custom Validation Rules → Record Saved to Database → After Triggers (Apex) → After-Save Record-Triggered Flows → Workflow Rules → Processes → Escalation Rules.

Key implications: Before-Save Flows run after Before Apex triggers. If your Apex trigger sets a field and your Before-Save Flow reads that field, the Flow sees the trigger's value. Conversely, if both the trigger and the Flow try to set the same field, the Flow runs after the trigger and overwrites it. In orgs with both Apex triggers and Before-Save Flows on the same object, field value priority must be explicitly documented.

⚠️
Apex Trigger + Flow Interaction Is a Debugging Nightmare

When both an Apex trigger and a Record-Triggered Flow modify the same fields on the same object, the order of execution determines which value wins. This is architecturally clean when documented, but in orgs where flows are added to objects that already have triggers — without reviewing the trigger logic — unexpected field value conflicts cause bugs that are difficult to diagnose because neither the trigger code nor the flow individually looks wrong. Document the complete automation inventory per object as a governance artefact.

Performance Architecture of Record-Triggered Flows

Record-Triggered Flows are bulkified by default — Salesforce processes records in batches of 200 and the Flow runtime handles all records in the batch in a single Flow execution. This is architecturally equivalent to a bulkified Apex trigger. However, several Flow element types have performance implications that differ from Apex.

Flow's Get Records element executes a SOQL query. Each Get Records element in a Flow that fires in a transaction consumes from the transaction's SOQL query limit (100 per transaction). A Flow with three Get Records elements, firing on 200 records in a batch, potentially consumes 3 SOQL queries (not 600 — Flow is bulkified). But multiple Flows on the same object can compound this.

The Loop element in After-Save Flows that performs DML inside the loop is the most common performance anti-pattern. DML inside a loop is the equivalent of the Apex "DML in a loop" anti-pattern — it fires one DML statement per iteration, consuming DML limits rapidly on large batches.

Complexity Ceiling: When Flows Become Unmaintainable

Flows have a visual representation limit beyond which they become difficult to understand. A Flow with 40+ elements spread across multiple decision branches, subflows, and fault paths is technically valid but operationally unmaintainable — a team member who didn't build it cannot debug it efficiently. This is the hidden cost of declarative automation: the visual metaphor that makes simple logic accessible makes complex logic harder to navigate than code.

The complexity ceiling manifests most severely when multiple admins have modified the same flow over time without documentation. Unlike code, Flows don't have meaningful inline comments, and the version history in Setup is coarse (version numbers without commit messages). A complex, multi-developer flow is harder to maintain than equivalent Apex code with proper comments and test coverage.

Migration: From Process Builder and Workflow Rules

Salesforce has deprecated Workflow Rules (retired in 2023) and Process Builder (scheduled for retirement in 2025). The migration path for both is Record-Triggered Flows. Salesforce provides a migration tool that converts basic Process Builder processes to Flows automatically, but complex processes with loop logic, fault handling, or scheduled actions require manual rebuilding.

The migration is not just a technical task — it's an opportunity to review and rationalise automation logic that has accumulated over years. Many Process Builder processes were built as workarounds for things that can now be done natively in Flow Builder or even in standard Salesforce configuration. Before migrating each process, evaluate whether the automation is still needed and whether the current logic is correct.

Governance for Flow-Heavy Orgs

The most urgent governance requirement for Flow-heavy orgs is an automation inventory: a documented map of every Record-Triggered Flow per object, what it does, who owns it, and when it was last reviewed. Without this, adding a new Flow to an object with five existing Flows is architectural roulette — you're working without a complete picture of what runs on that object.

Governance policies for Record-Triggered Flows: require naming conventions that encode the object, trigger type, and purpose (e.g. Account_BeforeSave_SLATierDerivation); require a description field in every Flow that explains the business purpose; require a developer code review for any After-Save Flow that performs DML or callouts; and limit the number of active flows per object with architectural sign-off required to exceed the limit.

One Flow per Object, One Trigger Handler per Object

The same best practice that governs Apex triggers — one trigger per object, routing to a handler class — applies to Record-Triggered Flows. One Before-Save Flow per object (consolidating all before-save logic) and one After-Save Flow (consolidating all after-save logic) is architecturally cleaner than multiple individual Flows. It's not always achievable in practice, but it's the target architecture: fewer, more comprehensive Flows with clear ownership are easier to maintain than many small Flows with unclear interaction.

Key Takeaways

  • Record-Triggered Flows are Salesforce's preferred automation mechanism — architecturally equivalent to Apex triggers for most use cases, maintainable by a broader skill set
  • Before-Save Flows update the triggering record without consuming DML statements — always use Before-Save for field update logic; use After-Save only when post-commit capabilities are genuinely required
  • Before-Save Flows run after Before Apex triggers in the order of execution — when both exist on the same object, document which sets each field to avoid silent overwrites
  • Flow's visual representation becomes a liability at high complexity — beyond ~40 elements, a well-structured Apex trigger with comments is often more maintainable
  • DML inside a Flow Loop element is the declarative equivalent of DML inside an Apex loop — an anti-pattern that consumes Governor Limits rapidly on bulk operations
  • Process Builder and Workflow Rules are deprecated — migration to Record-Triggered Flows should be a planned programme, not a reactive response to platform retirement notices
  • Governance for Flow-heavy orgs requires an automation inventory per object, naming conventions, and a policy limiting the number of active Flows per object without architectural review

Checkpoint: Test Your Understanding

1. A Flow needs to calculate a field value from other fields on the same record being saved, with no related record queries or DML on other objects. Which Flow type should be used?

A. Before-Save Record-Triggered Flow — it updates the triggering record's field using the $Record variable without consuming any DML statements, making it the most efficient choice
B. After-Save Record-Triggered Flow — it should always be used for field calculations to ensure the final record state is stable
C. Scheduled Flow — to avoid triggering on every save and impacting performance
D. Apex Trigger — field derivation is too simple for Flow and should always be in code

2. In the order of execution, when does an After-Save Record-Triggered Flow run relative to an Apex After trigger on the same object?

A. Before the Apex After trigger — Flows always have priority over Apex
B. Simultaneously with the Apex After trigger — they run in parallel
C. After the Apex After trigger — the order is: Apex Before triggers → Before-Save Flows → record saved → Apex After triggers → After-Save Flows
D. The order is non-deterministic and can vary by Salesforce release

3. What is the governance risk of having multiple admins modify the same complex Record-Triggered Flow over time without documentation?

A. Salesforce limits Flows to 3 editors — further edits require admin reactivation
B. Flow version history is automatically deleted after 12 months, removing audit capability
C. Complex Flows become unmaintainable — unlike code with inline comments and commit messages, visual Flow logic has no meaningful documentation mechanism, making it impossible to debug or safely modify without understanding the original business intent
D. Multiple editors cause Salesforce to flag the Flow for manual security review before activation

Discussion & Feedback