# Flow Structural Conventions - Record-Triggered

<span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">As detailed in the General Notes section, these conventions are heavily opinionated towards maintenance and scaling in large organizations. The conventions contain:</span>

- <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">a "[common core](https://wiki.sfxd.org/books/best-practices/page/flow-structural-conventions-common-core)" set of structural conventions that apply everywhere</span>
- <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">conventions for Record Triggered Flows specifically (this page!)  
    </span>
- <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">conventions for [Scheduled Flows](https://wiki.sfxd.org/books/best-practices/page/flow-structural-conventions-scheduled) specifically</span>


<div data-layout="center" data-node-type="mediaSingle" data-width="" id="bkmrk-high-level-communica">These Record-Triggered Conventions expect you to be familiar with the tools at your disposal to handle order of execution and general Flow Management, including the [Flow Trigger Explorer](https://trailhead.salesforce.com/content/learn/modules/record-triggered-flows/meet-flow-trigger-explorer), [Scheduled Paths](https://trailhead.salesforce.com/content/learn/modules/record-triggered-flows/add-a-scheduled-task-to-your-flow), [Entry Criteria](https://help.salesforce.com/s/articleView?id=sf.flow_ref_elements_start.htm&type=5) (linked: a page that should document entry criteria but doesn't).</div><div data-layout="center" data-node-type="mediaSingle" data-width="" id="bkmrk-"></div><p class="callout info">This page directly changes conventions that were emitted by SFXD in 2019, and reiterated in 2021.  
This is because the platform has changed since then, and as such we are recommending new, better, more robust way to build stuff.  
If you recently used our old guides - they are still fine, we just consider this new version to be better practice.</p>

## Record-Triggered Flow Design

#### <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Before Creating a Flow  
</span>

##### <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Ensure there are no sources of automation touching the Object or Fields</span>

<span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">If the same field is updated in another automation, default to that automation instead, or refactor that automation to Flow.  
If the Object is used in other sources of automation, you might want to default to that as well, or refactor that automation to Flow, unless you can ensure that both that source of automation and the Flow you will create will not cross-impact each other.</span>

<p class="callout info"><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">You can leverage "where is this used" in sandbox orgs to check if a field is already referenced in a Flow - or take the HULK SMASH approach and just create a new sandbox, and try to delete the field. If it fails deletion, it'll tell you where it is referenced.</span></p>

##### <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Verify the list of existing Flows and Entry Criterias you have  
</span>

<span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">You don't want to have multiple sources of the same entry criteria in Flows because it will make management harder, and you also don't want to have multiple Flows that do almost the same thing because of scale.</span>

<p class="callout info"><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Identifying if you can refactor a Flow into a Subflow that will be called from multiple places is best done before trying to build anything.</span></p>

##### <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Ask yourself if it can't be a Scheduled Flow instead  
</span>

<span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Anything date based, anything that has wait times, anything that doesn't need to be at the instant the record changes status but can instead wait a few hours for the flow to run - all these things can be scheduled Flows. This will allow you to have better save times on records.</span>

##### <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Prioritize BEFORE-save operations whenever possible</span>

<span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">This is more efficient in every way for the database, and avoids recurring SAVE operations.  
It also mostly avoid impacts from other automation sources (apart from Before-Save APEX)</span>.  
Designing your Flow to have the most possible before-save elements will save you time and effort in the long run.

##### <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Check if you need to update your bypasses  
</span>

<span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Specifically for Emails, using [bypasses](https://wiki.sfxd.org/books/best-practices/page/bypasses) remains something that is important. Because sending emails to your entire database when you're testing stuff is probably not what you want.  
</span>

##### <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Consider the worst case</span>

<span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Do not build your system for the best user but the worst one. Ensure that faults are handled, ensure that a suser subject to every single piece of automation still has a usable system, etc.</span>

#### <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">On the number of Flows per Object and Start Elements  
</span>

- <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">**Before-Save Flows**  
    </span><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Use **as many before-save flows as you require**.</span><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">  
    You *should*, but do not *have to*, set Entry Conditions on your Flows.</span><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">  
    Each individual Flow should be tied to a **functional Domain**, or a specific **user story**, as you see most logical. </span><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">The order of the Flows in the Flow Trigger Explorer should not matter, as a single field should **never** be referenced in multiple before save flows as the target of an assignment or update.</span>
- **<span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">After-Save Flows </span>**<span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Use **one** Flow for actions that should trigger without entry criteria, and orchestrate them with Decision elements.  
    </span><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Use **one** Flow to handle **Email Sends** if you have multiple email actions on the Object and need to orchestrate them.  
    Use **as many additional flows as you require, as long as they are tied to unique Entry Criteria**.  
    </span><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Set the Order of the Flows **manually in the Flow Trigger Explorer** to ensure you know how these elements chain together.</span><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Offload any computationally complex operation that **doesnt need to be done immediately to a scheduled** path.</span>

<p class="callout info"><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Entry Criteria specify when a Flow is *evaluated*. It is a very efficient way to avoid Flows triggering unduly and saves a lot of CPU time. Entry Criteria however do require knowledge of Formulas to use fully (the basic "AND" condition doesn't allow a few things that the Formula editor does in fact handle properly), and it is important to note that the entire Flow does not execute if the Entry Criteria isn't met, so you can't catch errors or anything.</span></p>

<span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">To build open what's written above:</span>

- <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Before-Save flows are very fast, generally have no impact on performance unless you do very weird stuff, and should be easy to maintain as log as you name them properly, even if you have multiple per object. "Tieing" a flow to a Domain or Object means by its name and structure. You can technically do a Flow that does updates both for Sales and Invoicing, but this is generally meh if you need to update a specific function down the line.</span>

<p class="callout success"><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Logical separation of responsabilities is a topic you'll find not only here but also in a lot of development books.</span></p>

<p class="callout info"><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Before-Save Flows don't actually require an Update element - this is just for show and to allow people to feel more comfortable with it. You can technically just use Assignments to manipulate the `$Record` variable with the same effect. *It actually used to be the only way to do before-save, but was thought too confusing.*</span></p>

- <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">After-Save flows, while more powerful, require you to do another DML operation to commit anything you are modifying. This has a few impacts, such as the possibility to re-run automtions if you update the record that already triggered your automation. The suggestions we make above are based on the following:</span>
    - <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Few actions on records should not have entry criteria set. This allows more flows to be present on each object without slowdowns. The limit of One flow is because it should pretty much not exist, or be small.</span>
    - <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Emails sent from Objects are always stress inducing in case of data loads, and while a proper bypass usage does not require grouping all emails in a Flow,knowing that all email alerts are in a specific place does make maintenance easier.</span>
    - <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Entry-Criteria filtered Flows are quite efficient, and so do not need to be restricted in number anymore.</span>
    - <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Ordering Flows manually is to avoid cases where the order of Flows is unkown, and interaction between Flows that you ahve not identified yields either positive or negative results that can't be reproduced without proper ordering.</span>
    - <span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Scheduled Paths are great if you are updating related Objects, sending notifications, or doing any other operation that isn't time-sensitive for the user. </span>

<p class="callout info"><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">We used to recommend a single Flow per context. This is obviously no longer the case.  
  
</span>This is because anything that pattern provided, other tools now provide, and do better.  
  
The "One flow per Object pattern" was born because:  
- Flows only triggered in `after` contexts  
- Flows didn't have a way to be orchestrated between themselves  
- Performance impact of Flows was huge because of the lack of entry criteria  
  
None of that is true anymore.  
  
The remnant of that pattern still exists in the "no entry criteria, after context, flow that has decision nodes", so it's not completely gone.  
  
So while the advent of Flow Trigger Explorer was one nail in the coffin for that pattern, the real final one was actual good entry criteria logic.<span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">  
</span></p>

<p class="callout warning"><span class="fabric-editor-annotation" data-id="be7a8409-1ba7-4163-bb94-90bdcb9488e4" data-mark-annotation-type="inlineComment" data-mark-type="annotation">Entry Criteria are awesome but are not properly disclosed either in the Flow List View, nor the Start Element. Ensure that you follow proper Description filling so you can in fact know how these elements work, otherwise you will need to open every single Flow to check what is happening.</span></p>

## 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. This makes it a lot easier to debug and see what’s going on.

<div id="bkmrk--0"><svg class="SnapLinksHighlighter" xmlns="http://www.w3.org/2000/svg"></svg></div>