AWS Scheduled Lambda Function: Possible Options and Ultimate Solution

The topic of the scheduled launch of lambda functions is quite relevant for AWS serverless solutions. Nowadays, almost all projects use the same approach, and even though it works it is far from the optimal approach. In this article, we will consider alternatives and define which option will work best in practice.

For the purposes of illustration, let’s take an architecture of the following type:

  1. User.
  2. API GW.
  3. Lambda functions.

There is a mobile application designed to book rooms in hotels. Also, the application functionality allows for keyless access to the room.

A back-end developer is expected to prepare the following:

  1. An API for creating and managing reservations.
  2. Checking the arrival of the client within 2 hours from the start of the reservation.
  3. Activation of the client’s key right at the start of the reservation.

The serverless solution means that the system has no initiator, and we need to somehow run the function to activate the key or cancel the reservation. Most often, CloudWatch rules are used for such tasks.

A solution using CloudWatch rules

A CloudWatch Event rule runs a lambda function, for example, every 5 minutes. This is a working solution, but it has several disadvantages:

  1. If the client books a room for 12:01, the next update will only be in 4 minutes. During this time, the client is likely to decide that something went wrong and start relaunching the application and getting nervous.
  2. If we increase the frequency of launches to intervals of a minute, the waiting time for the client will reduce. However, in this case, there will be up to 44,640 lambda function launches per month. The limit of free launches is 1 million. We won’t have to pay for launches; still, there is also a fee for computing.

Рисунок1.png

If we allocate 128 MB for a function, and it performs within 500 ms, the costs will be as follows:

  • The cost of computing is $0.00001667 per GB-s.
  • Total calculations (in seconds) = 44,640 * (0.5 s) = 22,320 s.
  • Total calculations (in GB-s) = 22,320 * 128 MB / 1024 = 2,790 GB-s.
  • Monthly calculation fee = 2,790 * $0.00001667 = $0.0465093.

Less than 5 cents per month! At first glance, this is nothing. In practice, however, costs can rise when the load on the system increases. The function performance time could increase from 0.5 seconds to a minute or more. In this situation, the increased costs are not as terrible as the danger of collisions.

If the function performs for more than a minute, CloudWatch will launch the next function in parallel with the previous one. This can lead to the problems of reprocessing the same data, which in our case are the reservations.

Although the number of functions called in parallel is a software limitation, it is not infinite, and for some clients of AWS, this limit is not enough. There should be an alternative solution with a more elegant architecture that will not allow all these problems to occur (read about it in full version of article in our blog).

An alternative solution

When looking through many services, Step Functions turned out to be the most interesting one. It allows working with AWS services at a higher level, has many features, and what is more important, it helps to solve the problem of the scheduled launch of a lambda function. In particular, on Step Functions, it is possible to specify the exact time of launch.

State Machine Definition is as follows:

{

"StartAt": "Delay",

"States": {

"Delay": {

"Type": "Wait",

"TimestampPath": "$.delayTimestamp",

"Next": "Invoke Lambda"

},

"Invoke Lambda": {

"Type": "Task",

"Resource": "arn:aws:states:::lambda:invoke",

"Parameters": {

"FunctionName":

"arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",

"Payload": {

"Input.$": "$.body"

}

},

"End": true

}

}

}

Then, we create an execution that conveys delayTimestamp (the exact time when the function is supposed to run) and body (data that will be transferred to the function). The task can be performed for no longer than a year, but in practice, this can hardly be called a limitation. No other drawbacks were noticed either.

The work process includes three transitions between states:

  1. Start - Delay.
  2. Delay - Invoke Lambda.
  3. Invoke Lambda - End.

The cost for one transition, for example, for Northern Virginia, USA, is $0.000025. The first 4,000 transitions per month are free. If during a month the process is performed 100,000 times, the cost is calculated as follows:

(100,000 3 - 4,000) $0.000025 = $7.40

The cost for 100,000 calls of the lambda function using 128 MB of memory and with a performance speed of 500 ms will be $0.041675.

Total Monthly Expenses: $7.441675

At first glance, it seems significantly more expensive than the simple use of CloudWatch rules. However, with Step Functions, a task is created only after making a reservation. In the case of CloudWatch rules, we would run a huge number of functions while having no reservations. This will entail meaningless costs for CloudWatch Logs, and the total cost is hard to predict.

Using Step Functions, we get a clear transparent cost system and a beautiful architecture. After adding SQS with the trigger of a lambda function, the scheme is as follows:

Рисунок1.png

State Machine:

{

"StartAt": "Delay",

"States": {

"Delay": {

"Type": "Wait",

"TimestampPath": "$.delayTimestamp",

"Next": "Send message to SQS"

},

"Send message to SQS": {

"Type": "Task",

"Resource": "arn:aws:states:::sqs:sendMessage",

"Parameters": {

"QueueUrl.$": "$.queueUrl",

"MessageBody.$": "$.body"

},

"End": true

}

}

}

The Step Functions Developer Guide describes the Task Timer project that uses lambda functions. This is a great example of how to manage AWS Lambda with the help of Step Functions, although now, Step Functions supports direct integration with SNS, as in the previously-mentioned example with SQS.

Written by Andersen