As Salesforce keeps enhancing Flows, my interest and enthusiasm keeps growing too. One area that Salesforce needs to “fix” is where you can invoke sub-flows. Sub-flows are flows that another flow can invoke. The use case for them is you have common functionality that you want to do in multiple places for various reasons. If you have to make a change, you can make it in the sub-flow and everywhere it’s used, it’ll get applied. Essentially, it’s what functions in code are in flows.
Currently, sub-flows can be invoked from a scheduled flow, from a screen flow, and from another sub-flow aka an autolaunched flow. They can’t be run from a record-triggered flow or a platform event triggered flow. In this post, we’ll explore other alternatives to invoke sub-flows in flows and the trade-offs of each. This feature will likely come eventually from Salesforce but unsure when. To help get it prioritized, upvote the idea.
Sub-flow Invocation Declarative Alternatives Summary
- Platform Event(s) – Create a platform event that has custom fields on it with the necessary input. Create a platform-event flow that does the desired sub-flow logic. All the caller / master flows that would’ve called that sub-flow will now create those platform events using a Create Records element.
- Process Builder – One can use a process builder on record change to then invoke an autolaunched flow. This is good when a subflow should be called when a record changes and meets some criteria.
- Apex Action To Call Subflow – A flow can call an apex action that then invokes the subflow. Since autolaunched flows can be dynamically instantiated, one can tell the apex which autolaunched subflow to instantiate and the input to provide to it. Forcepanda writes about that in the Flow Action: Call Subflow.
- Inline The Sub-flow – Copy the sub-flow logic into its caller methods. This is the least desirable option and will probably lead to a maintenance nightmare but it’s an option.
Apex Triggers / Invocable Apex– If one can write Apex, that’s actually the best “alternative” because one can easily use the same code from different apex triggers on different objects and from other places. This was intentionally excluded because I wanted to see what declarative only options there are.
Note – Platform Events and the Actions API alternatives won’t work in before-save record-triggered flows because one only has the Assignment and Update Records elements available so one can’t create platform events and can’t invoke Apex.
Platform Events Alternative
This alternative uses a separate platform event as the means to invoke common reusable logic. First create the platform event with the custom fields for the input. Next create a platform event flow that does the desired sub-flow logic. All the caller / master flows that would’ve called that sub-flow will now create those platform events using a Create Records element.
- Declarative Only – One doesn’t need any code and it’s all point-n-click.
- Scalable – High Volume platform events are highly scalable.
- Can be done from any of the flow options except from before-save flows.
Tradeoffs / Considerations
- Asynchronous – This causes the invoked logic to be asynchronous which can lead to partial transaction commits. Put differently, if the original automation worked but then the platform logic failed, only some of the automation worked. The opposite shouldn’t happen. I.e. the calling flow can fail and then the platform event logic succeed because the platform event should use the “publish after commit” behavior which only publishes the platform event if and only if the transaction succeeds.
- Runs as Automated Process User – The platform event flow will run as the Automated Process user with in system context. If it creates, updates, or deletes any records, those records’ created by and last modified will show as that user. This may or may not be a problem depending on your requirements.
One can use a process builder on record change to then invoke an autolaunched flow. This is good when a subflow should be called when a record changes and meets some criteria. This is the original way of doing things. Some may not know that it’s an option since Salesforce is promoting flows as the successor to process builders.
- Declarative Only
- Synchronous – Runs as part of the original transaction and either it all succeeds or it doesn’t.
Tradeoffs / Considerations
- Can be used from record triggered or autolaunched process builders only.
- Process builders are the slowest declarative option. If the subflow is updating the fields on the same record, consider using before-save flows instead since they’re considerably faster.
Apex Action To Call Subflow
A flow can call an apex action that then invokes the subflow. Since autolaunched flows can be dynamically instantiated, one can tell the apex which autolaunched subflow to instantiate and the input to provide to it. Forcepanda writes about that in the Flow Action: Call Subflow and there’s a sandbox package and production package one can use. The major limitation is it doesn’t scale as the number of records or platform events in the batch grows. See the Not Scalable point below for more info.
- Declarative Only – After one installs the package, one can create the autolaunched flow and then use the Apex Action to invoke it.
- Invocable from record-triggered and platform event flows.
Tradeoffs / Considerations
- Not Scalable – This is great for batches with few records or few platform events in them. However, Salesforce only lets one create and then run a flow from apex one at a time. Since the flow engine can bulkify the Apex Action so that all the inputs are passed to one invocable apex method, the problem is that the Apex can then only run the sub-flow one at a time. If that sub-flow queries or does DML (insert, update or delete), it’ll likely hit the 100 SOQL queries limit or the 150 DML statements limit.
- Note: I was thinking about how to scale this and one option, besides the platform events, was to have the Apex callout to the Salesforce Actions API with the named flow and its input which lets one invoke the named flow in bulk. The trouble is that one can’t typically do an apex callout when a record is being saved. One can get around that by making the API callout from apex using an async option like a future call or put the apex action after a pause element in the flow. However, that feels like a lot more work and potentially more fragile than just using the platform event option.
Inline The Sub-Flow
Copy the sub-flow logic into its caller methods. This is the least desirable option and will lead to a maintenance nightmare but it’s an option if absolutely needed. It would work great at first but then as one needs to make changes, every spot this has been duplicated will need to be changed too. This is likely the most used option today because many builders don’t know better.
Share in the comments any other solutions you have!