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 Recordselement 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.
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
ISCHANGEDlogic, 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
- Query Inside a Loop: Executing
Get Recordsinside iterations consumes multiple SOQL queries per interview. Fix: Perform a single query before the loop and use in-memoryCollection Filterelements. - DML Inside a Loop: Calling
CreateorUpdateinside a loop rapidly exhausts DML limits. Fix: Populate a record collection variable viaAssignmentelements 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
AssignmentandDecisionsteps.
Scenario-Based Follow-Ups
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.
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:
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.
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.