Skip to main content
New tool CRON Expression Builder — preview next run times before you schedule Apex. Open the builder →
Visualizing a complex Salesforce Flow canvas detailing best practices for automation logic and error handling
Flow

Salesforce Flow Best Practices: 12 Rules That Prevent 90% of Errors

The Salesforce Flow best practices most teams skip: bulkification, trigger choice, fault paths and subflow design, distilled into the 12 rules I apply on every implementation.

The short answer

Most broken flows are fine on one record and fall over on a data load. The rules that prevent it: keep Get and Update elements out of loops and work in collections, use before-save when you only update the triggering record, split monolithic logic into subflows, and put a fault connector on every data element.

Why your flows keep breaking

Most of the broken flows I get called into were fine on one record. Then a data load runs, or a user mass-updates a list view, and the whole thing falls over. The users are annoyed, and the admin spends the afternoon cleaning up.

Flow is visual coding at this point. Treat it as a drag-and-drop toy, without thinking about what happens under the hood, and it will behave like one. I've spent years fixing "broken" flows that were only ever badly designed, and nearly all of those problems trace back to how someone approached the canvas.

Salesforce Flow best practices for bulkification

The most common mistake I see is a Get Records or an Update Records element sitting inside a loop. It reads well on the canvas. For every item in this list, go find the related record. On the platform it is a one-way ticket to governor limits, and you will hit "Too many SOQL queries" faster than you can blink.

Think in collections instead. Grab everything you need before the loop starts, or let the newer elements do the heavy lifting. If you are still untangling old loop patterns, read how to handle bulk record processing in Flows. It will save you some late-night debugging.

Gathering IDs trips people up too. If you are looping only to build a list of IDs, use the Transform element instead. It is cleaner and much lighter at runtime.

Stop over-complicating your trigger logic

Before-save or after-save? Most teams get this wrong. If you are only updating fields on the record that triggered the flow, use before-save (Fast Field Update). It is significantly faster because it does not kick off another save cycle. Once you need to update related records or send an email, you move to an after-save flow.

I've seen teams cram an entire business process into one giant, monolithic flow. Don't. It is a nightmare to maintain. Break the logic into subflows so your automation is easier to read and, more to the point, easier to test. If a piece of logic shows up in three different places, it should be a subflow.

Error handling and Salesforce Flow best practices

Here is an opinion I will defend: a flow without a fault path is not finished. Plenty of clients have told me their flows "just stop working" with no explanation. When a DML operation fails, Flow throws a generic unhandled fault at whoever happened to be saving the record. That is a terrible experience.

Put Fault connectors on your data elements. At minimum, email the admin team the fault message. Better, log the error to a custom Error Log object. For the version your users actually see, look at Salesforce Flow error handling for email automation, which keeps people informed without showing them raw system errors.

A good flow tells you exactly why it failed.

Watch your transactional boundaries

Flows run in the same transaction as the event that triggered them. A slow flow is a slow save button. A flow that hits a limit takes the whole record save down with it. Watch for recursive updates, where Flow A updates a record, that triggers Flow B, and Flow B updates the original record again. That loop eats CPU time in seconds.

Anything heavy that does not have to happen right this second belongs on a scheduled path or in asynchronous processing. If a complex calculation does not change what the user sees on save, let it run in the background. The UI stays snappy and your users stay happy.

Key takeaways for flow design

  • No DML in loops. Seriously, just don't. Use collections.
  • Before-save for same-record updates, after-save for everything else.
  • Fault paths on your data elements, so failures arrive as messages instead of mysteries.
  • Subflows, so the main flow never turns into "spaghetti."
  • Selective filters in your Get Records elements, so you are not pulling data you will never read.
  • Filled-in description fields. Your future self will thank you.

Testing isn't optional

I have lost count of the flows that worked on one record and died the first time someone opened Data Loader. Always test with bulk data. Drop 200 records into a sandbox and see whether the flow survives. Check the nulls too. What happens when that Account Name is empty, or the lookup field is blank? If you have not tested the bad data, you have not tested the flow.

Following these Salesforce Flow best practices feels like extra work up front. It buys back the hours you would otherwise lose to bug reports, and you spend them building something new instead. Keep it bulk-safe, keep it modular, and plan for the day it goes wrong.

The 12-rule cheat sheet for Salesforce Flow best practices

  1. Never put DML or SOQL inside a loop. Build collections before the loop and operate on them once.
  2. Use before-save for same-record updates. Roughly 10× faster than after-save, and it avoids re-entrancy.
  3. Use after-save for related-record updates, async actions, or emails. Before-save can't do those safely.
  4. Add a fault path on every Get, Create, Update and Delete element. No fault path means silent failures.
  5. Set selective filters in Get Records. Pulling all 50,000 contacts when you need 12 is a guaranteed CPU-time blowup.
  6. Modularize with subflows. If logic is reused or runs longer than 15 elements, extract it.
  7. Avoid recursion. Use the $Flow.CurrentRecord recursion guard, or check stamp fields before re-firing.
  8. Use the Transform element instead of loops for collection-to-collection mapping (Spring '24+).
  9. Test with at least 200 records in a sandbox. The DML governor limit is 150, so you need to know where you stand.
  10. Document every element's description field. A future admin will thank you.
  11. Don't build one mega-flow per object. Split by trigger event (insert vs update) and concern (validation vs notification).
  12. Use platform events or queueable Apex for anything that can wait. Keep transactional flows under 1 second.

FAQ: Salesforce Flow best practices

What are the most important Salesforce Flow best practices?

Four rules carry most of the weight: (1) never put SOQL or DML inside a loop, (2) always add fault paths, (3) pick before-save or after-save based on which records you are updating, and (4) test with 200 bulk records before you deploy. The rest of the guidance follows from those.

When should I use before-save Flow vs after-save Flow?

Use before-save (Fast Field Update) when you only update fields on the same record that triggered the flow. It is roughly 10× faster because it skips a re-save cycle. Use after-save when you need to update related records, send emails, call Apex actions, or invoke approval processes.

How many records can a Salesforce Flow handle in one transaction?

Apex limits govern the transaction: 100 SOQL queries, 150 DML statements, and 10,000 DML rows. A bulkified Flow that processes 200 records in one batch stays inside those limits as long as it does not loop SOQL or DML. 200 is the standard "trigger batch" Salesforce uses internally.

Are Salesforce Flows replacing Apex triggers?

For most CRUD-style automation, yes. Salesforce recommends Flow over Workflow Rules and Process Builder, and Flow now performs well enough to replace many Apex triggers. Apex still wins for complex logic, callouts that need fine-grained control, and anything that requires dynamic SOQL or queueable patterns.

What is the biggest mistake admins make with Flow?

Putting a Get Records or Update Records element inside a loop. It looks logical ("for each item in the list, look up the related record") but it multiplies your SOQL queries by the loop count and crashes the moment a Data Loader job hits the trigger. Build collections, then operate on them outside the loop.

How do I debug a Salesforce Flow that fails silently?

Three steps: (1) add fault paths to every DML element so failures send an email or write to a custom Error Log object, (2) enable Flow debug logs from Setup → Process Automation → Process Automation Settings, (3) for triggered flows, check Setup → Apex Jobs (yes, even for Flows; they show up there) for unhandled exceptions.

Frequently asked questions

What are the most important Salesforce Flow best practices?

Four rules carry most of the weight: (1) never put SOQL or DML inside a loop, (2) always add fault paths, (3) pick before-save or after-save based on which records you are updating, and (4) test with 200 bulk records before you deploy. The rest of the guidance follows from those.

When should I use before-save Flow vs after-save Flow?

Use before-save (Fast Field Update) when you only update fields on the same record that triggered the flow. It is roughly 10x faster because it skips a re-save cycle. Use after-save when you need to update related records, send emails, call Apex actions, or invoke approval processes.

How many records can a Salesforce Flow handle in one transaction?

Apex limits govern the transaction: 100 SOQL queries, 150 DML statements, and 10,000 DML rows. A bulkified Flow that processes 200 records in one batch stays inside those limits as long as it does not loop SOQL or DML. 200 is the standard trigger batch Salesforce uses internally.

Are Salesforce Flows replacing Apex triggers?

For most CRUD-style automation, yes. Salesforce recommends Flow over Workflow Rules and Process Builder, and Flow now performs well enough to replace many Apex triggers. Apex still wins for complex logic, callouts that need fine-grained control, and anything that requires dynamic SOQL or queueable patterns.

What is the biggest mistake admins make with Flow?

Putting a Get Records or Update Records element inside a loop. It looks logical (for each item in the list, look up the related record) but it multiplies your SOQL queries by the loop count and crashes the moment a Data Loader job hits the trigger. Build collections, then operate on them outside the loop.

How do I debug a Salesforce Flow that fails silently?

Three steps: (1) add fault paths to every DML element so failures send an email or write to a custom Error Log object, (2) enable Flow debug logs from Setup → Process Automation → Process Automation Settings, (3) for triggered flows, check Setup → Apex Jobs (yes, even for Flows; they show up there) for unhandled exceptions.

Newsletter

One email every Tuesday

New guides, tool updates, and the release-note changes that break things.

No spam. Unsubscribe in one click.

Comments

Loading comments...

Leave a Comment