Flow / Admins / Developers

Apex vs. Flow – Code vs. Clicks

By Tim Combridge

I’m going to start by saying that this will be a friendly fight – we all love both Flow and Apex, and they certainly have their respective place and will for the foreseeable future. That being said, it’s about time they had a showdown! 

Today, we’ll be discussing two different tools – Flow and Apex – and identifying their strengths and weaknesses. We’ll be assessing each tool against a key requirement and seeing which tool is best for each job. So without further adieu, it’s time to introduce today’s contenders…

In the Blue Corner – Apex & LWC!

Apex was announced at Dreamforce 2006 and was Salesforce’s first major step in Salesforce Platform customization. This was a major release that allowed customers and third parties to expand upon the core Salesforce functionality using the same language that Salesforce used to build its platform. Apex was released alongside Visualforce, which follows a similar syntax to HTML and allowed developers to build their own custom interfaces within Salesforce.

Apex and Visualforce have since been accompanied by Aura Components, which were also replaced by Lightning Web Components (LWC). The two key technologies that are still used today are Apex and LWC, which both stand tall in the blue corner! 

In the Red Corner – Flow!

The first iteration of Flow was released in Spring ‘12 in the form of the Cloud Flow Designer tool which lets you create Visual Workflows. Since then, it has undergone significant changes. Visual Workflows are now just “flows”, and the Cloud Flow Designer tool is now simply Flow Builder, and has been granted some massive upgrades over the years. It has recently even replaced Workflow Rules and Process Builder as the go-to Process Automation tool.

It is important to know that there are three key types of Flows:

  • Autolaunched: A set of actions to be called from another Flow or other automation tool.
  • Triggered Flows: A set of actions that are triggered by a record change, platform event message, or on a regular schedule.
  • Screen Flows: A series of screens and actions that are presented to users to interact with.

Pros, Cons, and Special Mentions of Each Tool

There’s one clear difference between the two sets of tools: Flow is a click-based tool (also known as declarative), and Apex and LWC are code-based tools (also known as programmatic). We’re all just as familiar with our mouse as we are with our keyboard, but that’s not the point. Many assume that just because a tool is declarative it is somehow easier and simple enough for anyone to pick up quickly; this is simply not the case.

Just like its programmatic brothers, Flow should be used in such a way that it follows best practices in terms of architecture and design. There are multiple ways to achieve a goal using Flow and not all of them are the best way – it’s important to educate yourself properly on the Flow tool before you jump in and begin building. 

However, Flow is indeed easier to wrap your head around from a standing start than its programmatic counterparts. A lot of the challenge with Apex and LWC has to do with syntax – you must ensure that you adhere to it strictly to ensure that what you’re building does what you expect it to do. 

Flow also has a syntax, but the beautiful thing about a declarative tool is that it is a lot more structured, and tends to offer a lot more guidance than code-based tools. It’s not that Apex and LWC are necessarily more complex, but that Flow provides a lot more structure out of the gate. 

On the other hand, Apex and LWC being so flexible allows for a lot more functionality and powerful capability than Flow (yeah, I said it). Beginners will tend to flock towards Flow if they’ve never touched either tool as Flow comes with several pre-built components and functions, and can also be expanded by Apex and LWC if need be. 

The Challenges… 3, 2, 1, FIGHT!

Challenge One: Two-Way Integration with External Systems

You’re working with a B2B business that sells machinery to manufacturing companies. They are looking to connect its Salesforce environment with an external system that summarizes information about their customer accounts. This external system will change the summary of individual accounts from time to time when major news drops about them. This news is then gathered from yet another external system. 

The business wants Salesforce to send through information about the size of the deals that they’re working on with the customer, as well as the conversion rate of those deals. They also want the system to be able to push new summaries into Salesforce when they’re generated.

Round One: Best-Fit Solution

The first thing to note is that there are solutions beyond just Flow and Apex. Sure, with Flow you can use Platform Events as a method of receiving and sending messages to external platforms, and you could build a custom endpoint using Apex. Both of these solutions would work, but something that you need to consider is that you’re not just working with Salesforce and the external calculation engine, but also with the other external news source.

You may need to have a further discussion with the business and figure out if something like MuleSoft is required – some form of middleware platform that can connect with Salesforce, both external systems, as well as any other systems they may be using beyond this functionality. 

That being said, if you had to pick between either Flow or Apex for this solution, I would personally lean towards using Flow for this functionality. The requirement states that the summaries will change “from time to time”, and implies that it is not a regular occurrence. 

Assuming that the volume of pushes from Salesforce and calls from the external systems will not be huge, Flow should be able to handle it. More on how volume would impact this decision in one of the later challenges…

Challenge Two: Building a Custom-Branded Form

You are working with a water company that uses Salesforce to manage their customers, their usage, billing, and generate invoices. To ensure customers can receive an accurate bill, they want to provide customers with the ability to submit images of their water meters and readings. Additionally, they want to be able to onboard quickly and easily by sending them a branded, multi-page KYC (Know Your Customer) form. 

The form needs to follow very specific branding guidelines that will have several different pages for capturing data and will require connection to other data sources to validate against existing data.

Round Two: Best-Fit Solution

There are a few things to consider before trying to select a best-fit solution here. Firstly, the requirements state that the company is specifically a water company. There’s a chance that they may be using a Salesforce Industries solution here and may have access to a specialized tool – OmniStudio (more on that in a second).

Secondly, the requirements state that one of the forms must be a multi-page KYC form, which can often be a complex requirement. On the one hand, a Screen Flow may do the job here, perhaps in conjunction with some custom LWCs that are embedded within the Flow to capture information according to business requirements. However, the one point that stands out among the rest is that it must follow very specific branding guidelines that the business will provide. 

Technically speaking, you could create a Flow and embed it on an Experience Site or external website and apply custom CSS over the top of it. This could work, however going back to our first point, a specialist tool like OmniStudio is going to have a large impact on the best-fit tool decision. 

The customer is a water company that could have access to create OmniScripts through Salesforce Industries’ OmniStudio tool. This tool has been specifically designed to create complex, multi-page, custom-branded forms for this exact purpose. Rather than using Screen Flow, my recommendation would be to investigate using OmniScript for the core of the form and possibly layering some custom LWC over the top (similar to how you may do so in Flow). 

If the customer was not using Salesforce Industries and therefore didn’t have access to OmniStudio, my recommendation would be to use Screen Flow as the base and consider developing some custom LWCs over the top to ensure the Flow functions in alignment with the branding guidelines. Therefore, a hybrid of clicks AND code would be the best-fit solution – either Screen Flow and LWC, or OmniScript and LWC.

Challenge Three: Working with Complex Collection Types

The business you’re working with uses an Asset Management System outside of Salesforce, and they want the two systems to talk to one another. The external system is quite rigid in terms of sending data into Salesforce – when it does so, it sends a Map collection with the key being the Account External Ids (which can be set up to be the Id field on the Account object in Salesforce) and the value being the Asset information. 

You need to build a solution within Salesforce that receives the Map and compares it to existing records and relationships within your database. 

Round Three: Best-Fit Solution

This requirement highlights one of my biggest pet peeves with the Flow tool: the fact that it doesn’t support a Map collection type. It ruins it in some respects, as it forces declarative professionals to escalate a simple requirement to Apex. Sure, you could theoretically build a complex Flow that has a loop within a loop to handle a scenario in the absence of a Map collection type, but the requirement specifically states that the external system sends parameters in the form of a Map collection. 

Therefore, the only solution that can possibly handle this would be Apex, as Apex supports the ability to receive Maps and process them. As of writing this, Flow doesn’t yet. I’d love to see a world where we can get enough Salesforce Product Managers’ eyes on this idea, and we finally see the ability to receive, handle, and parse Maps in Flow.

Challenge Four: Large Scheduled Batch Processing

You work for a business with 2,000 active users who work in the insurance space. Your business performs calculations on Insurance Policies each night, with changes in Risk Rating, Proposed Renewal Premium, and other relevant values being updated on almost a million records a day.

These recalculations need to occur overnight, with the batch processing required to start at midnight each night. 

Round Four: Best-Fit Solution

You may see the scenario and immediately think of using a Schedule-Triggered Flow to address this problem, and your “clicks-before-code” mentality aligns with what Salesforce would want you to think. However, there’s one key part of the requirement that you can use to disqualify the tool. The business was clear that there are almost one million records that need to be processed every single day. 

One of the current considerations of the Schedule-Triggered Flow tool is that it can only process 250,000 interviews per 24 hours, OR 200 multiplied by the number of users in your org, whichever is greater. The requirements state that your org has 2,000 active users, which increases the number of interviews in 24 hours to 400,000. However, this is still nowhere near the million-ish records that need to be processed daily. Even if it was closer to a million, you’re not leaving any space for other Schedule-Triggered Flows within that org.

It is for this reason that Apex would be the best-fit tool in this round. Apex performs slightly better than Flow as well, which would be another big decision maker for selecting Apex as opposed to Flow for multiple calculations per record for a million records. Salesforce Architects talks in greater detail about high-performance batch processing between Apex Triggers and Flows, which you can read for more information and scenarios.

Challenge Five: Rollback Part-Way Through Transaction

While working through a specific complex automation, you need the ability to set savepoints throughout to ensure that if an error or failure occurs during the process, you can roll back to a specific point in time. Your business has specifically noted that if an error is experienced during the process, up to three prior record inserts will need to be rolled back to avoid orphaning records.

This means that the error can’t simply stop in its tracks and leave newly created records as they are, nor can it simply roll back ALL records (as some at the beginning should remain, but not all). 

Round Five: Best-Fit Solution

This is quite an interesting requirement and may be a bit of a head-scratcher if you’ve not come across something like this before. We know that Flow has received a Roll Back Records function in Winter ‘22, so you may be wondering if Flow could be used here. This is a potential solution but not the most elegant, leaving Apex as the winner here. Let me explain further…

Roll Back Records in Flow works by rolling back any pending records in that particular transaction. The example Salesforce gives in their Release Notes is that this includes all records sitting between one screen and the next. The requirements don’t state that there are any screens involved in the processing, but it does mention that the records themselves are important when wanting to avoid creating orphan records.

The likely best solution here is to use Apex’s setSavepoint, releaseSavepoint, and rollback methods in the Database class. These methods will give the developer the ability to set custom rollback points and allow for those rollback points to progress behind the scenes without the need for additional Screens for the sake of data preservation. 

And the Winner is…

I’m sure it comes as no surprise to anyone that there isn’t a single winner here – there’s no one tool to rule them all and there’s no “let’s migrate all our Apex to Flows”, or vice versa. Flow, Apex, LWC, Visualforce, OmniStudio, MuleSoft, and any other tool that I’ve mentioned above has its place. Some will be better than others at certain tasks, and that’s fine. There may also be different results depending on your Salesforce subscription type, and that’s fine too. 

In my experience, the best and most important thing is knowing the options that are available to you as a business. If you’re running a Professional Edition of Service Cloud you will have different limitations than someone who is running an Ultimate Edition version of Salesforce Industries – you’ll also have different needs! 

Salesforce’s message is that you should use clicks before code where possible. This doesn’t mean you should always use clicks before code, but only where it makes sense. For example, if you need to configure a structured Opportunity name based on the Account Name, Opportunity Type, and Amount fields, then you should use a Before-Save Record-Triggered Flow to apply this. 

For something more complex like the Map collection processing scenario outlined in round three, you should consider Apex. Even if it is possible to do this in Flow using nested Loops, it will be more efficient time-wise to build an ongoing system resource usage to simply hand off to Apex.


Salesforce offers many different tools and it is up to knowledgeable Admins, Developers, Architects, and Consultants to determine the best strategy, the best tool for the problem, and offer businesses the best possible experience using a combination of these tools. 

If you’re new to Apex and are looking to learn more, you may want to learn more from the Apex Academy: A-Z of Salesforce Apex. Alternatively, if you’d rather dabble into the world of Salesforce Flow you may want to take a look at the Ultimate Salesforce Flow Foundation Course.

The Author

Tim Combridge

Tim is the Managing Director at Sensible Giraffe, passionately educating others via high-quality blog content and training courses including the Ultimate Salesforce Flow Foundation Course.


    David Allen
    May 11, 2024 4:48 pm
    Tim, I really like your use of real-world scenarios. They story-like quality makes it easy to understand and remember. This is one of the best articles I've read on automation in Salesforce.

Leave a Reply