A couple years ago, I wrote a blog on my personal Flow Best Practices. Because I learn more about Salesforce every day, and my knowledge and understanding of the platform continues to grow, my list of best practices for flow has evolved. I share it with you today – and who knows, maybe in 2024 I’ll have even more!
These days, I actually have 24 Best Practices in total – some for Screen Flows AND some for all Flow Types. To keep things easy to digest, I’ve split the Best Practices into one post into one for All Flow Types and one for Screen Flows only – and some of these best practices have their own post as well.
Scroll down for the details, or click the links below to jump right to the best practice:
- Establish a Naming Convention
- Document Your Flow
- Limit Triggered Flows to One Per Object
- Reduce the Number of Variables
- DO NOT Hard Code IDs
- Use the Description
- Use Record Collections (AKA Bulkify)
- DO NOT Nest Loops
- Save Database Changes for the End When Possible
- Always Include A Fault Path
- Use Auto Layout
- Be Smart With Decisions
- Use Multiple Assignments
Best Practice #1: Establish a Naming Convention
As I mentioned in my prior Flow Best Practices post, a naming convention is key as the number of flows (and admins) in your org continues to grow. Establishing a naming convention helps future you, and your fellow admins, understand what the flow should be doing. I recommend you develop a standard not only for flows, but the items inside them as well. Here are some of my standard formulas for a flows and their various pieces and parts:
| Flow Item | Naming Convention | Example |
|---|---|---|
| Flows | Object | Trigger | Function | Contact | Screen | Create New |
| Variable (Text) | Prefix: v | vAccountId |
| Variable (Record) | Prefix: rv or rcv | rvAccount or rcvAccounts |
| Variable (Number) | Prefix: n | nCountCollection |
| Formula (Text) | Prefix: ft | ftDefaultAccountName |
| Record Choice Set | Prefix: rc | rcContactsFromAccount |
| Screens | ##. Purpose | 01. Account Details |
| Screen Components | Prefix (API Name Only): ##_ | Label: Account Name; API Name: X01_AccountName |
COMING SOON: A full post dedicated just to naming conventions!
Best Practice #2: Document Your Flow
Be the admin you wish came before you! And do that by having a firm process for documentation. I go for three key things for this:
- Process Diagram – You can do this in something like PowerPoint with shapes and arrows, or you can utilize a true process mapping tool. I prefer LucidChart, but here’s a list of free tools you can utilize (LucidChart limits you to 3)
- Written Documentation – Create some actual written documentation of your flow. This fits well If you have access to a documentation/wiki tool like Confluence, but you can always just throw the information in a Word Doc or Google Doc, if nothing else. Here’s what I try to include in mine:
- Purpose of the flow
- Where the flow is used
- API Name / Label
- List of ALL elements (Screens, Actions, Assignments, etc.) and resources (Variables, Formulas, Constants, etc) – I usually throw these items into a table with a quick description of what the purpose of the item is
- Referenced in Change Request – Find a way to link all requests related to the flow together. Maybe it’s with a label, an Outlook Folder, or something unique to your project management software. I come from a land of Jira companies, so I’ve accomplished this utilizing Jira Components, then each ticket that has work on the flow gets attached to the component.
Best Practice #3: Limit Triggered Flows to One Per Object
Most auto-launched processes should be limited to one per object – and ideally, only one type of automation, if you can get away with it. My preferred method is that each object has:
- One Before Save Flow
- One After Save Flow
- As many screen flows as I need (though be strategic about how many you create – use subflows as frequently as possible to reduce repetitive work)
Check out the official Salesforce Architect Guide for a table of automation
Note: With Spring 22, I’m reevaluating my stance on this one. With Flow Trigger Explorer and Trigger Order, this is not one of my hard-and-fast rules any longer.
Best Practice #4: Reduce the Number of Variables
Sometimes, it’s tempting to define a variable for every little thing… like vAccountName, vBillingStreet, vBillingState. But we can make our lives so much easier just by…
- Using Record Variables – So we can do things like have ONE variable defined for an account (
rvAccount) and then reference the Billing Street by callingrvAccount(rvAccount > Billing Street) … Read more - Using Global Constants – I have walked in to orgs with flows for a formula that grabs the current date (i.e.
TODAY()) and then this formula is used in an assignment (usually to a field). Instead of doing something like that, just use the$Flow.CurrentDateconstant directly in your assignment. … Read more - NOT Manually Assigning Outputs – When coming out of an action or subflow, it can be tempting to assign the outputs to specific variables. BUT just like we condensed our variables with a record variable, we can do the same thing by utilizing “Outputs” (which, in terms of subflows, is any variable defined as “Available for output”)
Best Practice #5: DO NOT Hard Code IDs
I’m sure you already know this one – but DO NOT hard code IDs. 99% of the time, you can do a record lookup to get what you need (lookin’ at you, Record Types). Then just assign the ID of the found record to where you need to use it.
Best Practice #6: Use the Description
Put yourself in the frame of mind of you’re someone who knows nothing about the flow trying to update it. What information do you need to know? And, yes, I do add a description to literally everything in my flows. I didn’t used to, and then I learned future me always appreciates it.
Best Practice #7: Use Record Collections (AKA Bulkify)
Story Time… I once opened a flow in a “mature” org that had users fill out a screen, commit data, send users to another screen asking if they needed to add another record, then take them back to the first screen. And users could literally do this FOREVER. So, this flow touched the database A LOT. (And I didn’t even mention the constant “Get Records” sprinkled everywhere)
Best Practice #8: DO NOT Nest Loops
Just don’t. There has been 1 time in my entire career I have actually had to do this. And I opted to instead learn to write Invocable Methods because Apex is your friend if you’re in a situation where there’s no other way around it. You’ll hit SO MANY LIMITS if you nest loops – especially in a bigger org. Don’t do it.
Example: Apex will let you query a list of accounts, and then use the resulting list of accounts to also update those contacts, rather than the flow solution of “Query the Accounts, Loop through the Accounts, then loop through the contacts to update Status”
Best Practice #9: Save Database Operations for the End
Remember 10 seconds ago when I mentioned that flow that added records as the user input information, essentially? That was also a great example for why bulkifying would be useful. Adding those records to a collection, and then not creating the collection until the last possible moment would have worked better.
Best Practice #10: Always Include a Fault Path
You can’t catch everything with a fault path, but you can catch most things. I’ve worked in orgs with low frequency of automation errors, and orgs with a higher frequency. In the high frequency org, I actually created a subflow specifically for error handling. Here’s what it did:
- Grabbed important details from the Errored Flow (Record Id, User, Flow API Name, Flow Fault Message, Message to show the user, etc.)
- Used Flow inputs to create an “Automation Error” record
- For screen flows, showed the user an “Uh Oh, something went wrong!” message
Bonus Tip: In Auto-Layout you can now link multiple database operations to the same fault path
Best Practice #11: Use Auto Layout
I don’t have much to add, other than using auto-layout makes life easier when you’re building a flow – it’s a bit like adjusting to Lightning, though, and you do have to practice a bit with it to know how things are supposed to work.
Best Practice #12: Be Smart With Decisions
I’ve looked at (and built) a lot of flows in my day. I often see nested decisions, like there’s a decision element for “Is Account Status Blank” and it has two outcomes, yes and no. The Yes path then goes to another decision element – that’s probably checking if Account BIlling State is blank. IMHO, this is just… cluttered junk. Instead, I put as much as I can in ONE decision element, without clouding it. I would instead do this with one decision element, with THREE outcomes
- Account Status & Billing State are blank
- Only Account Status is blank
- Neither is blank (which is the default that I’ve renamed because that makes me happy)
Bonus Tip: Use this same methodology to validate on-screen information
Best Practice #13: Use Multiple Assignments
This is a lesson I picked up along the way. We don’t always have control over the order in which items in an assignment happen, we can control the order in which our assignment elements themselves go. So, utilize multiple assignments when you need to (yes, I know I just told you to use fewer decisions, and now I’m telling you to use more assignments – I swear, it’s for a good reason). Typically, you’ll need to do this when you’re assigning values to a record variable, and then adding that record variable to a collection for processing.
That’s all for now! Stay tuned for part two with the goodies for Screen Flows!
