In the Winter ’20 release, Salesforce introduces scheduled flows. Now, you can schedule flows to run create scheduled batch jobs declaratively, specifying when the date/time the flow will run and the frequency of the scheduled flow (once, daily, weekly and monthly) and provide additional filter conditions for the records.
Here are some things to note with scheduled flows:
- The start time of the scheduled flow reflects the time zone of the org (look a the Company Information screen). However, when you configure the flow, the start time will reflect the time zone of your user record. So, if your time zone is different than that of the org, account for that when you configure the start time in your scheduled flow.
- Scheduled flows will run under the user called “Automated Process User.”
- For conditions, when using date or date/time filters, you cannot currently use a formula. It needs to be *gasp* a hardcoded date or date/time. As a workaround, you need to create a custom field that has the date or date/time stamped so you can use it as a filter condition.
- Formula references do not work in filter conditions.
- If you need to reference attributes associated to the record in the scheduled flow, use the global variable called “$Record.”
- You cannot debug scheduled flows (i.e. use the Debug feature in Flow Builder). They are logged in debug logs. You can also create a version of your scheduled flow as a non-scheduled flow to use the Flow Builder debug feature.
- Once you create your scheduled flow, you will see it listed in the Scheduled Jobs page in Setup.
- According to Salesforce, scheduled flow limits are the same as Apex Scheduler limits.
Fictional Business Use Case: Addison Dogster is the system administrator at Universal Containers. Addison received a requirement that for any contact that has “Jennifer Lee” as the assistant and the contact level is set to “Primary,” that Salesforce creates a task and updates the Description field on the contact record to read “This was updated by the scheduled flow.” This process will only run daily at 2pm.
Solution: Addison knows that this is a perfect candidate for the new scheduled flow feature where she can build a batch job using clicks, not code. She can set the schedule to run daily at 2pm and only for Contact records where the Assistant Name = “Jennifer Lee” and the Level = “Primary.”
However, she only wants it to run for Contact records that have not be processed previously versus having this run every day for the same records that meet the filter condition. Since there is no “IsChanged” feature that can be used in the filter condition, Addison will create a custom field called Trigger Scheduled Flow? with picklist values “Do Not Trigger” and “Trigger”, and create a process that will stamp this field with “Trigger” when the criteria condition is met for use in the scheduled flow. However, once the record is processed in the scheduled flow, we want to clear the record from being picked up by updating the Trigger Scheduled Flow? field to “Do Not Trigger.”
Quick Steps:
Pre-requisites:
- Create a custom picklist field to determine whether or not to kick off the scheduled flow.
1.Let’s create the process that stamps the “Trigger Scheduled Flow?” custom field for use in the scheduled flow. In Setup, go to Create | Workflows & Approvals | Process Builder in Salesforce Classic or Process Automation | Process Builder in Lightning Experience.
Note: This process does not follow the best practice of one process per object. For the purposes of this blog post, we are specifically naming this process to match its purpose “Stamp Contact Record.”
A. Provide a process name “Stamp Contact Record,”API name (auto-populated via tab key), description and select the process starts when “A record changes.”
Best practice tip: Don’t forget to provide a description so you and other/future admins know what this process is for.
B. Choose “Contact” as the object and to start the process when “when a record is created or edited.”
C. Specify the first criteria “Assistant Name and Level = Primary” where the condition will use the formula is:
(ISCHANGED ([Contact].AssistantName ) || ISCHANGED ([Contact].Level__c)|| ISNEW())
&& [Contact].AssistantName = “Jennifer Lee”
&& ISPICKVAL([Contact].Level__c, “Primary”)
We have to use the formula here because you cannot use the point and click to specify a new record. This formula will evaluate to true if (the Contact’s Assistant Name is changed OR the Level has changed OR the record is new) AND the Assistant’s Name is “Jennifer Lee” and the Level is “Primary.”
For the immediate action, we are going to update the record on the Contact Object that started the process:
- Action Name: Stamp Record
- Record: [Contact]
- Criteria for Updating Records: Updated records meets all conditions
- Set new field values for the records you update
- Field: Trigger Scheduled Flow?
- Operator: Formula
- Value: IF (
([Contact].AssistantName = “Jennifer Lee”
&& ISPICKVAL([Contact].Level__c, “Primary”)), “Trigger”, “Do Not Trigger”
)
Note: This formula says if the Contact Assistant Name is “Jennifer Lee” and the Level is “Primary,” then select the “Trigger” picklist value. Otherwise, select the “Do Not Trigger” value.
D. Activate the process.
2. Now, let’s create the flow. In Setup, for Classic, go to Create | Workflows & Approvals | Flows. In Lightning Experience, it is found under Process Automation | Flows.
Here is the flow we are going to create.
- This will start on a specific day (I picked the day I created the flow) at 2pm daily with the filter conditions: Assistant Name = “Jennifer Lee” and Level =”Primary” and the Trigger Scheduled Flow? = “Trigger.”
- We will create a task associated assigned to the contact owner and associated to the contact and account.
- Lastly, we will update the contact record’s description field in the scheduled flow to “This was updated by the scheduled flow.” and the Scheduled_Flow_Trigger__c to “Do Not Trigger.” The last part is important. By updating the Scheduled_Flow_Trigger__c field, the contact record will not be picked up in the next scheduled flow unless changes were actively made to the record where the filter conditions are met again.
A. Click the “New Flow” button, click the “Autolaunched Flow,” and click on the Create button.
B. Let’s set the schedule flow information by double-clicking on the Start button.
- Flow Trigger: Schedule
- Start Date: Sep 25, 2019
- Start Time: 2:00 PM
- Frequency: Daily
- Object: Contact
- Conditions are Met (AND)
- AssistantName Equals Jennifer Lee
- Level__c Equals Primary
- Scheduled_Flow_Trigger__c Equals Trigger
C. Create a Formula Resource that will store the formula to set the activity date on the Task record to 3 days from today. Go to the Manager tab, click on “New Resource.” Then provide the following:
- Resource Type: Formula
- API Name: TodayPlus3
- Data Type: Date
- Formula: today()+3
D. Next, we will add a Create Records flow element to create the new task assigned to the contact owner and associated to the contact and the contact’s account. In order to access the contact record’s field attributes in this flow, use the new $Record global variable. It is essentially a sobject record that gives you access to the field attributes.
Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.
Configure the Create Records flow element to the following:
- How Many Records to Create: One
- How to Set the Record Fields: Use separate variables, resources and literal values
- Object: Task
- Set Field Values for the Task:
- ActivityDate: {!TodayPlus3}
- OwnerId: ${Record.OwnerId}
- Priority: Normal
- Status: Not Started
- Subject: This is a auto-generated task for Primary Contacts
- WhatId: {!$Record.AccountId}
- WhoId: {!$Record.Id}
E. Now, we will use a Update Records flow element to update the Description and Trigger Scheduled Flow? fields on the contact record.
Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.
Set the information on the Update Records flow element:
- How to Find Record to Update and Set Their Values: Specify conditions to identify records, and set fields individually
- Object: Contact
- Filter Contact Records to:
- Condition Requirements: Conditions are Met
- Id Equals {!Record.Id} [Note: This can be found under Global Variables]
View Image Full Screen
-
Set Field Values for the Contact Records:
- Description: This was updated by the scheduled flow.
- Scheduled_Flow_Trigger__c: Do Not Trigger
F. Connect the flow elements to match the below…
G. Save/Save As with the flow name and a description about the flow.
Best practice tip: Provide a description so you and other/future admins know what this flow is used for.
H. Click the “Activate” button to activate the flow. [This is a new Winter ’20 feature!]
That’s it! You’ve configured the changes.
Now, before you deploy the changes to Production, don’t forget to test your configuration changes.
- Make updates to the contact record and wait until the next scheduled date/time. For testing purposes, I schedule the flow to run in the next 15 mins from when I updated the contact records.
- Once the scheduled flow ran, verify that the task was created with the appropriate attributes and the contact record was updated accordingly. Verify this for several contact records.
Deployment Notes/Tips:
- The flow, process and custom field can be deployed to Production in a change set (or can be deployed using a tool such as Metazao’s Snapshot).
- Don’t forget to update the custom field’s FLS for the profiles that will use the flow.
- You will find the flow in a change set under the Flow Definition component type.
- Activate the flow post deployment as they deploy inactive in Production, unless with Winter ’19, you have opted in on the Process Automation Settings screen, to “Deploy processes and flows as active.” NOTE: With this change, in order to successfully deploy a process or flow, your org’s Apex tests must launch at least 75% of the total number of active processes and active autolaunched flows in your org.
Hi Jennifer – This one is very detailed information. able to learn a new concept today. Thanks.
LikeLike
Awesome!
LikeLike
Hi Jennifer,
How does this solution work with the flow limit of 2 000 elements executed at runtime knowing that we have 2 elements here (Is max records to be processed here 1000? or the Apex limit of 250K or 200 x nb users whicheverr is higher )
Thanks
Jacques
LikeLike
Hi Jennifer. This has the potential for multiple applications, thank you! Also, what tool or app are you using to embed the video clips into your post? Thanks, Eddie
LikeLike
You’re welcome
LikeLike
I use Licecap for the animated gifs and SnagIt for any videos
LikeLike
I was told it works like apex batches. I have not tested this put myself.
LikeLike
NP
LikeLike
Thanks Jennifer
LikeLike
Hi Jennifer,
Very good and detailed information about scheduled flows..However ,while doing you use case I exactly copied your formula in the process builder but it’s giving syntax error..Both the formulas are giving syntax error.Any Idea.
(ISCHANGED ([Contact].AssistantName ) || ISCHANGED ([Contact].Level__c)|| ISNEW())
&& [Contact].AssistantName = “Jennifer Lee”
&& ISPICKVAL([Contact].Level__c, “Primary”)
The formula expression is invalid: Syntax error
The formula expression is invalid: Syntax error
LikeLike
What do you mean by both formulas?
This is the same formula I copied from the criteria node for the process. I did not get any syntax errors. Sorry.
(ISCHANGED ([Contact].AssistantName ) || ISCHANGED ([Contact].Level__c)|| ISNEW())
&& [Contact].AssistantName = “Jennifer Lee”
&& ISPICKVAL([Contact].Level__c, “Primary”)
LikeLike
Has anyone tried it in live projects yet? How does it compare to the Batch apex?
LikeLike
Hi Jen,
Where is the option to schedule the flow monthly? I can only see once, daily, and weekly but no monthly – thanks
Jay
LikeLike
Hi Jennifer … hope you are keeping safe and well. I note that the scheduler won’t allow any sort of formula as a filter and you suggested a work around
“Formula references do not work in filter conditions.
If you need to reference attributes associated to the record in the scheduled flow, use the global variable called $Record.”
So I created an Opportunity field and entered a date (not a formula) for testing.
I get the error:
The Start element can’t have a record filter condition that references a resource or element. Remove the condition that contains the unsupported value “$Record.Renewal60Days__c” or replace it with a literal value.
I am trying to get a Flow to send an email 60 days prior to the Contract End Date
Any suggestions?
LikeLike
Excellent information! Can you use a scheduled flow to move stale reports (last run date over a year ago) to an Archived folder or just delete the report?
LikeLike
Thanks. I have not tried doing anything in flow with reports so I don’t know what is possible. I’d say, give it a try and see.
LikeLike
You can’t reference a field in the start element. It is a hard coded date. Instead, like in my blog post, have something stamp a processing field to true and those records are picked up to be processed and then remember to unchecked the processing field. You can also use process builder to create a process that sends the email that is x number of days from a specific field. Did you try that?
LikeLike
Hmm, could’ve sworn the option was there before but I no longer see it. Perhaps Salesforce removed it?
LikeLike
I figured out a way that seems to work using PB and Flows. PB schedules a Flow and that way if something changes in the opportunity that moves it outside the Process criteria, the Flow won’t run. I was possibly just over thinking it because I had to account for pre-existing records as well as new. Thanks for getting back to me. keep up the good work 😉
LikeLike
I would recommend using an immediate action that invokes the flow. The flow has the wait element and then add a decision for it to check that the criteria still stands and then run the rest of the flow. We’re run into some issues with process and scheduled flows too and that’s what Salesforce recommended we do to work around this issue. Hope that helps.
LikeLike
Thanks. I have used a Decision to check it still meets the criteria. Are you recommending a Pause prior to the decision?
LikeLike
If you want it to be a scheduled action. There are times in which you tweak the process criteria but scheduled actions continue to fire off of your previous process criteria.
LikeLike
Is there any way to schedule time-triggered email sends on monthly for a batch of records? Email would be going to community license users.
LikeLike
The scheduled flow can only be scheduled one time, daily or weekly.
LikeLike
Hi Jen,
Is it possible to have the flow daily process to only run on weekdays, and not weekends? Can we have it work with our internal org’s business hours?
LikeLike
You can set it to run daily only if a flag evaluates to true – which you can set the field to true for weekdays and false for weekends.
LikeLike
Hi
What is the limit to process the number of records for auto launch flow for delete operation.
I’ve the situation that our auto launch flow runs on weekly and will have more that 10k records to delete. And for the first time running will have millions of records to delete.
Can we set the batch size for each transaction?
Do Auto launch flow runs until all records are completed like batch?
LikeLike
Declarative automation is not the right solution in this case. You should use apex.
LikeLike
Thank you Jenwlee
LikeLike
Thanks for the tutorial! This was super helpful!
LikeLike
You’re most welcome!
LikeLike
Hi Jen, thanks for the great post.
I’m trying to schedule my flow for weekdays only. I have a checkbox on the account object to determine if it’s a weekday, but I’m having trouble evaluating it. Any suggestions?
LikeLike
I’m not sure I understand what the issue is that you are running into. Can you elaborate a bit more?
LikeLike
Hi Jen,
I have to create a schedule flow to send an email to the user’s who have not logged in the last 10 days.Will have to send another email in 15 days if they fail to login.
Could u please look at the steps below.
Here are the steps:-
1)Queried all active users and stored their last name,email in the collection variable of type User.
2)Loop thorugh the user records.
3)Created a variable to store the difference between Today()-last login date.
VarTotalDays=Today()-last LoginDate
4)Decision:-if (VarTotalDays<=10)
then send an email to the user
Will this formula be or Do i need to make some changes to it
Thank's
LikeLike
I’m not sure if you had more text but it cut off at 4)Decision:-if (VarTotalDays. Sorry. If there is a character limitation here, I would recommend reaching out to me on the Trailblazer Community. Thanks.
LikeLike
Hi Jen,
I’m trying to create a new task using flow. The Lookup component that I’m using shows “Object Task is not supported in UI API” while testing in debug mode. Have you ever had that error before?
LikeLike
What do you mean by lookup component in debug mode? You aren’t able to select a record when debugging a scheduled flow.
LikeLike
Hi Jen,
I am running into a similar issue that Nit posted on 3/5/20. I am getting “The formula expression is invalid: Syntax error. I am using it as one formula for clarification. Here is the formula that I copied from you:
(ISCHANGED ([Contact].AssistantName ) || ISCHANGED ([Contact].Level__c)|| ISNEW())
&& [Contact].AssistantName = “Jennifer Lee”
&& ISPICKVAL([Contact].Level__c, “Primary”)
Any thoughts?
Mike Di Rauso
LikeLike
It is probably the quotes. These are curly quotes. Change them the straight quotes.
LikeLike
Thanks Jenwlee for your expertise!
Not using formula when filtering with date/time, and not referencing a formula field? That’s a very big limitation. And you post is the only place I saw this mentioned. Is this still true?
That would explain why my Flow doesn’t work. Since I need to reference dates that are relative, i use custom formula fields, but if this cannot work… To go around the limitation, I would have to create text fields for each formula date fields, and update them daily, for all my accounts. yikes.
Any advice would be super appreciated. Thanks again for putting this up!
LikeLike
I would recommend testing this out on one record and seeing the behavior. Note: if one of the records in your collection fails to update, everything in that scheduled flow fails.
LikeLike