Skip to main content

Flow Structural Conventions

Per-Flow Design

  1. Fill in the bloody descriptions. You'll thank yourself when you have to maintain it in two years. Like seriously it takes two seconds, stop arguing and just do it.
  2. All Pink (DML or Query) elements should have Error handling. Screen Flow ? Throw a Screen, and display what situation could lead to this. Record-triggered Flow ? Throw an email to the APEX Email Exception recipients. Hell, better yet throw that logic into a Subflow and call it from wherever. Or send a Notification I don't care. CATCH. ERRORS.
  3. Don't do DMLs or Queries in Loops. Simpler: No pink squares in loops. Salesforce now actually warns you when you're doing this, but it still bears saying. To avoid doing this, ASSIGN a single record that you want to process to a collection variable in your loop, then do the DML outside of the loop at the end of your Flow.
  4. If you have the same logic happening in various places, this is where you should be considering to use Subflows. This will avoid you having to modify the same thing in 6 places. It also makes the Flows easier to read.
  5. Don't exit loops based on decision checks. The Flow engine doesn't support that well and you will have issues if you ever go back to the main loop
  6. Don't use non-official components without checking their limits. Yes UnofficialSF is great, and it also contains components that are not bulkified or contain bugs.

Cross-Flow Design

  1. Try to pass only one Record variable or one Record collection to a single Subflow. Intiializing a lot of Record variables on run often points to you being able to split that subflow into different functions. Passing Records and a lot of configuration information as variables is fine, though.
  2. Once at the point of designing subflows, try to make those reusable as much as possible - you might be able to reuse a subflow from another main flow later if you design them well.
  3. Avoid casquading Subflows wherein one calls another one that call another one. Unless the secondary subflows are basically fully abstract methods handling inputs from any possible Flow (like one that returns a colleciton from a multipicklist), you're adding complexity in maintenance which will be costly.

Record-Triggered Flow Design

One Trigger Per Object is... "subject to considerations" now. SFXD as of writing has no formal best practice on the number of flows per Object. The current recommendations below may change depending on new releases or communications from Salesforce.

  1. Prioritize BEFORE-save operations whenever possible. This is more efficient in every way.
  2. You can't really leverage Subflows yet (at least not for Before-save), but it will come later, so try to design in a way you can leverage Subflows later if at all possible.
  3. Record triggered Flows should be 1 per Object and Operation (so `RTFL01_ACC_BeforeUpdate`, `RTFL02_ACC_AfterUpdate` ) excluding Email Flows.
    1. In the case of BeforeUpdate, the "decisions" should be done in a vertical tree reminiscent of Process Builder, and the actual actions and logic to the right side. This is done to familiarize Admins with Flows if they open them, and to ease migrating to Subflows when possible.
    2. In the case of AfterUpdate, the "decisions" should be done in a vertical tree reminiscent of Process Builder, and the logic should be stored in Subflows whenever possible, and called on the right side of the decision.
  4. Flows that exclusively are Email handlers should be their own record-triggered flows. This is done because the conditions for evaluating Flows can impact how Email sending is handled.

 

On Delayed Actions

Flows allows you to do complex queries and loops as well as schedules. As such, there is virtually no reason to use wait elements or delayed actions, unless said waits are for a platform event, or the delayed actions are relatively short.
Any action that is scheduled for a month in the future for example should instead set a flag on the record, and let a Scheduled Flow evaluate the records daily to see if they fit criteria for processing. If they do in fact fit criteria, then execute the action.
A great example of this is Birthday emails - instead of triggering an action that waits for a year, do a Scheduled flow running daily on contacts who's birthday it is.