Warming Up your Lambdas: Schedule or Plugin?
Tags: coldstart, serverless, lambda, aws
Published: 2019-02-20 09:33:41

---
title: Warming Up your Lambdas: Schedule or Plugin? 
published: true
cover_image: https://media.giphy.com/media/GrnNAqkOfqHyU/giphy.gif
description: 
tags: #coldstart, #serverless, #lambda, #aws
---

As soon as you switch your backend development to serverless, you will start facing an issue called Cold Start: Your API is awesome, scalable and everything and normally also very fast.  Only now and then it seems it takes ages to respond ( well, **from the user perspective 10 seconds are actually ages**). 
For its own nature a serverless application is not always running and after it has been idle for a bunch of minutes, the container is shut down. The time needed for the container to be restarted and all the components of the app to be reinitialized is longer than simply executing your code. That is the Cold Start. 

One of the approaches to reduce cold starts ( even though this is not really solving the problem though,  read [im-afraid-youre-thinking-about-aws-lambda-cold-starts-all-wrong article from Yan Cui](https://theburningmonk.com/2018/01/im-afraid-youre-thinking-about-aws-lambda-cold-starts-all-wrong/ to understand why) if you want to know more) is keeping your Lambda warm.  
![keep warm](https://thepracticaldev.s3.amazonaws.com/i/xo165l1pdvii0f8hqbc1.jpg)
That means having a scheduler that invokes the function at regular intervals to prevent the container to be destroyed. 

As documented by Serverless you can quickly configure a [ScheduledEvent](https://serverless.com/framework/docs/providers/aws/events/schedule/) or you can configure [Serverless WarmUp Plugin](https://github.com/FidelLimited/serverless-plugin-warmup) 

##What is the difference?

Schedule creates a CloudWatch Event that triggers your Lambda with the rate or cron job that you specified.
This means that for each Lambda in your serverless.yml you need a configuration for the Scheduling Event like this
```
  - schedule:
      name: your-scheduled-rate-event-name # optional
      rate: rate(10 minutes)
```
This can get pretty messy to maintain - especially if you chose the Multiple Endpoints approach (where each Resource points to a specific Lambda), and it also means that every Lambda will have its own CloudWatch event, for which it seems there is a per account limitation on AWS:

> Each AWS account can have up to 100 unique event sources of the CloudWatch Events- Schedule source type. Each of these can be the event source for up to five Lambda functions. That is, you can have up to 500 Lambda functions that can be executed on a schedule in your AWS account.
[CloudWatchEvents](https://docs.aws.amazon.com/lambda/latest/dg/with-scheduled-events.html)

WarmUp also makes use of a CloudWatchEvent but that event is bound only to a specific Lambda created on purpose. This Warmer stores an array of all the Lambdas from your serverless.yml and when triggered by CloudWatch will, in turn, invoke all them. 

In both cases the payload in the hander will specify the origin of the invocation so that you can exit immediately and avoid useless calculations or errors.
Just remember to check for the event source like this for the WarmUp Plugin
```
module.exports.handler = async(event, context, callback) => {
    /** Immediate response for WarmUP plugin */
    if (event.source === 'serverless-plugin-warmup') {
        return callback(null, 'Lambda is warm!')
    }
    // do your stuff
}
```
and like this for the Schedule Event:

```
module.exports.handler = async(event, context, callback) => {
  /** Immediate response for Ping from CloudWatch */
    if (event.source === 'aws.events' && event["detail-type"] === 'Scheduled Event') {
       return callback(null, 'Lambda is warm!')
    }
    // do your stuff
}
```
In our project we went for the Plugin since it allows easier and cleaner global configuration.

Our serverless.yml ended up looking like this:
```yml
custom:  
    warmup:
        default:
          - production  
            # lambdas in dev and staging environment can even freeze... who cares. 
        schedule: 'cron(0/20 8-18:30 ? * MON-FRI *)'  
            # since our API is used only from an internal company WebApp keep lambda warm only every 20 minutes in office hours.
        prewarm: true # Run WarmUp immediately after a deployment 
        concurrency: 2 # Warm up 2 concurrent instances
```

When your run ´sls deploy´ make sure the plugin reads the configuration and logs the Lambdas that will be warmed and pre-warmed:

![Found Lambdas to warm up](https://thepracticaldev.s3.amazonaws.com/i/d4oxf7qyf634apx8qccb.png)

![Pre-warming after deployment](https://thepracticaldev.s3.amazonaws.com/i/0yfi7fp6awv47tcuvkc1.png)

Afterward, you can check in your AWS UI Console and along your Lambdas, you will find another Lambda with description Serverless WarmUP Plugin.   If you open its code you will see all your lambdas that will be warmed and you can also make sure the CloudWatch Event is there and properly configured: `Schedule expression: rate(5 minutes)`.

If in the terminal you notice ![No Lambda to warm up](https://thepracticaldev.s3.amazonaws.com/i/rbdoxncdtvu6ftnkz3jz.png) then something went wrong.  Like in my first attempts: in fact, I was following the [instructions on Github](https://github.com/FidelLimited/serverless-plugin-warmup#global-configuration) repo and from [this article](https://serverless.com/blog/keep-your-lambdas-warm/) and found that info was something conflicting in the configuration of each function and that the global configuration wasn't working at all.
Then I [found this issue](https://github.com/FidelLimited/serverless-plugin-warmup/issues/100) and realized that the plugin has currently issues in releasing new versions and the Code and README on Master on Github is more up to date that the version on NPM, so the configuration must be done differently. 

Until a new version is released just stick to the [docs on NPM](https://www.npmjs.com/package/serverless-plugin-warmup), then if you upgrade with npm or yarn remember to refactor its configuration in your serverless.yml

Hope this helps!