Scheduling Future Events with AWS Step Functions

Rik Claessens
NN Tech
Published in
4 min readSep 23, 2020

Using the Serverless Framework and the power of AWS Step Functions and AWS Lambda, we create a reusable microservice that is able to execute any business logic at a very precise moment in the future.

Some members of the Catapult innovation team of NN.

Future events

A typical business requirement in a modern application could be something like:

  • When a user’s subscription ends one year from now, remind him that his subscription will be extended one week before he is charged.
  • When a user signs up to your service send them an email with tips & tricks in the evening 4 days after he signed up.

These scenarios have a lot of similarity and can be simplified to:

When <event> happens, execute <logic> at <moment>.

The event can happen anywhere throughout your application, maybe from a specific API call, or as a trigger from a DynamoDB stream where a specific record got inserted or updated. We will now use AWS Step Functions for waiting until the right moment and performing the required logic.

AWS Step Functions is a serverless function orchestrator that makes it easy to sequence AWS Lambda functions and multiple AWS services into business-critical applications.

Step Function

A visual of the state machine that handles future events.

We make use of the state machine functionality in AWS Step Functions. You can look at a state machine like a definition of states and the description of how you get from one state to another. In our case the state machine will be quite simple with two states: Wait and HandleEvent.

When the state machine starts we wait for a specific moment in the future and then it executes the logic we need.

Serverless

So let’s see how can define this state machine in the Serverless Framework.

In our serverless project, we need to install the serverless-step-functions plugin:

And add the plugin to our serverless.yml file:

This gives us the ability to define our state machine in serverless.yml like this:

A couple of things to highlight in this code snippet:

  • One of the parameters of the Wait state is TimestampPath: $.timestamp. What this means is that we can pass a variable called timestamp to this state and then the state machine will wait to that exact timestamp before going to the next state which is HandleEvent.
  • The final state is the HandleEvent state, where we reference the arn (Amazon Resource Name) of the HandleEventLambdaFunction.

Executing the business logic

In order to make the state machine generic and reusable for different types of events and business logic, the HandleEventLambdaFunction is implemented like this:

Next to the timestamp parameter, we also pass lambdaFunctionArn to the state machine when starting a new execution. This is the arn of the lambda function that actually runs our required business logic. All the HandleEventLambdaFunction does is invoking this lambda function. The actual business logic could have been implemented in the function above as well, but then we would have to create separate state machines for every type of logic we would like to do.

Executing the State Machine

With all the pieces in place, we can start the state machine with the required inputs:

  • In the payload, besides timestamp and lambdaFunctionArn, we pass all other properties that we need for our business logic. These are passed from Wait to HandleEvent automatically and to the final lambda function in line 9 of the HandleEventLambdaFunction.
  • arn is the arn of the state machine.
  • name is the name of the state machine execution, which needs to be unique for 90 days for your AWS account.

We now have all the basic pieces in place for scheduling future events using AWS Step Functions, so let’s have a look at an example.

Tying it all together

Now to tie it all together, let’s consider the case of sending an email to a user a week before he will be charged for the extension of his subscription. So in our API implementation, when a user subscribes, we start the state machine with the user’s email and first name as additional info to pass to our lambda function that will actually send the email:

In this example the lambda function that will execute our business logic is called sendSubscriptionEmail and the state machine’s name is futureEventStateMachine. As the executionName we choose the person’s email and the year for which he will pay the subscription, which should be unique (or you are making your customers pay twice!).

Now for our actual business logic, we send an email to our customer letting them know they will be charged next week:

That’s a wrap!

We created a generic, reusable future event scheduler using AWS Step Functions. Implemented using the Serverless Framework, we can use it to execute any type of business logic at a very precise moment in the future.

More material on the subject & inspiration

About Rik

Rik works as a Full Stack Engineer at NN, a financial services company active in 18 countries and the leading insurance company in the Netherlands. In the Catapult team, an in-house innovation team of NN, he focuses on new technology and developing applications to support the business in bringing innovations to life. Rik lives and loves to develop web and mobile apps as well as taking full stack to the next level with a focus on serverless and cloudnative applications.

Interested in working at NN? Check the NN careers website.

--

--