A schedule-triggered flow runs Salesforce automation at a set time and frequency, without needing a user or record change to fire it. It replaces scheduled actions from Workflow Rules and Process Builder with more flexible, low-code logic.
Workflow Rules and Process Builder are legacy automation tools, and Salesforce support for them ended after 2025. Plenty of admins still have scheduled logic sitting in one or the other, unmigrated. A schedule-triggered flow is the direct replacement and handles the same recurring tasks with more flexibility than either legacy tool offered. When planning integrations with external systems, Salesforce Integration Companies can also help ensure scheduled automation works reliably across connected platforms, while Service Cloud provides a natural use case for automating recurring customer-service processes.
Moving that logic over isn’t a simple copy-paste job. Schedule-triggered flows work on a different entry model, support formulas and decision branches natively, and need their own planning approach before you touch Flow Builder.
Get that planning wrong and you end up with a flow that either processes the wrong records or misses the ones that needed automating. So here, we’ll walk through it step by step, using one flow from start to finish.
Key Takeaways
- A schedule-triggered flow runs automatically at a set time and frequency, independent of any record change
- Each matching record creates its own flow interview
- It queries up to 50,000 records per run, well below batch Apex’s 50 million
- Testing should cover the warning, deactivation and no-action paths before activation.
- It runs as the Automated Process User unless you configure a different default Workflow User
How Does a Schedule-Triggered Flow Function in Salesforce?
The flow starts on its schedule and queries the object you specified, applying any entry conditions you set. Every record that matches gets its own separate run of the flow, called an interview.
From there, the flow can branch through Decision elements, apply formulas, send emails or update records, exactly like other flow types. The only difference is what triggers it, which is, a clock.
Salesforce monitors these runs from the Scheduled Jobs page in Setup, where you can see upcoming and completed executions. Each interview runs independently, so a failure on one record doesn’t stop the flow from processing the rest of the batch.
This is important for large data sets especially. If 400 users match your entry criteria, the flow creates 400 separate interviews and processes each one on its own.
When Should You Use a Schedule-Triggered Flow?
Anything that runs on a timer rather than in reaction to a record change is a candidate. A few examples come up constantly across different orgs:
- Deactivating users who haven’t logged in for a set number of days
- Sending reminder emails for cases or opportunities that have gone stale
- Cleaning up outdated lead or contact data on a recurring basis
- Notifying managers about high-value opportunities every week
- Running one-time bulk updates on existing records after adding a new field
- Sending recurring customer communications like birthday emails or renewal notices
- Flagging records that haven’t changed in a defined number of days
- Archiving closed cases that have sat inactive past a set threshold
For very large record volumes or more complex schedules, Batch Apex may be a better fit. Batch Apex handles up to 50 million records against a 50,000-record ceiling on schedule-triggered flows and supports scheduling patterns a flow can’t replicate on its own. For teams exploring additional automation capabilities, Salesforce AppExchange Development can also extend Salesforce with solutions that complement these workflows.
Choosing between the two comes down to scale and skillset. If your team is comfortable with declarative tools and the record count stays well under the flow limits, a schedule-triggered flow gets you there faster and without a developer.
Schedule-Triggered Flow vs Scheduled Path in Salesforce
Both features run automation after a delay, but they trigger differently.
| Factor | Schedule-Triggered Flow | Scheduled Path |
| What starts it | A defined schedule, set in advance | A record-triggered flow firing on a specific record |
| Scope of each run | Every matching record, all at once | Just the one record that triggered it, after a delay |
| Where it fits | Recurring batch checks across a data set | A delayed follow-up tied to one record’s change |
| A working example | Checking every inactive user each Saturday | Emailing a customer three days after their case closes |
Pick a Scheduled Path when the trigger is a single record event, like a case being created or an opportunity closing. Pick a schedule-triggered flow when the trigger is the clock itself, independent of any specific record’s history.
Mixing the two up leads to overcomplicated builds. Trying to force a Scheduled Path to handle recurring batch checks or trying to force a schedule-triggered flow to react to a single record event, usually means fighting the tool instead of using it as designed.
Schedule-Triggered Flow vs Workflow Rules and Process Builder
Both legacy tools handled scheduled actions with far more rigid trigger criteria, one more reason the migration is worth finishing now that support has ended.
| Feature | Schedule-Triggered Flow | Workflow Rules/Process Builder |
| Status | Current automation tool | Legacy, losing support |
| Trigger requirement | Only needs a start time | Needs specific record criteria |
| Logic options | Decisions, formulas, actions, updates | Limited conditional logic |
| Best use | New scheduled automation | Migration source only |
Any new scheduled automation should go into Flow. If you’re still running old Workflow Rules with scheduled actions, migrate them now rather than later, since Salesforce no longer patches or supports issues on either retired tool.
Migrating existing scheduled Workflow logic into a flow isn’t always a direct one-to-one conversion. Workflow Rules often trigger on record criteria that a schedule-triggered flow has to recreate through entry conditions and Decision elements instead, so budget time for the rebuild rather than treating it as a copy job.
Schedule-Triggered Flow Example: Deactivate Inactive Salesforce Users
A company with a rotating seasonal sales team wants inactive users cleaned up automatically. Temporary staff often stop working with the company but stay active in Salesforce, since nobody remembers to deactivate them manually.
The goal is to find active sales team users who haven’t logged in for over 60 days, send them a warning email and deactivate them if they still haven’t logged in a week later. Running this every Saturday at 3:00 PM keeps it clear of peak sales activity while giving users time to respond before deactivation.
| Path | Conditions | Action |
| Warning | Sales user, inactive for 60+ days, Warning Sent = False | Send email and set Warning Sent = True |
| Deactivation | Sales user, inactive for 60+ days, Warning Sent = True | Set Active = False |
| Reset | User logs in again | Set Warning Sent = False |
| No Action | User is active recently or not in sales group | Do nothing |
Prerequisites to Create a Schedule-Triggered Flow in Salesforce
Before opening Flow Builder, confirm you have the following in place:
- Manage Flows and Run Flows permissions, assigned through a Profile or Permission Set
- Access to Flow Builder inside Setup
- A clear, mapped-out business process for what you’re automating, ideally sketched on paper first
- A sandbox or test environment separate from production
- An email template and email alert ready, if the flow sends email
- A plan for any custom fields the logic needs, such as a checkbox to track sent warnings
Schedule-triggered flows touch live records the moment they’re activated and there’s no undo button once a batch of users gets deactivated by mistake.
How to Plan a Schedule-Triggered Flow Before Building
Planning on paper first prevents messy logic once you’re inside Flow Builder. Map the process using a simple who, when, what, how framework before touching the tool.
| What You’re Deciding | For This Flow |
| Users involved | Sales team members |
| Run schedule | Every Saturday at 3:00 PM |
| Core action | Warn inactive users first, deactivate if they still don’t log in |
| Identifying sales users | Profile name or another reliable user attribute |
| Checking inactivity | The Last Login field |
| Tracking warnings sent | A custom checkbox field |
| Deactivation trigger | Update the Active checkbox to false |
This table becomes your build checklist. Every row maps directly to a step in Flow Builder, so nothing gets designed on the fly halfway through.
It’s worth spending time on the “how” column specifically. Vague answers here, like “somehow check if they’re on sales,” turn into stalled logic once you’re staring at a Decision element with no clear field to reference.
How to Create a Schedule-Triggered Flow in Salesforce
Step 1: Open Flow Builder
Navigate to Setup and type Flow into the Quick Find box. Click Flows once it appears in the results, landing you on a list of every flow currently active in the org.
Click New Flow in the upper right. This opens Flow Builder in a new tab and prompts a choice between starting from scratch or using a template. Select Start From Scratch.
Step 2: Select Schedule-Triggered Flow
The next prompt asks for a flow type. Choose Schedule-Triggered Flow and click Create in the bottom right.
This choice is permanent for the flow itself. There’s no converting a schedule-triggered flow into a record-triggered one later without starting over.
Step 3: Set the Flow Schedule
The first thing Flow Builder asks for is a schedule:
- Pick a Saturday in the future as the start date
- Set the start time to 3:00 PM
- Set frequency to weekly
The start time follows the org’s default time zone. A time typed in as 3:00 PM fires at 3:00 PM wherever the org itself is set, which isn’t always the same zone the admin building it sits in.
Step 4: Choose the User Object and Entry Conditions
Click Choose Object and select User from the dropdown. Three things need to be true for a user to qualify downstream:
- The user is still active
- The user belongs to the sales team
- The user hasn’t logged in for over 60 days
Only the first is available as a direct entry condition. Set Condition Requirements to All Conditions Are Met (AND) and set the condition to User is Active.
Here’s the snag: searching “profile” in the entry criteria only surfaces ProfileId, no usable profile name field. Hard-coding an ID into the flow isn’t the goal, so that check moves into the Decision element instead.
Step 5: Create a Formula for the Last Login Check
Open the toolbox from the sidebar icon, click New Resource and select Formula as the Resource Type. Set the Data Type to Date/Time, then write a formula that takes the current date and time and subtracts 60 days from it.
Fill in the description field, name it something recognizable like nowMinus60 and click Done. This one formula gives every future run of the flow its own updated 60-day cutoff, recalculated fresh each time rather than pinned to a fixed date.
Step 6: Add a Warning Sent Checkbox
Open a second browser tab and leave Flow Builder running in the background. Go to Setup, Object Manager, User, Fields & Relationships and create a new Checkbox field.
- Give it a label and description
- Leave the default value as Unchecked
- Confirm it shows up on the user detail page under Setup, Users
Without this field, the flow has no way to separate a user who’s never been warned from one who has already had a chance to log back in.
Step 7: Add Decision Outcomes for Warning and Deactivation
Back in Flow Builder, add a Decision element with three outcomes, Warning, Deactivation and no action for anyone who logged in recently.
Warning outcome conditions:
- User belongs to the sales team (match Profile Name, using the arrow option so you’re not stuck with Profile ID)
- Last Login isn’t blank
- Last Login falls before nowMinus60
- Warning Sent equals False
Switch Condition Requirements to Custom Condition Logic is Met and enter:
(1 AND 2 AND 3 AND 4) OR (1 AND NOT(2) AND 4)
That second half catches users who’ve never logged in at all. A blank Last Login field would otherwise fail condition 3 and slip through uncaught.
Build the Deactivation outcome with the same four conditions, flipping only the last one to Warning Sent equals True. This outcome represents someone already warned who still hasn’t logged in a week later.
Step 8: Send a Warning Email
Two things happen under the Warning outcome. An email goes out and the checkbox updates. Start with the email:
- Open the App Launcher, go to Email Templates, click New Email Template and fill in the content
- Go to Setup, Email Alerts, New Email Alert, set Object to User and select the template
- Change recipient type to Email Field, add Email Field: Email, choose a From address and save
Back in Flow Builder, save first and refresh the page so the new alert appears as an option. Add an Action element under the Warning outcome, select the alert and pass Triggering User > User ID as the input.
A template and alert combo isn’t the only path here. A template ID can be referenced directly without a separate alert or a Text Template inside the Send Email action works depending on the setup.
Step 9: Update the Warning Sent Checkbox
Below the email action, add an Update Records element targeting the triggering user’s record and set Warning Sent to True.
This step is easy to skip past and the gap doesn’t surface right away. The email still sends fine either way and it’s only a week later, when the same user gets warned twice instead of deactivated, that the missing update shows up.
Step 10: Deactivate Inactive Users
Only one action lives under the Deactivation outcome. Add an Update Records element targeting the triggering user’s record and set IsActive to False.
Before this touches production, check what deactivation affects beyond the login itself:
- Record ownership
- Queue membership
- Any external system tied to that account
None of that resolves automatically just because a checkbox flipped.
Step 11: Add Fault Paths
Add fault paths to the email alert action and both Update Records actions. A fault path catches whatever breaks, a missing permission, a broken alert setup, a record that won’t save and keeps that single failure from taking down the entire scheduled run.
What happens next is a choice. Log the error to a custom object, send a notification email or flag the record for manual review.
Step 12: Save, Debug and Activate the Flow
Give the flow a name and description clear enough that someone else could understand its purpose without opening every element inside it. Click Debug and run it against a sample record, checking that both the Warning and Deactivation branches fire the way they’re supposed to.
Once that checks out, activate it. From here it runs on its own schedule, no one needs to remember to check for inactive users manually again.
Step 13: Reset the Warning Checkbox When a User Logs Back In
The flow built so far never clears Warning Sent once it’s checked, so a user who logs back in after receiving a warning still carries that flag forward. If they go inactive again months later, the flow skips straight to deactivation instead of warning them a second time.
Fixing this needs a second, separate flow, one that fires on a completely different trigger:
- Build a record-triggered flow on the User object, set to fire when a record is updated
- Set the entry condition to run only when Last Login changes and is no longer blank
- Add an Update Records element that sets Warning Sent back to False whenever it currently reads True
This flow runs independently of the schedule-triggered one. It reacts the moment a user logs in, rather than waiting for the next Saturday run, so the checkbox resets as soon as it’s no longer accurate.
Without this second flow, Warning Sent behaves correctly exactly once per user. With it, the whole system holds up across as many inactivity cycles as a user goes through.
How to Test a Schedule-Triggered Flow in Salesforce
Testing a schedule-triggered flow works differently than testing a record-triggered flow, since you can’t manually pick which record debug mode uses. Debug mode automatically selects the oldest record matching your entry criteria, which may not be the test record you want to check.
For more control, route the record into a subflow, since subflows let you debug with a specific record instead of whatever happens to be oldest. Build a lightweight autolaunched flow that handles the logic, then have your schedule-triggered flow call it, passing along the record you want tested.
Always test in a sandbox first, confirm both decision branches fire correctly and only activate in production once the logic holds up. Create a handful of test users with different Last Login dates and Warning Sent values, so you can verify the Warning outcome, the Deactivation outcome and the No Action outcome all behave exactly as designed for High-Tech businesses.
Schedule-Triggered Flow Considerations and Limits
Salesforce caps schedule-triggered flows below what batch Apex can handle:
| Limit | Schedule-Triggered Flow | Batch Apex |
| Records queried | Up to 50,000 | Up to 50 million |
| Max batch size | 200 | 2,000 |
| Interviews per 24 hours | 250,000 or licenses × 200, whichever is greater | Not applicable |
A few other behaviors are important for planning. Deleting a scheduled flow from the Scheduled Jobs page cancels all future runs and you have to deactivate and reactivate it to resume. A one-time flow scheduled for a date that’s already passed simply won’t run and Salesforce won’t warn you before you try to activate it that way.
If your org has multiple scheduled flows hitting the same object around the same time, review them together. Two flows updating the same records within seconds of each other can create record-locking conflicts that are hard to diagnose after the fact.
Best Practices for Schedule-Triggered Flows in Salesforce
A well-built schedule-triggered flow holds up long after the admin who created it moves on. These habits keep it stable, traceable and safe to hand off:
- Build and test in a sandbox before touching production data
- Keep entry criteria narrow so the flow doesn’t process more records than intended
- Avoid hard-coding profile or record IDs, since they break across sandboxes and orgs
- Add fault paths on every email and update action
- Document the flow’s purpose and schedule directly in its description field
- Review scheduled flow run times against other automation to avoid record-locking conflicts
- Name checkbox and tracking fields clearly, since future admins will need to understand their purpose without reading the flow itself
Common Schedule-Triggered Flow Mistakes to Avoid
Most schedule-triggered flow failures trace back to a handful of repeat mistakes. Watch for these before they cost you a bad production run:
- Skipping the planning step and building decision logic directly in Flow Builder
- Using overly broad entry criteria that pull in unintended records
- Forgetting users or records with blank fields, like a never-logged-in user
- Leaving out a way to track whether an action, like a warning email, already ran
- Testing changes directly in production instead of a sandbox
- Hardcoding a profile ID instead of referencing the profile name
- Deactivating users without checking downstream effects on ownership, queues or integrations
Conclusion
A schedule-triggered flow turns a recurring manual task into something that just runs, quietly, every week, without anyone remembering to do it by hand.
Start in a sandbox. Map your who, when, what and how before opening Flow Builder, then build only after the logic is clear.
Frequently Asked Questions
How often can a schedule-triggered flow run and what scheduling options are available?
A schedule-triggered flow can run once, daily or weekly, based on the frequency you set on the Start element. You also choose the exact start date and time, which the flow uses as its baseline for repeat runs. For anything more granular than these three options, a scheduled Apex job typically fills the gap instead.
How do I test and debug a schedule-triggered flow before activating it
Debug mode automatically pulls the oldest record that matches your entry criteria, so you can’t manually select a test record the way you can with a record-triggered flow. For more precise testing, route the logic into a subflow and debug that subflow with a specific record instead. Always confirm both the success and failure paths in a sandbox before moving to production.
Can schedule-triggered flows handle large data volumes and what are the governor limits?
A schedule-triggered flow can query up to 50,000 records per run and process a maximum batch size of 200 at a time. It can also create up to 250,000 flow interviews in a 24-hour period or your org’s user license count multiplied by 200, whichever is higher. For anything beyond these limits, batch Apex is the better tool, since it can query up to 50 million records.
What user context and permissions do schedule-triggered flows run under?
Schedule-triggered flows run as the Automated Process User by default. If you want completed actions to display under your own name instead, configure the Default Workflow User setting in Process Automation Settings.
How are errors logged and how do I retry failed records in a scheduled flow?
Nothing retries automatically once a fault path catches an error. Log the failed record ID and the error reason somewhere you’ll check, a custom object works or a simple email alert. From there you’re back to fixing the root cause and re-running the flow by hand or setting up a small cleanup flow that revisits anything still flagged.






