Serverless - Scheduled Lambdas

Often, you require your function to be invoked at fixed intervals. It can be once a day, twice a week, once a minute during weekdays, and so on.Serverless provides two types of events to invoke functions at fixed frequencies. They are cron events and rate events.

Cron Event

The cron event has much more flexibility than the rate event. The only downside is that it is not as straightforward to understand as the rate event. The syntax of the cron expression is defined in the AWS documentation

cron(minutes hours day-of-month month day-of-week year)

As can be seen, the cron expression consists of 6 fields. Each field can take in some accepted values, and some, as AWS calls them, wildcards.

Let's have a look at the accepted values first −

  • minutes − 0-59

  • hours − 0-23

  • day-of-month − 1-31

  • month − 1-12 or JAN-DEC

  • day-of-week − 1-7 or SUN-SAT

  • year − 1970-2199

Now that the accepted values are clear, let us have a look at the wildcards. There are a total of 8 wildcards possible in the cron expression (some allowed for all 6 fields and some only for specific fields). Listing them down here −

  • * (asterisk, allowed for all 6 fields) − This is the most popular wildcard. It simply says that all values of the field are included. A * in the hours field would mean that the cron would run every hour. A * in the day-of-month field would mean that the cron will run every day.

  • , (comma, allowed for all 6 fields) − This is used to specify more than one value. For example. If you want your cron to run at the 5th, 7th, and 9th minute of every hour, your minute field would look like 5,7,9.Similarly, MON,TUE,WED,THU,FRI in the day-of-week field could mean that the cron should run only on weekdays.

  • - (dash, allowed for all 6 fields) − This wildcard specifies ranges. In the previous wildcard example, in order to specify weekdays, instead of specifying 5 comma-separated-values, we could have simply written MON-FRI

  • ? (question mark, only allowed for day-of-month and day-of-week) − This is like a don't-care wildcard. If you have specified MON in the day-of-week field, you don't care what date Monday falls on. Therefore, you will enter ? in place of day-of-month. Similarly, if you want the cron to run on the 5th of every month, you will enter 5 in the day-of-month field and ? in the day-of-week field, because you don't care what the day is on the 5th of every month. Note that the AWS documentation clearly states that you cannot use * for both day-of-week and day-of-month fields. If you use * for one, you have to use ? for the other

  • / (forward slash, allowed for the 5 fields except for day-of-month) − This field specifies increments. If you enter 0/2 in the hours field, this cron will run every even hour (0, 0+2, 0+2+2, and so on). If you specify 1/2 in the hours field, this cron will run every odd hour (1, 1+2, 1+2+2, and so on). As you would have guessed, the value preceding the / is the starting value and the value succeeding it defines the increment.

  • L (only allowed for day-of-month and day-of-week) − Specifies the last day of the month or the last day of the week

  • W (only allowed for day-of-month) − This specifies a weekday (Monday to Friday) nearest to that specific day of the month. So if you specify 8W in the day-of-month field, and it corresponds to a weekday, say Tuesday, then the cron will fire on 8th itself. But if 8 corresponds to a weekend day, say Saturday, then the cron will be triggered on 7th (Friday). If 8th corresponds to Sunday, then the cron will fire on 9th (Monday). This is one of the least used wildcards.

  • # (only allowed for day-of-week) − This is a very special wildcard, best understood by an example. Say you want a cron to run on Mother's day. Now, Mother's day falls on 2nd Sunday of May every year.Therefore, your month field would contain MAY or 5. But how do you specify 2nd Sunday? Come in the hashtag. The expression is 0#2. The value preceding the wildcard is the day of the week (0 for Sunday,1 for Monday, and so on). The value succeeding the wildcard specifies the occurrence. Therefore, 2 here refers to the 2nd occurrence of Sunday or the second Sunday.

Now, to define a cron trigger for your lambda function, all you need to do is specify the cron expression within the events key in the function in serverless.yml.

      handler: handler.hello
         - schedule: cron(10 03 * * ? *) #run at 03:10 (UTC) every day. 

Some Examples

Given below are some examples of cron expressions −

  • cron(30 15 ? * MON-FRI *) − Triggered at 15:30 (UTC) on every weekday

  • cron(0 9 ? 6 0#3 *) − Triggered at 09:00 (UTC) on the third Sunday of June (Father's Day)

  • cron(0/15 * ? * MON *) − Triggered every 15 minutes on Mondays

  • cron(0/30 9-18 ? * MON-FRI *) − Triggered every 30 minutes from 9 AM to 5:30 PM on weekdays (corresponding to office hours at several places)

Rate Event

This is much more straightforward compared to cron expressions. The syntax is simply rate(value unit). For example, rate(5 minutes).

The value can be any positive integer and the allowed units are minute(s), hour(s), day(s).

Defining a rate trigger for your lambda function is similar to defining a cron trigger.

      handler: handler.hello
         - schedule: rate(10 minutes) #run every 10 minutes

Some Examples

  • rate(2 hours) − Triggered every 2 hours

  • rate(1 day) − Triggered every day (at 00:00 UTC)

  • rate(90 minutes) − Triggered every 90 minutes

As you would have realized, the simplicity of the rate expression comes at the price of reduced flexibility. You can use rate for lambdas running every N minutes/hours/days. To do anything more complex, like triggering your lambda only on the weekdays, you have to use a cron expression.

Please note that if your cron expression somehow results in trigger times of less than a minute, it won't be supported.