General considerations
- Do not use Process Builder or workflow rules
- The general target is to create solutions that are
- Scalable meaning that it performs well with large amounts of data and it is easy to build upon by other people than those that did the initial implementation
- Robust solutions meaning that it can handle error during execution and handle erroneous inputs
- Easy to understand and explain to other developers / consultants
- Follow the KISS design principle, Keep it simple, stupid!
- Simple is beautiful, in simple solutions there is less room for errors. Simple solutions are also easy to maintain and troubleshoot
- Simple solutions are also easy to explain to others
- Keep in mind that you are not the only one maintaining the Flow
- Follow DRY principle, Don’t Repeat Yourself
- Do something once and only once, meaning that if you keep recreating some logic make that to a sub-flow and use that sub-flow in other Flows
- Do not duplicate logic, reuse existing logic instead
- Consider what has already been implemented in the org (or on the object), instead of creating a new Flow add the new change to an existing automation (could be Apex also)
- It’s not a question can you do it with a Flow but should you do it with a Flow
- A common approach is to off-load all DML activity (insert, update, delete) to Apex to keep it simple and understandable
- If you need to make modification to an existing Flow, “leave it in better shape than you found it”. Make an improvement to the Flow keeping in mind the things discussed here.
- Building a Flow is not always the best idea
- Complex processing logic (e.g. handling of thousands of records) should not be built to a flow.
- Flows don’t have maps, or other elements which are suitable for heavy processing, looping is inefficient and may cause CPU limit errors (among others)
- Either create LWC/Apex implementation OR add Apex processing to do the heavy lifting part
Many of these angles and even more is opened up in this quality blog post:
Salesforce Flow Considerations
Must haves for every Flow
- Every Flow needs to be documented and every new version of the Flow needs to include version history what has been changed in the Flow compared to the earlier version
- Add the change history to the Version Properties dialog with version number, date, your name and description of what has changed
- Double check the entry criteria for the Flow – make sure that the Flow is only run for those records that are used in the Flow. This is to prevent unnecessarily firing of the Flow when records are changed.
- Flows must be reviewed with a colleague before being deployed to UAT / Production
- It is very important that another set of eyes will look thru the Flow implementation and catch potential issues
- Have a review session with your colleague to go thru the Flow with screen share and explain the logic (and changes) in the Flow
- This process shares the knowledge of the implementation of the Flow to other people so that they can possibly also make changes to the Flow
Do not
- Hard code ids in Flows
- The ids are not the same in the orgs which means that when deploying the Flow to another org it will not work
- Instead, if for example referring to a record type Id, get the Record Type Id with Get Records element with Object Type and Developer Name
- Hard code reference logic, like numbers or text
- Make the Flow more dynamic by using for example custom metadata (consider making the custom metadata based on org so that you can have different settings for different orgs)
- Use Flows for batch processing, use Apex batches instead
- When using API version less than 57 → Do not create more than 2000 element executions in a flow. Note that this does not mean 2000 records:
- every element in the loop is multiplied by the number of records so if you have 500 records and 4 element steps in the loop this is already 2000 element executions
- even if you have API version 57 or larger you can still hit CPU timeout or SOQL limit easily when looping thru large lists
- make DMLs inside a loop
- E.g. if inserting new records, first put all the records to a collection variable, then make one insert with Create Records element
- E.g. if finding records, define general conditions (WHERE MyField__c = ‘A’ OR YourField__c = ‘B’), then use loops or filter collection elements for further processing instead of getting one record at time and processing it
- use Flows for central Salesforce objects (Lead, Contact, Opportunity, Order, etc) where records are changed frequently or in objects where integration is pushing data into Salesforce in large batches
- make tricks / hacks to overcome limitations. If you do this then Apex is a better solution.
Do´s
- Use only one automation tool per object
- Using multiple tools results in
- increased time in troubleshooting issues
- difficult to understand the business logic
- difficult to understand the sequence in which operations are happening on the object
- poor performance
- documentation is more difficult
- Using multiple tools results in
- Always when creating a new flow, check Flow Triggers from the object, consider e.g.
- If there is already a before save flow setting field values on insert/update, use that same flow if that is adequate
- If creating another before save flow from some reason, ALWAYS populate the order of execution
- If there is already an after save flow which updates e.g. related opportunity products for opportunity, use that and don’t create another flow to process same related objects
- If there is already a before save flow setting field values on insert/update, use that same flow if that is adequate
- Incorporate null / empty checks to Flow, do not assume always happy path
- Bunch all your database changes together at the end of the flow, whether those changes are create, update, or delete records
- Make sure that your collection variable does not contain read-only fields because this will cause errors during record inserts and updates. This can happen if you use the “Automatically store all fields” option in the Get Records element.
- Build exception handling into the Flows, think about what will happen when an exception occurs and how to recover from exceptions
- Use “fault path” especially when doing DML operations (insert, update, delete). Modelling happy path is not enough since DML operations can easily fail
- Consider creating error logs if unhandled exceptions can happen – this applies especially to asynchronous flows
- Test the Flow, Record-Trigger Flows should be tested with Apex unit tests. Remember to assert the results in the tests.
- Always test the flows with users who actually use them. E.g. if making a flow to a case, which is handled in community by community user, test the functioning with a community user
- Record Triggered Flows support also declarative test framework “Flow Test” since Spring 23 release. However functionality is quite limited still and cannot be for example run upon deployment. Thus Apex unit test is still required in order to validate correct behaviour in all situations.
- Use free SFDX plugin to detect flow issues earlier in the development phase
- GitHub – Lightning-Flow-Scanner/lightning-flow-scanner-sfdx: A Salesforce CLI Plugin designed to pinpoint deviations from Industry Best Practices in Salesforce Flows, ensuring standards of business automation excellence.
- Add flow scanner into CI/CD pipeline so that flows will meet all the criterias before they get deployed into UAT/production
- Fix already implemented flows to be compatible with the scanner findings
Example Flow Naming Conventions
When you create a flow use appropriate naming convention
| Type | Naming Convention | Description Example |
|---|---|---|
| Screen Flow | <Object>_SCR_<ShortMeaningfulDecription> | QUOTE_SCR_AddQuoteLines |
| Scheduled Flow | <Object>_BAT_<ShortMeaningfulDecription> | CONTACT_BAT_SendBirthdayEmails |
| Before Update Flow, on Account | <Object>_TRG_BeforeSave_<ShortMeaningfulDecription> | ACCOUNT_TRG_BeforeUpdate_ShortDescription |
| After Update Flow, on Account | <Object>_TRG_AfterSave_<ShortMeaningfulDecription> | ACCOUNT_TRG_AfterUpdate_ShortDescription |
| Record-triggered Flow on Opportunity | <Object>_TRG_BeforeSave_<ShortMeaningfullDecription> | OPPORTUNITY_TRG_BeforeUpdate_ShortDescription |
| Event-Triggered Flow | <Object>_EVT_<ShortMeaningfullDecription> | INVOICE_EVT_SalesFinished |
| Record-triggered Email-sending Flow, on Account. | <Object>_EML_BeforeSave_<ShortMeaningfullDecription> | ACCOUNT_EML_BeforeUpdate_EmailSend |
References
Salesforce Flow Considerations
Flow Structural Conven… | SFXD Wiki
The Ultimate Guide to Flow Best Practices and Standards – Salesforce Admins

Leave a comment