The “Flows vs Apex triggers” debate is one of the most common architectural questions on the Salesforce platform. The answer in 2026 is nuanced — it is not either/or but a deliberate choice of the right tool for each specific automation scenario.
What changed in Summer ‘26
Two Summer ‘26 updates directly affect this decision.
Flow Orchestration is now unlimited. As of Spring ‘26, Flow Orchestration runs are included in Enterprise, Performance, Unlimited and Developer editions with no usage-based caps. This removes a key economic barrier that previously pushed teams toward Apex for complex multi-step processes. If Flow Orchestration covers your use case, the previous argument about licencing costs no longer applies.
Agentforce can modify Screen Flows using natural language. Builders can describe changes to Screen Flows in plain language and Agentforce implements them. This increases the velocity of Flow development for non-developer team members.
Schedule-Triggered Flow batch size is now configurable. You can now set a custom batch size for Schedule-Triggered Flows, reducing governor limit risk for flows that process large record sets by processing smaller chunks at a time.
The decision framework
Use a Record-Triggered Flow when the logic is expressible declaratively without excessive complexity, the team maintaining it includes admins without Apex expertise, the automation involves simple field updates on the triggering record (use before-save for maximum efficiency), creating related records, or sending notifications.
Use an Apex trigger when the logic requires complex SOQL with multiple
relationships and Map-based lookups for bulkification, custom error handling
with partial success patterns using Database.insert(records, false),
platform event publishing or callout coordination in after-triggers, or
logic that is genuinely too complex to express clearly in Flow without
creating unmaintainable spaghetti-canvas flows.
The one trigger framework pattern
Regardless of how many automation types you use on an object, maintain a single Apex trigger per object that dispatches to a handler class.
trigger AccountTrigger on Account (
before insert, before update, before delete,
after insert, after update, after delete, after undelete
) {
AccountTriggerHandler.dispatch(Trigger.operationType);
}
The handler contains all logic, is unit-testable independently of the
trigger, and includes a static flag to prevent recursion when Flows or
other automation causes the same trigger to fire again within the same
transaction.
## Flow anti-patterns that cause governor limit violations
The same SOQL-in-a-loop problem that breaks Apex triggers applies to
Flow. A Get Records element inside a Loop element fires a SOQL query
for each iteration — not once for the entire batch of records. With
200 records in the trigger context and a Get Records inside a Loop,
you consume 200 SOQL queries instantly.
The fix in Flow mirrors the fix in Apex: move the Get Records element
outside the Loop, retrieve all related records at once, and then use
Assignment elements inside the loop to match records from the collection.
## When to refactor Flows to Apex
Monitor Flow Error Rate in Setup (a Summer '26 addition) to identify
flows that are failing in production. If a Flow is failing due to
governor limits with real-world data volumes, that is a signal to
refactor the logic into Apex where you have precise control over
bulkification. If a Flow has become so complex that understanding it
requires tracing a canvas with dozens of elements and nested decisions,
that is a maintainability signal — complex conditional logic is often
clearer as readable Apex code than as a visual flow diagram. Test your knowledge — Automation
10 questions · Basic to Advanced