How do I schedule APEX programmatically?

Apex Scheduling

How do I schedule APEX programmatically?

Waitโ€ฆ What even is it?

Scheduled APEX is great. In fact, in the Salesforce world itโ€™s the only way to queue up code to be run repeatedly at a set time of day / week / month / year. Itโ€™s like a cron job. It even uses a cron-like notation. Suppose you want to run a monthly job on the first of every month that loads any Opportunities that are open but have passed their close date, and for each one creates a high priority task for its owner requesting an update. This would be a perfect time to use Scheduled Apex. In this case youโ€™d probably want to marry it with Batchable Apex too, incidentally, to avoid limits.

A scheduled job can be enqueued via the setup menu, or via code. This is about doing it via code. Why do it like this? Because if you do it in the setup menu you have to specify an end date so you canโ€™t schedule a job indefinitely.

I havenโ€™t created my schedulable class yet, can you help?

Yes, you need to create a class that implements the Schedulable interface. We could show you, but Salesforce has already done a good job of thatโ€ฆ thereโ€™s good documentation on doing that in the Apex Developer Guide, and thereโ€™s a Trailhead Module that covers it.

Get to the point, how do I schedule it?

Well, according to Salesforce, something like this:

MySchedulableClass sched = new MySchedulableClass();
String cronExp = '0 30 8 1 * * *';  // 8:30am every 1st day of the month 
String jobID = System.schedule('Something descriptive', cronExp, sched);

This is great, open up your Developer Console, pop that into anonymous APEX and away you go. The Salesforce docs give you a lot of warnings about being careful where you call this code, particularly with Triggers, as you could wind up running the same thing multiple times which would be a Bad Thingโ„ข. So donโ€™t, especially if this is a repeating task, just do it in the Developer Console.

Thatโ€™s quite a bit to remember and type correctly, got anything better?

Funny you should ask. Not only is this a fair bit to type, you may also find yourself having to remember it quite often, as youโ€™ll see in a minute. First though, hereโ€™s the pattern we use for Schedulable classes (batchable class example included for completeness):

global class MyJobSchedulable implements Schedulable {
  /*
    Run at 8:30 am on the first of every month. Remember this is
    Scheduled in the Userโ€™s timezone who schedules the job, not UTC
  */
  public static final String CRON_EXPR = โ€˜0 30 8 1 * * *โ€™;

  /*
    Call this from Anonymous Apex to schedule at the default regularity
  */
  global static String scheduleIt() {
    MyJobSchedulable job = new MyJobSchedulable();
    return System.schedule(โ€˜Something Descriptiveโ€™, CRON_EXPR, job);
  }
  
  global void execute(SchedulableContext sc) {
    // This is good practice if you are likely to be processing a
    // lot of records at a time
    MyJobBatchable b = new MyJobBatchable();
    Database.executeBatch(b);
  }
}

With this setup you can avoid having to remember all the incantations, and simply run the following in anonymous apex instead

MyJobSchedulable.scheduleIt();

Done. Easy. The something descriptive string is shown in the scheduled jobs list so make it something that summarises to future you what it is your job is doing.

Whatโ€™s that about remembering the incantation to schedule my job?

Hereโ€™s one of the gotchas of scheduled Apex jobs:

You cannot release updated versions of any code that is used by your scheduled job without first deleting your scheduled job.

This includes the Schedulable class itself, the Batchable class (if youโ€™re using one) and any service classes that you might be delegating the work out to. If you like to create reusable, shared code, to reduce duplication and the risk of code rot, then this is likely to be a problem for you. This makes having a simple to remember, difficult to get wrong pattern (like the above) for scheduling your job almost critical.

Help, my scheduled job is running at the wrong time whatโ€™s going on?

Firstly, Salesforce makes no promises that your scheduled job will run at exactly the time specified (from the docs):

โ€œSalesforce schedules the class for execution at the specified time. Actual execution may be delayed based on service availability.โ€

If this isnโ€™t the case, then itโ€™s likely that the user you used to schedule the job has a different time zone set on their profile to the one you are expecting your job to run in. For example, If your user has the GMT time zone set, then the example above will run at 8:30am GMT. If you are in the USA, on EST the job will run at 3:30am. This gets EVEN more confused based on daylight savings. But I wonโ€™t go into that here because time zones are hard

Tom Blockley, Salesforce DeveloperThanks!

Tom

Work with Desynit

Looking for exceptional, professional Salesforce support?

Our independent tech team has been servicing enterprise clients for over 15 years from our HQ in Bristol, UK. Let’s see how we can work together and get the most out of your Salesforce implementation.