Optimizing Record-triggered flows for performance
If you’re building automation today, you’re almost certainly using Record-triggered flows to get the job done. But I’ve noticed a lot of people still struggle with the “When to Run the Flow” setting. It’s one of those things that seems small, but picking the wrong option can lead to sluggish page loads or weird data issues that are a pain to debug later.
In my experience, most teams default to After-Save because it feels safer. They want access to everything. But that’s usually a mistake. If you’re just updating a field on the same record that triggered the flow, you’re wasting resources by waiting until after the record hits the database. Let’s break down how to choose the right tool for the job.
Record-triggered flows: When to use Before-Save vs After-Save
The short answer? If you’re updating the record itself, go Before-Save. If you’re doing literally anything else, go After-Save. But since nothing in Salesforce is ever that simple, we need to look at the “why” behind those choices. Following best practices for Salesforce Flow means understanding the order of execution.
The “Fast Field Update” (Before-Save)
Before-Save flows are incredibly fast. Why? Because they run before the record is actually saved to the database. Think of it like a quick check-and-fix before the mailman picks up the envelope. Since the record isn’t “committed” yet, the flow can swap out values on the fly without needing a separate update command. This saves a ton of CPU time and avoids the whole “re-triggering” mess that happens with older workflow rules or Process Builder.
I’ve seen teams try to use these for everything, but they have limits. You can’t update related records, you can’t send emails, and you can’t call external systems. It’s strictly for “on-record” work like normalizing phone numbers or setting a default category based on an Amount field.
The “Actions and Related Records” (After-Save)
Now, After-Save is where the heavy lifting happens. These Record-triggered flows run after the record is committed. This is crucial because it’s the only way you’ll get a Record ID for a brand-new record. If you need to create a Task, update a parent Account, or send a Slack notification, this is your only option.
One thing that trips people up is the performance cost. Because the record is already saved, any update the flow makes counts as a second save operation. If you aren’t careful with bulk record processing in Flows, you’ll hit governor limits faster than you’d think. It’s also where you’re more likely to run into recursion issues if your flow updates something that triggers another flow.
Pro Tip: If you find yourself writing complex logic that needs to decide between Flow and code, check out this guide on Apex vs Flow. Sometimes a trigger is still the better move for high-volume objects.
How they stack up: A quick comparison
Here is a simple way to look at the differences. I usually keep this mental checklist when I’m starting a new project.
| Feature | Before-Save (Fast Update) | After-Save (Actions) |
|---|---|---|
| Speed | Lightning fast (no extra DML) | Slower (requires extra DML) |
| Record ID | Available (usually), but not final | Fully available and committed |
| Related Records | Read-only access only | Can create/update/delete |
| Emails & Actions | Not supported | Fully supported |
| External Callouts | No | Yes (via Async paths) |
Real-world scenarios
Let’s look at how this actually plays out in a real org. I recently worked on a project where the client wanted to automate their Lead intake. Here’s how we split the work between the two types of Record-triggered flows.
Scenario 1: The Before-Save approach
When a Lead comes in, we needed to make sure the “Source” field was capitalized and set a “Rating” based on the industry. Since we only cared about the Lead record itself, we used a Before-Save flow.
// Trigger: Lead is created or updated
// Logic:
If (Lead.Industry == 'Technology') {
Lead.Rating = 'Hot';
}
Lead.LeadSource = UpperCase(Lead.LeadSource);
// Result: No extra DML. The save finishes with these values already set.
Scenario 2: The After-Save approach
Once that Lead is saved, the sales manager wanted a Task created for the owner and a notification sent to a specific Slack channel. This requires a Record ID and an external action, so it has to be After-Save.
// Trigger: Lead is created
// Action 1: Create Record (Task)
// Action 2: Send Custom Notification or Slack Action
// Result: The Lead exists in the DB, so the Task can be linked to it correctly.
Key Takeaways for Record-triggered flows
- Start with Before-Save: Always ask yourself “Can I do this with a Fast Field Update?” if the answer is yes, don’t even look at After-Save.
- Mind the ID: If your logic relies on a Record ID for a new record (like for a junction object), you must use After-Save.
- Watch your limits: After-Save flows are more expensive in terms of CPU time. If you have a lot of them on one object, you’ll feel it.
- Avoid recursion: Use entry conditions. Honestly, most teams get this wrong. Don’t let your flow run unless the specific fields you care about have actually changed.
At the end of the day, it’s about being intentional. Don’t just click “Actions and Related Records” because it’s the default. Take ten seconds to think about whether you’re just updating the triggering record or reaching out to the rest of the org. Your users (and your future self) will thank you for the performance boost.








Leave a Reply