Phil Stalpes – April 15, 2026

In Short, Salesforce Flow is probably the right tool for roughly 70% of your automation. But when flows start hitting CPU time limits, require nested loops for record matching, fail in production after passing sandbox tests, outgrow basic error handling, or become too complex for anyone to modify safely, those are signals that specific processes need to move to Apex. The transition isn't all-or-nothing; it's about putting the right tool on the right job.
Salesforce Flow is one of the most powerful tools on the platform. For the majority of your automation needs, it's the right answer: fast to build, and visible to admins. We use it constantly, and we recommend it constantly.
But Flow has limits. And those limits don't announce themselves.
What actually happens is quieter: a process that ran fine for a year starts timing out during data loads. An admin who used to maintain the flow stops making changes because the canvas is too tangled to follow. A sandbox test passes perfectly, then production explodes on a Monday morning when real data volumes hit.
If your team is spending more hours working around Salesforce Flow limitations than it would cost to write Apex, you've already crossed the line. You just haven't named it yet.
Here are five signals we see repeatedly in client orgs. If two or more sound familiar, it's time to talk about your automation architecture.
Every synchronous Salesforce transaction gets 10 seconds of CPU time. Flow and Apex share that limit, but Flow burns through it faster because the platform can't optimize declarative logic as it does compiled code.
This rarely shows up as a sudden failure. It's a slow creep. The flow you built ran in 3 seconds. Six months and a few added elements later, it's at 7 seconds. Your data keeps growing, and you're one bulk update away from the wall.
Why this matters to your business: When a flow times out, it doesn't just fail quietly. Transactions roll back. Records don't save. Users see errors they can't interpret, and your team spends hours in debug logs tracing a problem that boils down to "this process has outgrown its tooling." The cost isn't the fix; it's the disruption and the lost trust from business users who stop relying on the system.
The move: Apex can handle the same logic asynchronously through Batch or Queueable processing, with dramatically better performance. Batch Apex gets 60 seconds per chunk instead of 10 for the whole transaction. For a process that runs nightly against tens of thousands of records, that's the difference between reliable and fragile.
Flow doesn't have maps or dictionaries. That's a technical statement with a very practical consequence: if you need to match child records to parent records, the only approach in Flow is to loop through one collection for every item in another.
Consider a common scenario. You need to process 200 accounts, each with 50 related contacts. In Flow, you're iterating through all contacts for every single account. That's 10,000 loop iterations to accomplish something that Apex handles in a single pass by grouping contacts by their parent ID.
Why this matters to your business: These workarounds don't just run slowly. They're invisible complexity. The admin who built the nested loops moves on, and the next person inherits a flow that's technically correct but architecturally fragile. One change to a requirement (say, adding opportunities to the matching logic) turns a slow process into an impossible one.
The move: Apex collection methods (Maps, Sets, List operations) solve this class of problem cleanly. The code is shorter, faster, and more maintainable than the Flow equivalent. If your team is building nested loops or creating multiple collection variables just to relate records, that's the platform telling you to switch tools.
Not sure whether your specific process warrants the move? Our Technical Debt Calculator can help you quantify the cost of staying on Flow versus refactoring to Apex.
This is the most common signal we see, and the most expensive. Everything tested fine with 50 records in the sandbox. Production has 50,000 records and immediately hits governor limits.
The root cause is structural. Unlike Apex, Flow doesn't require test coverage to deploy to production. No mechanism forces you to validate a flow against realistic data volumes before it goes live. Flow Tests exist, but they're optional. So teams ship automation that works perfectly in test conditions but fails in real ones.
Why this matters to your business: A production failure during business hours costs more than the engineering time to fix it. Depending on the process, you're looking at missed SLAs, stalled deals, broken integrations, and a loss of confidence from the business stakeholders you need on your side for the next initiative. The worst part: this is a category of failure that Apex's mandatory testing discipline was specifically designed to prevent.
The move: Apex requires 75% test coverage before deployment. Full stop. You can (and should) write tests that process 200 records and verify your code stays within governor limits before it touches production. That's not overhead; it's insurance. The 30 minutes you spend writing a bulk test saves the 3-hour fire drill when production breaks.
Flow has fault paths. They work for simple cases. But they're not try-catch blocks, and the distinction matters as your processes get more complex.
In Flow, you can't implement retry logic for transient failures. You can't catch specific exception types differently (a duplicate rule violation requires a different response than a field validation error, but Flow's fault paths don't differentiate between them). You can't gracefully handle partial failures in a batch of records. And when something does break, Flow's error reporting gives you less diagnostic detail than Apex stack traces.
Why this matters to your business: Vague errors create a support burden. When users see "An unhandled fault has occurred," and your team has to manually trace through the flow canvas to find the failure point, you're paying developer rates for detective work. Multiply that by every production incident, and the cost of inadequate error handling adds up faster than most teams realize.
The move: Apex try-catch blocks let you catch specific exception types, log structured error information, implement retry logic for external callouts, and handle partial successes in bulk operations. If your process has more than two distinct failure modes (and most real-world processes do), Apex error handling pays for itself in reduced incident response time.
This is the signal that encompasses all the others, and it's the one most likely to appear in a conversation rather than in a debug log.
Open your most complex flow in Flow Builder. If you can't explain what it does in 30 seconds by looking at it, you've outgrown the visual canvas. We see this constantly: a flow that started as a clean 15-element automation grew to 100+ elements over two years of requirement changes. The visual interface that was Flow's greatest strength at 15 elements becomes its greatest liability at 100. Admins who were supposed to own it can't follow the logic. New requirements mean threading more branches through an already tangled web. And because flows lack the version control, diff tooling, and code review processes that Apex benefits from, changes go in without rigor.
Why this matters to your business: The real cost isn't technical. It's organizational velocity. When your team avoids modifying a critical process for fear of breaking it, you've created a bottleneck that slows down every initiative that touches that area of your org. Requirements pile up. Workarounds multiply. And the eventual refactor costs three times what it would have cost to do it right the first time.
The move: Refactor into modular Apex with a proper trigger framework. Each business process gets its own handler class with clear inputs, outputs, and test coverage. The upfront investment is real, but the ongoing cost drops significantly because code is searchable, testable, version-controlled, and reviewable. More importantly, your team stops being afraid to make changes.
| Signal | What You'll Notice | What to Do |
|---|---|---|
| CPU time creep | Flows running 5+ seconds; timeouts during data loads | Move to async Apex (Batch or Queueable) |
| Nested loop workarounds | Loops inside loops to match related records | Refactor with Apex Maps and collection methods |
| Production-only failures | Sandbox tests pass; production hits governor limits | Apex with mandatory bulk testing before deploy |
| Patchwork error handling | Vague errors; fault paths can't differentiate failure types | Apex try-catch with specific exception handling |
| Unmaintainable canvas | 50+ elements; team afraid to modify | Modular Apex with trigger framework |
Moving to Apex doesn't mean rewriting everything. The organizations we work with that get the best results use both tools strategically.
We call it the 70/20/10 split. Flow handles roughly 70% of automation: standard record triggers, notifications, guided screen experiences, and scheduled maintenance. Apex handles roughly 20%: bulk data processing, complex calculations, sophisticated integrations, and performance-critical operations. And Agentforce handles roughly 10%: conversational interfaces where natural language understanding creates genuine value.
The critical thing to understand about Agentforce is that it orchestrates Flow and Apex. It doesn't replace them. The agent decides which action to call, but the actions themselves still need to be built and tested in Flow or Apex. Getting your automation architecture right at these two layers is a prerequisite for everything Salesforce is building next.
If two or more of these signals describe your org, the question isn't whether to start using Apex. It's which flows first. Start with the ones causing the most pain: the processes that break in production, the ones nobody wants to modify, and the ones running closest to governor limits.
We built a decision engine that walks you through exactly which tool belongs where for your specific situation. Our white paper, Flow vs. Apex vs. Agentforce: The Decision Tree Nobody's Drawing for You, lays out the complete architectural framework behind the 70/20/10 split. And our Technical Debt Calculator can help you quantify the cost of the automation decisions you've already made.
The developer hours you spend building Apex properly will cost less than the admin hours you're already spending fighting Flow's constraints. That math works out every time.
How do I know if my Salesforce Flow is too complex? If your flow has more than 50 elements, takes more than 5 seconds of CPU time in production, or your team hesitates to modify it, it has likely outgrown Flow's declarative model. Open it in Flow Builder: if you can't explain the logic in 30 seconds, that's your answer.
Can I use both Flow and Apex in the same Salesforce process? Yes, and you should. The most effective Salesforce orgs use Flow for standard automation (roughly 70% of use cases) and Apex for complex logic, bulk processing, and sophisticated integrations (roughly 20%). Agentforce handles the remaining 10% for conversational AI interfaces. The three tools complement each other.
What does the 70/20/10 split mean for Salesforce automation? The 70/20/10 split is Digital Mass's architectural framework for Salesforce automation: 70% Flow (record triggers, notifications, screen flows, scheduled tasks), 20% Apex (bulk data processing, complex calculations, advanced integrations), and 10% Agentforce (conversational interfaces with natural language). The key insight is that Agentforce orchestrates Flow and Apex actions; it doesn't replace the need to build them.
Is it expensive to refactor from Salesforce Flow to Apex? There's an upfront investment in developer time, but it typically pays for itself quickly. The ongoing cost of maintaining overbuilt flows (production failures, debugging time, admin hours fighting constraints, organizational bottlenecks from untouchable processes) almost always exceeds the cost of a well-architected Apex refactor. Start with the highest-pain flows, not a full rewrite.