Salesforce have really been pushing Flow Builder the last few years and for good reason to. It has seen vast improvements in terms of functionality but it’s still not the Be-all And End-all. Salesforce recommends using point-and-click tools (e.g. Flow Builder, Process Builder) as opposed to code whenever possible. Not so long ago, to perform an action based on a record being created/modified/deleted, you’d have to create an APEX trigger to perform the logic you wanted, but even this functionality can be implemented using the Flow Builder. In this article, I’ll look at a few things I’ve learnt from working with flows and the best way to go about avoiding these problems.
For the purposes of this blog, I’m going to create a simple Flow which will require the user to enter a Name from which it will create an account.
The Create Account SubFlow (there really is no need for this to be in a SubFlow, it’s just for illustration purposes):
And my Flow UI looks like this:
Once your Flow becomes complex with many DML statements, loops and sub flows, then the problems start. Salesforce state that you are allowed up to 2,000 “Executed elements at runtime per flow” but what exactly does this mean?
This execution limit includes EVERYTHING! Every element, from Start of the main Flow to the End. Also not that a Sub Flow does not count as a single execution unit, but each element inside the Sub Flow is counted. In our flow, we only have 1 so it’s not too bad.
If I change my original flow so that instead of creating a single account using the name, we loop and create 500 accounts. Now we can’t use a traditional loop here as we don’t have a collection to loop through. Instead we can use the decision element to keep creating accounts until we have created 500.
My Flow now looks like:
Running this flow now produces the error: “Error Occurred: Too many DML statements: 151”. This is due to the fact we are created over 150 records separately. This is one thing to always avoid: DML in loops; bulkily by acting on a collection of records instead of a single record. Don’t forget, all the major governor limits still apply in Flows:
What we can do is to add each record we want to create into a collection, then create all our records at once, which is successful. Modifying the flow to the following would create the desired 500 records:
But let’s say we wanted to create 3,000 accounts. If we increase our “loop” to create 3,000 accounts, we’d get the following error:
Limit Exceeded You or your organization has exceeded the maximum limit for this feature
This error means that we’re trying to execute over 2,000 elements within our Flow, which is beyond the governor limit. Each item within the loop counts as a separate execution, not singular. To overcome this problem, we’d have to involve some APEX. The best solution would be to create an Invocable APEX method and pass in the number of accounts we’d like to create. This method would then return the accounts and we can create them in our Flow.
Limits with Collections
Let’s look at a different scenario now. Say we have a Flow where the user can type in an account name and a value for Annual Revenue, our Flow then goes and updates all the accounts matching the entered name and updates the annual revenue to the value entered. Here is our new Flow:
The DML statements are bulkified so we don’t need to worry about them. What we need to worry about is the loop. We have 3 elements outside the loop and 2 elements in the loop (the looping element itself is counted towards the limit of executions). Therefore, if the user searches for an account and our Get Records query returns more than 998 records (998 * 2 + the other 3 elements = 1,999 iterations, just below the limit), our Flow will fail.
In this instance, there’s not a whole lot we can do about this; this is where we need APEX to help bulkify this. I’ve created a SalesforceFlowHelpers repo in GIT (https://github.com/viqashussain/SalesforceFlowHelpers) to help with this exact situation. It contains many Invocable Method classes which can be called using generic SObjects and it will perform an action on the collection such as updating a field, filtering the collection etc.