Keep your lambdas warm during Winter. ♨
Clone or download

README.md

Serverless WarmUP Plugin ♨

serverless npm version npm downloads license

Keep your lambdas warm during Winter.

Requirements:

  • Serverless v1.12.x or higher.
  • AWS provider

How it works

WarmUP solves cold starts by creating one schedule event lambda that invokes all the service lambdas you select in a configured time interval (default: 5 minutes) or a specific time, forcing your containers to stay alive.

Setup

Install via npm in the root of your Serverless service:

npm install serverless-plugin-warmup --save-dev
  • Add the plugin to the plugins array in your Serverless serverless.yml:
plugins:
  - serverless-plugin-warmup
  • Add a warmup property to all functions you want to be warm.

You can enable WarmUp in general:

functions:
  hello:
    warmup: true

For a specific stage:

functions:
  hello:
    warmup: production

For several stages:

functions:
  hello:
    warmup:
      - production
      - staging
  • WarmUP requires some permissions to be able to invoke lambdas.
custom:
  warmup:
    folderName: '_warmup' # Name of the folder created for the generated warmup 
    cleanFolder: false
    memorySize: 256
    name: 'make-them-pop'
    role:  myCustRole0
    schedule: 'cron(0/5 8-17 ? * MON-FRI *)' # Run WarmUP every 5 minutes Mon-Fri between 8:00am and 5:55pm (UTC)
    timeout: 20
    prewarm: true # Run WarmUp immediately after a deployment
    tags:
      Project: foo
      Owner: bar

.....

resources:
  Resources:
    myCustRole0:
      Type: AWS::IAM::Role
      Properties:
        Path: /my/cust/path/
        RoleName: MyCustRole0
        AssumeRolePolicyDocument:
          Version: '2017'
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action: sts:AssumeRole
        Policies:
          - PolicyName: myPolicyName
            PolicyDocument:
              Version: '2017'
              Statement:
                - Effect: Allow
                  Action:
                    - logs:CreateLogGroup
                    - logs:CreateLogStream
                    - logs:PutLogEvents
                  Resource: 
                    - 'Fn::Join':
                      - ':'
                      -
                        - 'arn:aws:logs'
                        - Ref: 'AWS::Region'
                        - Ref: 'AWS::AccountId'
                        - 'log-group:/aws/lambda/*:*:*'
                - Effect: Allow
                  Action:
                    - ec2:CreateNetworkInterface
                    - ec2:DescribeNetworkInterfaces
                    - ec2:DetachNetworkInterface
                    - ec2:DeleteNetworkInterface
                  Resource: "*"
                - Effect: 'Allow'
                  Action:
                    - 'lambda:InvokeFunction'
                  Resource:
                  - Fn::Join:
                    - ':'
                    - - arn:aws:lambda
                      - Ref: AWS::Region
                      - Ref: AWS::AccountId
                      - function:${self:service}-${opt:stage, self:provider.stage}-*

The permissions can also be added to all lambdas using iamRoleStatements under provider (see https://serverless.com/framework/docs/providers/aws/guide/functions/#permissions):

provider:
  name: aws
  runtime: nodejs6.10
  iamRoleStatements:
    - Effect: 'Allow'
      Action:
        - 'lambda:InvokeFunction'
      Resource:
      - Fn::Join:
        - ':'
        - - arn:aws:lambda
          - Ref: AWS::Region
          - Ref: AWS::AccountId
          - function:${self:service}-${opt:stage, self:provider.stage}-*

If using pre-warm, the deployment user also needs a similar policy so it can run the WarmUp lambda.

  • Add an early callback call when the event source is serverless-plugin-warmup. You should do this early exit before running your code logic, it will save your execution duration and cost:
module.exports.lambdaToWarm = function(event, context, callback) {
  /** Immediate response for WarmUP plugin */
  if (event.source === 'serverless-plugin-warmup') {
    console.log('WarmUP - Lambda is warm!')
    return callback(null, 'Lambda is warm!')
  }

  ... add lambda logic after
}
  • All done! WarmUP will run on SLS deploy and package commands

Options

  • folderName (default _warmup)
  • cleanFolder (default true)
  • memorySize (default 128)
  • name (default ${service}-${stage}-warmup-plugin)
  • role (default to role in the provider)
  • schedule (default rate(5 minutes)) - More examples here.
  • timeout (default 10 seconds)
  • prewarm (default false)
  • tags (default to serverless default tags)
custom:
  warmup:
    folderName: '_warmup' // Name of the folder created for the generated warmup 
    cleanFolder: false
    memorySize: 256
    name: 'make-them-pop'
    role: myCustRole0
    schedule: 'cron(0/5 8-17 ? * MON-FRI *)' // Run WarmUP every 5 minutes Mon-Fri between 8:00am and 5:55pm (UTC)
    timeout: 20
    prewarm: true // Run WarmUp immediately after a deploymentlambda
    tags:
      Project: foo
      Owner: bar    

Options should be tweaked depending on:

  • Number of lambdas to warm up
  • Day cold periods
  • Desire to avoid cold lambdas after a deployment

Lambdas invoked by WarmUP will have event source serverless-plugin-warmup:

{
  "Event": {
    "source": "serverless-plugin-warmup"
  }
}

Artifact

If you are doing your own package artifact set option cleanFolder to false and run serverless package. This will allow you to extract the warmup NodeJS lambda file from the _warmup folder and add it in your custom artifact logic.

Gotchas

If you are deploying to a VPC, you need to use private subnets with a Network Address Translation (NAT) gateway (http://docs.aws.amazon.com/lambda/latest/dg/vpc.html). WarmUp requires this so it can call the other lambdas but this is applicable to any lambda that needs access to the public internet or to any other AWS service.

Cost

Lambda pricing here. CloudWatch pricing here. You can use AWS Lambda Pricing Calculator to check how much will cost you monthly.

Example

Free Tier not included + Default WarmUP options + 10 lambdas to warm, each with memorySize = 1024 and duration = 10:

  • WarmUP: runs 8640 times per month = $0.18
  • 10 warm lambdas: each invoked 8640 times per month = $14.4
  • Total = $14.58

CloudWatch costs are not in this example because they are very low.

Contribute

Help us making this plugin better and future proof.

  • Clone the code
  • Install the dependencies with npm install
  • Create a feature branch git checkout -b new_feature
  • Lint with standard npm run lint

License

This software is released under the MIT license. See the license file for more details.