Your CRM, developed by AI. See it live.
Book a Demo Call
All Posts
· Laine · 11 min read

Salesforce Flow vs Apex: When Flow Stops Being Enough

Salesforce Flow vs Apex isn't a staffing question, it's a shape question. Five signals your automation has outgrown Flow — and what to do about it.

SalesforceFlowApexAutomationAISentinelCRM
Sentinel cover graphic: Salesforce Flow vs Apex, When Flow Stops Being Enough

Salesforce Flow vs Apex gets argued as a staffing question — Flow if you have an admin, Apex if you have a developer. That framing is exactly why so many orgs end up nursing a forty-element flow that everybody is afraid to open. The honest version of this comparison has nothing to do with the shape of your team. It’s about the shape of the work, and the work tells you the answer almost every time, if you’re willing to hear it.

The position here: Flow is the correct default, it is better than its reputation among developers, and it has a real ceiling that arrives earlier than most admins expect. The failure mode isn’t choosing Flow. It’s staying on Flow for eighteen months after the work stopped fitting, because the alternative felt institutionally out of reach.

The comparison everyone makes is the wrong one

The usual framing puts Flow and Apex on a difficulty ladder — declarative on the easy rung, code on the hard one — and then asks which rung you can afford to stand on. Framed that way, the answer is always Flow, because the answer is always “we don’t have a developer.”

That’s a budget decision wearing a technical decision’s clothes. It doesn’t ask whether the automation you’re building is the kind of thing Flow is good at. It asks whether you’re allowed to consider the alternative. And when only one option is really on the table, you don’t get a comparison — you get a rationalization, and it shows up eighteen months later as a flow with nested loops, twelve decision elements, and a comment from an admin who left in March.

The better question is dull and useful: what is this automation actually doing? Record-triggered updates, field derivation, simple approvals, screen-based data entry, orchestration between known objects — Flow’s home turf. Complex conditional math, bulk operations across tens of thousands of records, recursion, callouts with real error handling, anything that has to be correct rather than merely done — that’s Apex’s, and no amount of dragging will change it.

What Flow is genuinely better at

Flow deserves more credit than it gets from people who write code for a living. It is visible. A competent admin can open it, read it, and understand the business rule inside it without a local dev environment or a deploy pipeline. That legibility is a real operational asset — when the person who built the automation leaves, a flow survives the handoff far better than an undocumented trigger does.

It is also where Salesforce is putting its investment. You haven’t been able to create new Workflow Rules since Winter ‘23 or new Process Builder processes since Summer ‘23, and both are on a retirement path — existing ones still run, but Salesforce has not committed to a date when they stop. Flow is the declarative future, not a stopgap.

So: build in Flow first. Genuinely. The argument in this post is not “skip Flow and write Apex.” It’s that Flow has an edge, and you should be able to recognize it when you hit it instead of grinding against it for another two quarters.

Signal 1: You’re looping over records

This is the clearest one. The moment your flow has a loop that performs a Get Records or an Update Records inside the loop, you have written the declarative version of the oldest bug in Salesforce.

Flow and Apex share the same per-transaction governor limits — this is the single most misunderstood thing about the comparison. Salesforce allows 100 SOQL queries and 150 DML statements per transaction, 50,000 records retrieved, and 10 seconds of CPU time, and Flow does not get a discount. Drag-and-drop is not a governor-limit exemption. It is the same engine with a friendlier picture on top.

You can restructure a flow to move the queries outside the loop, and you should. But when the restructuring itself becomes the hard part — when you’re building collection variables and assignment gymnastics to simulate what a bulkified trigger does natively — the tool is telling you something.

Signal 2: The logic no longer fits on a screen

There’s a rough threshold where a flow stops being documentation and starts being a puzzle. Different people put it in different places; mine is somewhere around twenty elements, or the second nested decision.

Past that point, the legibility advantage — the whole reason to prefer Flow — quietly inverts. A 400-line Apex class with clear method names and a test suite is easier to reason about than a sprawling canvas where the business rule is distributed across fourteen boxes and you have to click each one to see its criteria. You kept the declarative tool to stay readable, and you are no longer readable.

There’s a practical tell for this. Ask whoever owns the org to explain, out loud and without opening it, what the flow does in the case where the Opportunity has no Contact Role. If the answer is “let me trace through it,” the flow has stopped documenting the rule and started hiding it. A class with a method named assignWhenNoContactRole answers that question from its name.

Signal 3: You need real error handling

Flow’s fault paths work, and they’ve improved. But there’s a difference between “route to a fault screen and email the admin” and “catch this specific exception, roll back cleanly, retry with backoff, and leave a record of what happened.”

If your automation touches an external system, moves money, or has a partial-failure state that matters — half the records updated, half not — you need the second thing. Apex gives you savepoints, typed exceptions, and control over what a failure leaves behind. Flow gives you a fault path.

The scenario that exposes the gap: you push an order to an ERP, the callout times out, and you don’t know whether the order landed. Handled properly, that’s a retry against an idempotency key and a status field that reflects genuine uncertainty rather than guessing. Handled in a flow, it’s usually a fault path that marks the record “Failed” and sends an email — and then somebody retries by hand and creates a duplicate order. The difference isn’t sophistication. It’s whether the failure case was something you could express at all.

Signal 4: It has to be right, not just done

Some automations are conveniences. If they misfire, somebody notices and fixes a record.

Others are load-bearing: commission calculations, renewal dates, territory assignment, anything finance reconciles against. For those, the thing Apex has that Flow structurally does not is tests. Salesforce requires 75% code coverage to deploy Apex to production, which admins reasonably experience as a tax. It is also the only mechanism in the platform that lets you change a business rule two years later and get told, in thirty seconds, that you broke the edge case nobody remembers.

There is no equivalent for a flow. You test it by running it and looking — which works fine the day you build it, and not at all in the moment that actually matters, which is eleven months later when someone adds a new record type and nobody remembers the flow assumed there were only two. Apex tests are how a decision you made once keeps being enforced after you’ve forgotten you made it. That property is worth the coverage tax on anything finance will reconcile against, and worth skipping on a task-creation convenience.

Signal 5: You’re rebuilding the same logic in four places

Flow doesn’t compose well. When the same territory rule needs to apply on Lead create, on Account update, in a screen flow, and in a nightly batch, you tend to end up with four copies that drift apart — and the drift is invisible until somebody escalates a mis-assigned deal.

Apex has methods. One service class, called from wherever, updated in one place, and a single place to change when sales redraws the map in January. If you’ve caught yourself copy-pasting a decision element between flows, that’s the signal — and it’s worth reading how routing and assignment logic and round-robin lead assignment tend to sprawl, because they are the two places this shows up first in most orgs.

Subflows are the declarative answer here and they’re a real improvement, but they’re a partial one: they share a definition, not a contract. Nothing warns you when a caller starts passing a variable the subflow wasn’t built to handle, and nothing fails when someone changes the shared logic for one use case and quietly breaks the other three.

The tiebreaker that shouldn’t exist

Go back through those five signals and notice what happens in a typical org when one of them fires. Everybody agrees it’s an Apex problem. And then somebody says we don’t have a developer, and the flow gets one more decision element.

That’s the tiebreaker doing all the work. Not “which tool fits,” but “which tool can we actually reach.” What a Salesforce developer costs in 2026 explains why: for a two-day trigger, a contractor has a minimum engagement, a hire has a six-month ramp, and the admin has a flow open right now. The economics push you toward the wrong tool, every time, for entirely rational reasons.

Which means the interesting question isn’t Flow vs Apex at all. It’s what the comparison looks like when the access problem goes away.

What changes when Apex is reachable

Sentinel exists to remove that tiebreaker. It gives your AI — Claude Cowork, or anything that speaks MCP — the ability to develop directly against your Salesforce org: read the schema, write the Apex and the test class, deploy it sandbox-first with tests required, and leave a full record of what changed. The idea behind making your AI your CRM developer is simply that the thing standing between you and the right tool was access, not judgment.

The safety story matters here, and it isn’t a guardrail story. Nothing stops you from building something wrong — that’s true of any developer, human or otherwise. What you get instead is recoverability and visibility: snapshots before deploys, a sandbox-first pipeline with tests that must pass, and an audit log of who changed what and when. The logs-and-snapshots mechanics are covered in full elsewhere; the short version is that a bad deploy becomes an afternoon, not a quarter.

Nothing about this makes Flow wrong. It makes Flow chosen. You build the record-triggered update in Flow because Flow is genuinely the better tool for a record-triggered update — not because Apex was never going to happen. And when the nightly reconciliation job needs to be a batch class with real tests, it becomes one, this week, instead of becoming flow number thirty-one. The same shift is what makes Salesforce automation without hiring an Apex developer a practical statement rather than a marketing one.

How to actually choose

Ask three questions in order.

Is it bulk? If the automation will ever process more than a couple hundred records in one transaction, start in Apex. You will get there anyway, and the flow you’d write first is the one you’d throw away.

Does a wrong answer cost money? If yes, you want tests, which means Apex. Convenience automations don’t need them. Commission logic does.

Can a new admin read it in five minutes? If the flow can’t clear that bar, the legibility argument for Flow has already expired. Write the class.

Everything else — and it’s most things — belongs in Flow. That’s not a concession. That’s a good default doing its job, which it can only do once you stop asking it to cover for the option you couldn’t reach.

The orgs that get this right over the next few years won’t be the ones that picked a side in Flow vs Apex. They’ll be the ones who stopped letting their staffing chart decide their architecture.

If you’ve got a flow you’re afraid to open, that’s the place to start. Pricing is flat per Sentinel and is covered on a short demo call. Book a Demo Call and we’ll look at the worst one together.

Ready to see what AI can do for your business?

Start a Conversation