10+1 Admin Tips: Building Maintainable Flows
10+1 Admin Tips: Building Maintainable Flows

10+1 Admin Tips: Building Maintainable Flows

11/22/2021 by Mario Di Genio
In this post we’ll take a look at best practices to build maintainable flows in Salesforce and tips on how an admin can troubleshoot some of the most common issues.

Introduction

In a previous post we reviewed how to troubleshoot processes in Process Builders. As powerful a tool as they are, we saw how, no matter how straightforward, sometimes you just can’t figure out why they aren’t working. This time, it is the Flows’ turn to help us accomplish our functionality goals, but not without giving us a few headaches along the way.

Flows provide even more possibilities for automation in a declarative point-and-click way, but with great power comes great responsibility. Nodes can easily become confusing, following the path that a record goes through becomes harder to track, and they can easily turn into an intricate heavily woven web of muddle.

So what can we do to not succumb to despair? Here are some guidelines to build Flows in an organized way that will make them easier to track and maintain.

Editor's note: Flows can seem overwhelming and complex to some, when in reality they can be quite simple. We will be walking through some common basic flows to help admins learn the fundamentals in an upcoming Arkus webinar. If you're reading this before the event on December 8th, you're invited to join us live. After this, you can access the recording via the registration page. Find the link to the registration page at the end of this post.

Tip 1: Identify scenarios and common behaviors

Before doing anything in Salesforce or even sketching it out, we recommend analyzing what you need to implement: scenario by scenario, where each scenario is a path that a record would go through under specific conditions. This way we are already following a more structured approach that will lead us to a cleaner, more organized implementation, with fewer bumps (troubleshoots) likely along the road and easier maintenance in the future.

Use Case

Our use case throughout this post involves Applications that are submitted and need to be linked to the proper Contact that submitted them. A form in our community allows users to enter their first name, last name and email address along with some other information depending on the type of application submitted. Salesforce creates the Application record and now we need an automated way to find the Contact to relate it to.

If a Contact with the first name, last name, and email address entered in the Application record and of Record Type “General” exists in the system, then assign that Contact in the Contact field of the Application.

Otherwise:

- If the Application is of Record Type “Traveler,” then create a Contact with the first name, last name and email address entered in the Application record and Record Type “Traveler,” and assign that Contact in the Contact field of the Application.

- If the Application is of Record Type “Educator,” then create a Contact with the first name, last name and email address entered in the Application record and Record Type “Educator,” and assign that Contact in the Contact field of the Application.

- If the Application is of Record Type “Explorer,” then create a Contact with the first name, last name and email address entered in the Application record and Record Type “Traveler,” and assign that Contact in the Contact field of the Application.

- If the Application is of Record Type “Meet the World,” then create a Contact with the first name, last name and email address entered in the Application record and Record Type “Traveler,” and assign that Contact in the Contact field of the Application.

- If the Application is of Record Type “GLL,” then create a Contact with the first name, last name and email address entered in the Application record and Record Type “Educator,” and assign that Contact in the Contact field of the Application.

- If the Application is of Record Type “Volunteer,” then create a Contact with the first name, last name and email address entered in the Application record and Record Type “Volunteer,” and assign that Contact in the Contact field of the Application.

Analyze the paths

This is a pretty well-ordered set of requirements, we can only wish we got them like this all the time. Our first recommendation is to prepare a table where each row is a scenario and each column a step in the flow. If at any step there’s a split depending on a certain condition, then you duplicate the row, so that each row has in that step one of the possible results of the conditions. Following this method you will be able to cover all possible scenarios to implement and test, already on your way to build a flow that is robust and consistent.

In this case we have different paths depending on the Record Type of the Application first, and then we have another split in scenarios depending on whether the Contact is already in the system or not. So our scenarios would be split overall like this:Maintainable Flows 1

Analyze the steps

As we complete each column with the steps, we recommend numbering them to keep in mind how the sequence for each scenario goes. In the cell for each step you can put the basics of what that step is going to be for that particular scenario. As a result, you will have a pretty good outline of all your scenarios:

Maintainable Flows Screenshot 2

Order and group similar behaviors

Now that we have all the steps and all scenarios, we recommend identifying the common steps among scenarios. The best way to do this is by color-coding those commonalities. In this case we have that for different scenarios we have to create contacts of Record Type Traveler and Educator:

Maintainable Flows Screenshot 3

We built this table following the requirements in the order they were written. But now that we can clearly see the similarities in some of the steps, we can reorder and group the scenarios by the common steps between them:

Building Maintainable Salesforce Flows 4

Following this method you will be able to implement your flow without repeating any nodes unnecessarily. Avoiding this kind of repetition allows you to build a flow that is more consolidated, with fewer steps, making it easier to maintain in the case of changes and fix in the case of troubleshooting.

Tip 2: Identify nodes and connectors

Identify nodes

Now that the scenarios are ready, we can start identifying how this is going to be represented in a flow:

Building Maintainable Salesforce Flows 5

All the common steps will be a node (to create, update, delete records, assign values, etc.), and the steps in which we can split depending on the conditions will be a decision node. Note that if we hadn’t followed Tip 1, we could have ended up with more nodes than we need, which eventually turns into more nodes, connectors and paths of execution to implement and maintain (compare the following figure with the previous one):

Building Maintainable Salesforce Flows 6

Identify connectors

Now that we have all the nodes identified, we can see how they will connect with one another, and how the different paths of execution will go:

Building Maintainable Salesforce Flows 7

Finally, you can start visualizing what your flow is going to look like:

Building Maintainable Salesforce Flows

Tip 3: Build one path of execution at a time

We have reached the point where we’re ready to go into Salesforce and start building our flow. Thanks to the previous analysis, we have more certainty as to which nodes to build and how to connect them in a more optimized way than if we had started doing it directly in Salesforce from the beginning.

To build the flow we recommend you start with only one path of execution (one scenario, or one row in our table), test it out, if it works, then you proceed to create a new version of the flow with the next path. This is a good practice as it allows you to identify errors early on and troubleshoot them before you reproduce scenarios that reuse steps that already contain errors.

Building Maintainable Salesforce Flows 8

Tip 4: Follow the path of execution

In both building and testing your flow you have to follow the path of execution to properly implement and troubleshoot it if needed. Think of it as taking the subway:

  • There’s passengers (like the records and variables you manipulate throughout flows).
  • A passenger gets into their origin station (the Start node in flows).
  • There’s stations (like nodes in flows) where new passengers get on (like a Create Records or Get Records node in flows), switch to another line (like an Update Records node in flows) or get off (like a Delete Records node in flows).
  • A passenger can switch cars in certain stations (like an Assignment node changes the value of a record or variable).
  • Every station is connected by a line (like a connector in flows).
  • Some stations are hubs where passengers can choose which line to change to (like a Decision node in flows).
  • Several passengers can do any of the actions described above in any station in a row (like a Loop node in flows).
  • A passenger may need to reload their metro card and interact with a screen device to enter data such as amount and payment information (like a Screen node in flows).

building flows 9

When building a flow you are planning the possible paths that a record can take to be processed, without errors, and left in a consistent state (like passengers getting to their destination safe and sound).

Map your scenarios with paths of execution

Once you have built and tested your first path and it works as expected, you can continue adding each remaining scenario to your flow one at a time: build, test, and continue with the next scenario.

Building Maintainable Salesforce Flows 9

After you have all your scenarios implemented, you should be able to compare your table with the flow and trace all the paths of execution in it (this looks very much like a subway map, which is why we put it as an example).

Building Maintainable Salesforce Flows 10

Our next tips are recommendations to follow for the building of each node of your flow.

Tip 5: Use constants

Many times there are values that you will need to use over and over again throughout your flow. A common example is the ID of Record Types to set them when creating or updating a record. Flows allow you to create Resources of type Constant, which is the best way to store a value that is not going to change and that you can reference from any node. For example: in a Create Records node to assign the Record Type as a text value:

Building Maintainable Salesforce Flows 12

Create a Resource of type Constant with the value:

Building Maintainable Salesforce Flows 13

On a side note, when you are building comparisons of Record Types we recommend always using the developer name of the Record Type instead of the label. Labels may change over time to display it to end users. But for internal purposes in configuration the developer name will not (and should not) change, so that you don’t have to update any item of metadata that references it. For example: here’s how you can compare the Record Type to a specific value comparing the Developer Name in a decision node:

Building Maintainable Salesforce Flows 15

You can also use Constants to store the Developer Name of a Record Type that you will use within your flow:

Building Maintainable Salesforce Flows

And then use it in conditions to filter by:

Building Maintainable Salesforce Flows

We applied both these techniques in the decision node to divide the paths by the Application Record Type and when creating the new Contact with the corresponding Record Type.

Tip 6: Use variables for common results

Variables are the most used type of resource in flows. They allow you to store values, an entire record or a collection (list) of records to manipulate throughout your execution. But besides that, the same way that in Tip 1 we identified common behaviors to consolidate nodes and reduce the amount of nodes to maintain, the same goes for variables. In our use case, if we have to create a Contact, even if it’s of different Record Types, the result is always the same: create it and assign the created Contact to the Contact field of the Application. So whatever the case, we can store the ID of the Contact in a variable in each case and then have a single node to assign the value of that variable to the Contact field of the Application. This way we save repeating the same Assignment node several times.

We define the variable to store the Contact ID:

Building Maintainable Salesforce Flows

In the Create Records node we indicate to store the ID of the created Contact in such variable:Building Maintainable Salesforce Flows

And then we have a single node to do the Assignment of the Contact ID to the field in the Application using the variable:

Building Maintainable Salesforce Flows

The same Assignment node can be used for all cases where the Contact needs to be assigned to the Application, saving us a lot of time reviewing and maintaining the different paths of executions that need to do the same:

Building Maintainable Salesforce Flows

Tip 7: Follow naming conventions

As explained in First Time Flownatic Tips, following naming conventions is key to easier troubleshooting. Nodes are hard to read, you have to open them one by one to see what criteria they have defined in them, which makes it difficult to have a full view of the entire flow and follow the paths of execution. Naming helps you remember what each item does, how to debug and how it is connected without opening it.

We recommend creating a naming standard for yourself when naming variables, nodes, connectors and other Resources. Remember to always be consistent (naming format stays the same), clear (what or which kind of action is performed) and explicit (add as much detail as possible to uniquely recognize the action by its name without having to open it to see its details).

Building Maintainable Salesforce Flows

Tip 8: Debug your flow with a history field

Debugging with the flow debugger is not always helpful for Administrators and the error messages a flow sends by email are not always the most clear for non-Developers to tell what the issue is. If you are having a hard time telling what’s going on, which node your record is entering and which one is not, a history field is the best way to track this down. You can create a history field in the object that your flow executes on or you can create a special object to track down the history of your flow, that’s up to you. In this case we’ll show you how to do it with a field in the object that is the subject of our flow. In our use case, our flow fires on the Application object, so we create a field called “Application History” of type Text Area (Long) with plenty of length to store any history we need:

Building Maintainable Salesforce Flows

Make sure you add the field to the layout so that you can see the results after your flow executes. Then in the flow, you can add an Update Records node to put messages into the history field we just created (let’s call this node “Debug Node”). 

The message in the history field must include the previous value of the field (in this case Application_History__c), so that it doesn’t overwrite itself with other debug nodes in the path and concatenates the debug messages as the record goes along the flow, followed by whatever text you want to include as a message to yourself of which node it just passed.

For example: store in the Application History field the value:

{!Get_Application.Application_History__c} -> entered node Create Volunteer Contact RT

If we place this Debug Node after the node that creates the Contact of Volunteer Record Type, then while we are testing, if the history field has this text it means it went through the node as expected, otherwise there’s some condition before that node that is preventing the record to follow that path, and you need to place more Debug Nodes earlier in your flow.

Building Maintainable Salesforce Flows

You can select the Debug Node and clone it with the “Duplicate” button as many times as you need:

Building Maintainable Salesforce Flows

Place each copy within as many nodes as you want to debug:

Building Maintainable Salesforce Flows

Change the text to add to the history field in each node.

You can also include values of fields to see which values they have and why they may or may not meet the conditions to go down one path or another, for example:

{!Get_Application.Application_History__c} -> entered node Create Volunteer Contact RT with {!Get_Application.Whatminor__c} 

which will store the previous application history value and the string “ -> entered node Create Volunteer Contact RT with ” concatenated with the value of the Whatminor__c field at that moment of the execution. This way we can tell the path that the record went through and why.

Tip 9: Remember: Assignment does not mean saving

When we created the scenarios during Tip 1 we explicitly put the Assignment of the Contact as a separate step from the Update of the Contact. But likely you may not consider them as separate steps while you are designing your scenarios and then implement it in the flow as only the Assignment node:

Building Maintainable Salesforce Flows

If you find that the flow is not saving data in your records, likely you just missed saving the record with an Update Records node:

Building Maintainable Salesforce Flows

Think of an Assignment node like changing the value of a field in a page layout, and then the Update Records or Create Records node like clicking the “Save” button in the page layout. You need to do both in the page layout, otherwise the data will not be saved, just like the Assignment also needs the Update Records or Create Records node afterwards.

Tip 10: Work with parameters to manually fire the flow and make it return to the original record

If you are defining a flow that you want to be launched manually from a custom button in a record, instead of triggering automatically when the record is created, updated or deleted, then you can work with parameters. This is useful if you want to make it easier for you to trigger the flow while you are testing.

You can create the custom button in the object with “Content Source” = URL. In the “Button or Link URL” you have to form the call to the flow with:

/flow/<api name of your flow>?<name of variable to pass the ID of the record>=<ID of the record>

So for example: if your flow has API Name “Process_Application” and the flow is expecting the ID of the record that triggers it in a variable called “appId,” then your url will look like:

/flow/Process_Application?appId={!Application__c.Id}

Building Maintainable Salesforce Flows

The flow should have the “appId” variable of type Text defined and as a first step to get the record with the ID you passed in the appId variable as follows:

Building Maintainable Salesforce Flows

If in addition you want the flow to automatically close and return to the original record upon completion, you can add the retUrl parameter to the url:

/flow/<api name of your flow>?<name of variable to pass the ID of the record>=<ID of the record>&returl=/<ID of the record>

Which in our example would look like this:

/flow/Process_Application?appId={!Application__c.Id}&returl=/{!Application__c.Id}

Building Maintainable Salesforce Flows

Extra Tip: Keep inserts, updates, and deletes outside of loops

This one is a very technical, very long to explain, but very important issue to be aware of when building flows that may process multiple records at a time. If you are not careful, you may or may not end up with errors when the flow is executing, depending on how many records you are manipulating at a time. Luckily one of our colleagues already wrote about this and you can get a full dive into it here Flow Bits – Keeping your DML Outside of the Loop.

Conclusion

Flows can be a life saver, but not without a couple of tricks. Patience is a must and hopefully these tips will help you become more savvy when building and testing them. Staying organized and methodical can save you time and effort. There’s a lot to cover and it may take a bit of thinking outside the box to find workarounds for your particular troubleshooting. Regardless how many times you feel you failed, persevere, for where there’s a will, there’s a way.

Resources

Here are some interesting articles, ideas and exercises related to the topics we touched:

If this all sounds complex, we will be hosting a live flow building demo in our next free Arkus Lunch & Learn, "4 Flows Every Salesforce Admin Needs to Know," that will air live on Wednesday, December 8th at 12:15pm EST. A recording will be available via the registration page after the event takes place. 

Find more details and register here: https://www2.arkusinc.com/lunch-learn-flows

Do you have any tips to share when building or debugging flows? Any particular technique that has worked well for you? Tell me all about it in the comments below, in the Salesforce Trailblazer Community, or tweet directly at me @mdigenioarkus. Subscribe to the Arkus Newsletter here to get the top posts of the Arkus blog directly to your inbox.