Use CloudWatch timers to thaw functions and help reduce response times from 3 seconds to a couple hundred milliseconds
There are many advantages to using a serverless architecture and there are hundreds of excellent articles extolling its virtues, but one painful downside is the often-slow response time of serverless functions that are infrequently used.
This is because on occasion, the container that created the function does not get reused. So on some requests, AWS needs to re-provision a container with your code before it can process the request.
For background tasks this obviously isn’t a problem. But if you have a task that is triggered by user input and blocks your app until you receive a response, it’s important that the function is warm so your response time can be a couple hundred milliseconds rather than 3 seconds.
On the other hand, there are times when your code is simply frozen on a container which can be “thawed” before it handles new requests, which only takes milliseconds.
Ideally, AWS would have an option along the lines of “keep warm” that you could toggle and agree to pay more to have AWS keep an unused container running at all times. Alas, this has not (yet?) been implemented, so our next best option is to use a CloudWatch timer.
As suggested by Michael over on Stack Overflow, you’ll need to ping your Lambda function every 5–15 minutes to keep it warm. This is easier than you might expect.
First, open up the AWS console (and yes, there is a way to do this via CLI) and go to CloudWatch. From there, go to
Events and click
Create rule. Set the event type to
Schedule, and we’ll run this event every 1 minute.
Then select the Lambda function you want to target from the
Targets list and Save. you’ll then need to create a name and description.
And that’s it! You’re now pinging your Lambda function every 1 minute.
How to Test
To test whether or not our timer actually kept the function alive, we’re going to create a function that stores the unique
awsRequestId in a variable called
containerID in the global scope (outside of the individual function).
Technically this is not the ID of the container, but it will tell us if a container us being reused for a subsequent request since we’re only writing to it if a value has not already been defined.
After you deploy this function, set up a timer, and wait some length of time, you can check your CloudWatch logs and you’ll see that the
containerID is persisting across requests, which tells us that AWS is keeping the functions warm if there is less than 1 minute between invocations.
So for the sake of science, I went ahead and created interval timers for 1–15 minutes, as well as 30, 45, and 60 minute intervals for good measure. This should give us a sense of how long AWS keeps these containers warm.
Fast forward 8 hours and we have our results. I was hoping the results would be interesting enough to create a fancy chart, but instead, I found this pattern for all of the functions.
Basically, all Lambda functions stayed warm for the duration of the experiment except that sometime around 14:00 UTC, AWS decided to reset all containers with no regard to whether or not it had been used recently.
Even the 1-hour ping continued to use the same container for several hours in a row (image below).
So it would appear (from this experiment, at least) that the frequency of the pings doesn’t matter all that much…
Either way, pinging every 15 minutes or so still costs approximately nothing, so there’s not reason to be stingy with your CloudWatch timers.
If you have any ideas of how we might improve upon these results, or if you have reason to believe these results are not valid for some particular reason, let me know in the comments.
Sam Corcos is the co-founder of CarDash, a full-service automotive concierge provider that eliminates the hassle of auto service, care, and maintenance. He is also the author of Learn Phoenix, and founder of Sightline Maps.