Skip to main content

Salesforce Flow Bulkification & Recursion Guards: Complete Best Practices Guide

💬 In plain words: A flow that runs smoothly on a single record can instantly fail during a 200-record batch update. True bulkification means keeping all queries and DML elements outside of loops, while recursion guards stop flows from triggering themselves repeatedly. Always validate flows with bulk datasets rather than single-record tests.
📌 Example: A flow functions without issues during single-record manual testing. However, a bulk upload of 5,000 leads causes an unhandled exception because a Get Records element was placed inside a loop, triggering 5,000 separate queries. Moving that query prior to the loop and leveraging collection variables keeps the flow entirely bulk-safe.

🎬 Real-Life Scenario: The Flow That Failed at Record 201

A record-triggered flow flags delayed deliveries and generates an alert task for each record. A partner initiates a bulk upload of 5,000 delivery records.

The Anti-Pattern: The flow executes a loop containing both a Get Records and a Create Records element inside the iteration path.

Why It Breaks: Salesforce processes incoming transactions in 200-record batches. Running database elements inside a loop creates 400 data operations in a single execution transaction ($200 \times 2$), hitting governor limits mid-transaction and leaving partial data states.

The Solution:

  • Query necessary data once before entering the loop using Get Records.
  • Use the loop body only to assign record values into a collection variable.
  • Execute a single Create Records element on the entire collection after the loop finishes.
  • Validate automation with a standard 200-row batch import before production deployment.

Result: Database transactions drop from 400 down to 2 operations per batch, allowing large-scale uploads to complete reliably.

🧠 Core Rule: Database operations inside loops break at scale. Always stage records in memory and commit transactions once after the loop finishes.

Platform Bulkification Mechanics

Salesforce natively executes record-triggered flows in batches, combining interviews at wait conditions and transaction boundaries. However, poor flow design can negate these platform optimizations.

  • Interview Batching: The runtime engine combines identical queries and data changes across up to 200 records at platform pause points.
  • Loop Invalidation: Placing queries or DML operations inside loops bypasses platform bulkification, resulting in governor limit violations equivalent to SOQL/DML queries inside an Apex for-loop.
  • Recursion Control: Recursive loops can be prevented using tightly scoped entry criteria and the "Only when a record is updated to meet the condition requirements" setting.
  • Evaluation Optimization: Choosing transition-only evaluation applies ISCHANGED logic, shielding your org from unnecessary downstream executions and endless update loops.

🧭 360 Card — Flow Bulkification & Recursion Rules

  • Golden Rule: Never place query (Get Records) or DML (Create/Update/Delete) elements inside a loop. Collect in memory, commit once outside.
  • Architectural Advantage: Efficiently designed flows consume virtually the same governor limit capacity for 200 records as they do for 1 record.
  • Loop Boundary Impact: Automatic batching stops at loop iterations. Every element inside a loop executes once per iteration per record interview.
  • Limits Consideration: High-volume executions typically hit total flow element execution limits before running out of SOQL queries.
  • Recursion Defense: Using "Updated to meet condition requirements" ensures triggers fire only on state changes, serving as a declarative recursion lock.
  • Testing Standard: Never sign off on flows using single-record tests. Always test using a 200+ record bulk load.

Core Q&A: Flow Anti-Patterns & Fixes

Q: What are the common flow anti-patterns that hit governor limits during 200-record transactions, and how are they fixed?
🎯 Say this first: The most common issues are queries and DML operations placed inside loops, along with unmanaged recursion. Resolve them with collections, pre-loop queries, precise entry criteria, and transition-based evaluation.
  • Query Inside a Loop: Executing Get Records inside iterations consumes multiple SOQL queries per interview. Fix: Perform a single query before the loop and use in-memory Collection Filter elements.
  • DML Inside a Loop: Calling Create or Update inside a loop rapidly exhausts DML limits. Fix: Populate a record collection variable via Assignment elements and run one DML operation outside the loop.
  • Self-Updating After-Save Flows: Using an after-save flow to update the triggering record creates duplicate transactions and potential recursion. Fix: Use before-save (Fast Field Updates) flows for zero-cost updates on the same record.
  • Cross-Object Update Cascades: Flows updating related records that re-trigger other flows in a circular loop. Fix: Consolidate logic, establish clear trigger ordering, and add recursion bypass flags.
  • Design Guardrail: Keep loop bodies restricted to non-DML elements such as Assignment and Decision steps.

Scenario-Based Follow-Ups

Q1: How does "Only when a record is updated to meet the condition requirements" differ from standard entry conditions, and when does it fail?

Standard entry criteria evaluate to true on every edit where conditions are met, triggering automation on every save. The "Updated to meet" option only fires when a record transitions from not meeting the criteria to meeting them (comparable to ISCHANGED and ISNEW behavior).

This setting will not suffice in two scenarios:

  • When subsequent automations in the same save sequence modify the field back and forth.
  • When business logic must run on every edit while a record remains in a continuous state (e.g., recalculating totals whenever any edit occurs on an "Active" Account).

In such scenarios, implement explicit state tracking using a custom processed checkbox or check previous values using $Record__Prior.

Q2: A flow passes single-record testing but fails due to iteration limits during an enterprise integration upserting 5,000 records. How do you resolve it?

Bulk integrations process data in 200-record chunks. If each parent record contains 30 children and the loop body holds 40 elements, a single batch produces:

$$200 \times 30 \times 40 = 240{,}000 \text{ executed elements}$$

This will breach the per-interview element execution limit. To resolve this:

  • Review Flow Error Emails and debug logs to analyze element execution counts.
  • Eliminate loop-based transformations by utilizing collection actions and formula variables.
  • For complex transformations across large volumes of related records, migrate processing to an Apex trigger or Batch class where chunking can be explicitly controlled.
  • Adjusting batch sizes on the integration side can provide temporary relief, but refining the architecture is the proper long-term solution.
Q3: Why doesn't Salesforce automatically bulkify elements nested inside loops?

The platform automatically handles bulkification by grouping similar DML and query operations across simultaneous interviews at standard execution steps. However, the runtime engine cannot infer how data flows through iterative loops across varying record counts. Ensuring loop structures stage items in collections before triggering database events remains the developer's architectural responsibility.