In some of my recent articles I have been posting about how to make use of AWS EventBridge – a serverless messaging event bus – in applications that can benefit from its loosely coupled event driven features – such as this post on designing an order fulfillment system or this other article on using EventBridge in a notification system. Both of those examples make active use of a custom EventBridge bus to have components actively publish and subscribe to topics on the bus.
About how the subscription works – EventBridge triggers (or invokes if you will) the target when a particular event occurs – which in the examples is something getting published to the event bus.
That very basic feature of EventBridge being able to seamlessly invoke targets based on a rule lends itself very nicely for another extremely useful application – triggering or invoking targets based on time and frequency based rules. That is right, EventBridge can be configured to trigger targets like Lambdas by defining cron expressions that are almost exactly like a Unix cron expression. As an added convenience, we can also define a simpler rate expression, simply specifying the frequency rate – which is great when there is no necessity for exact time based scheduling or complex intervals which cron expressions cover just fine. The other convenience of EventBridge schedule expressions is the fact that there is no need to configure a custom event bus – these will all run off the default bus.
You can probably see the utility of this service, arguably more useful than even the powerful messaging capability of EventBridge just because of the simplicity. This obviates the need to have an EC2 with a cron job defined and allows us to stay serverless. In the principle of doing just that – let us review how we can define Cron and Rate Expressions as EventBridge rules that can be used to target a Lambda function. There are so many use cases for this kind of scenario but just to enumerate some examples – firing a Lambda to run some clean up job a few times a day or running a Lambda at a specific time to send out reports or having a job defined to run and do work when a day light savings switch occurs.
First a quick primer on EventBridge’s Cron and Rate expressions before I demonstrate how to define them as a Lambda Event in a Cloudformation template.
Defining EventBridge Cron Expressions
You define EventBridge Cron expressions almost exactly you would a regular Unix cron expression. This post is not meant to be an exhaustive primer on how to write cron expressions – my personal favorite resource for doing this honestly is cronmaker. But very, and I mean very briefly…
Say you want something running at 1:15 PM every weekday – then you would define it like so: cron(15 13 ? * MON-FRI *) each position representing in order – minute, hour, day of month, month, day of week year. There are a bunch of wildcard positions and in my expression I have used the most common ones. ? indicates any, so any day of month for my expression. * is all – so all months and years in the above. – is for ranges as shown in the MON-FRI.
Things can get very creative with how those are defined and cron is like its own language – not covering it here, but hopefully you get the gist.
Now the big difference between actual Unix Cron and EventBridge – no second precision – EventBridge is not so precise because of the serverless nature of provisioning things on demand and it cannot avoid delays in the seconds range, so no second level precision. Honestly this should be fine in the vast majority of use cases and if not, that is not something you want to build serverlessly probably. On a related limitation – the minimum frequency of an invocation is one minute and cannot be less.
Defining EventBridge Rate Expressions
This is such an excellent feature – just specify rate and unit – rate(1 hour) rate(2 days) etc – indicating the s for plural rates.
Ultimately this can be done with a cron expression and there is no need to use this if you prefer cron – but sometimes I just care about the rate – I just need this to run daily and when doesn’t matter – for those kinds of use cases, it saves me a trip to cronmaker.
With all that done, now lets configure a Lambda with a EventBridge Rules that use rate and cron expressions.
Configuring Lambda EventBridge Rules to run it based on the schedule expression via Cloudformation
Review the cloudformation yaml template below and I will explain after.
ScheduledLambda:
Type: AWS::Serverless::Function
Properties:
Runtime: python3.9
CodeUri: ./scheduled-lambda/
Handler: scheduled-lambda.event_handler
Description: Run twice a day - once on a cron schedule and once on a rate schedule
FunctionName: scheduled-lambda
Events:
CronEvent:
Type: Schedule
Properties:
Schedule: cron(15 13 * * ? *)
Name: CronSchedule
Description: Trigger Lambda at 1:15 PM daily
RateEvent:
Type: Schedule
Properties:
Schedule: rate(1 day)
Name: RateSchedule
Description: Trigger Lambda once daily
The above should be self explanatory if you have some familiarity with Cloudformation. If not – this might help to get the gist.
We basically have a Lambda with two events defined. Both are of the Schedule type which allow you to set the properties of the schedule expression. The Name and Schedule properties are required, the description is always helpful to set.
After deploying this, you will be able to see two new rules in EventBridge – the CronSchedule and RateSchedule rules and you should also be able to confirm the frequency on the console.
When will the Rate schedule take effect?
Now the Cron expression is understood – the Lambda will be triggered at the defined time – 1:15 PM in the example.
The rate expression though takes effect the moment you deploy the template – or more specifically the moment Cloudformation creates the event and wires it to the Lambda. After that it will fire at that time everyday. This is the point of using rate expressions – not worrying about the specifics of when things run, but if you have criteria like run after 5 PM or something you are probably safer going with a cron expression rather than trying to time your deployment.
And that is a wrap for this one. In a future post I plan to cover how I handle daylight savings with EventBridge and some Python wrangling.