Keep your lambdas warm during Winter.
Requirements:
- Serverless v1.12.x or higher (Recommended v1.33.x or higher because of this).
- AWS provider
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.
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.enabled
property to custom to enable/disable the warm up process by default for all the functions
Enable WarmUp in general:
custom:
warmup:
enabled: true
For a specific stage:
custom:
warmup:
enabled: production
For several stages:
custom:
warmup:
enabled:
- production
- staging
You can override the global enabled
configuration on any function.
Enable WarmUp for a specific function
functions:
hello:
warmup:
enabled: true
For a specific stage:
functions:
hello:
warmup:
enabled: production
For several stages:
functions:
hello:
warmup:
enabled:
- production
- staging
Do not warm-up a function if enabled
is set to false:
custom:
warmup:
enabled: true
...
functions:
hello:
warmup:
enabled: false
- folderName (default
_warmup
) - cleanFolder (default
true
) - name (default
${service}-${stage}-warmup-plugin
) - role (default to role in the provider)
- tags (default to serverless default tags)
- vpc (default to vpc in provider, can be set to
false
to deploy the warmup function outside of VPC) - memorySize (default
128
) - events (default
- schedule: rate(5 minutes)
) - timeout (default
10
seconds) - prewarm (default
false
)
- enabled (default
false
) - payload (default
{ "source": "serverless-plugin-warmup" }
) - payloadRaw (default
false
) - concurrency (default
1
)
custom:
warmup:
enabled: true # Whether to warm up functions by default or not
folderName: '_warmup' # Name of the folder created for the generated warmup
cleanFolder: false
memorySize: 256
name: 'make-them-pop'
role: myCustRole0
tags:
Project: foo
Owner: bar
vpc: false
events:
- 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
payload:
source: my-custom-source
other: 20
payloadRaw: true # Won't JSON.stringify() the source, may be necessary for Go/AppSync deployments
concurrency: 5 # Warm up 5 concurrent instances
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
(unless otherwise specified above):
{
"Event": {
"source": "serverless-plugin-warmup"
}
}
Over time some options have been removed form the pluging. For now, we keep backwards compatibility so they still work. However, they are listed here only to facilitate upgrading the pluging and we strongly recommend switching to the options defined above as soon as possible.
- default Has been renamed to
enabled
- schedule
schedule: rate(5 minutes)
is equivalent toevents: - schedule: rate(5 minutes)
. - source Has been renamed to
payload
- sourceRaw Has been renamed to
payloadRaw
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
events:
- 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 # WarmUp lamda to send logs to CloudWatch
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 # WarmUp lamda to manage ENIS (only needed if deploying to VPC, https://docs.aws.amazon.com/lambda/latest/dg/vpc.html)
Action:
- ec2:CreateNetworkInterface
- ec2:DescribeNetworkInterfaces
- ec2:DetachNetworkInterface
- ec2:DeleteNetworkInterface
Resource: "*"
- Effect: 'Allow' # WarmUp lamda to invoke the functions to be warmed
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
}
You can also check for the warmup event using the context
variable. This could be useful if you are handling the raw input and output streams:
...
if(context.custom.source === 'serverless-plugin-warmup'){
console.log('WarmUP - Lambda is warm!')
return callback(null, 'Lambda is warm!')
}
...
If you're using the concurrency
option you might consider adding a slight delay before returning when warming up to ensure your function doesn't return before all concurrent requests have been started:
module.exports.lambdaToWarm = async (event) => {
if (event.source === 'serverless-plugin-warmup') {
/** Slightly delayed (25ms) response for WarmUP plugin to ensure concurrent invocation */
await new Promise(r => setTimeout(r, 25))
console.log('WarmUP - Lambda is warm!')
return
}
... add lambda logic after
}
Once everything is configured WarmUP will run on SLS deploy
.
serverless deploy
WarmUp also runs on SLS package
.
If you are doing your own package artifact set the cleanFolder
option 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.
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.
Lambda pricing here. CloudWatch pricing here. You can use AWS Lambda Pricing Calculator to check how much will cost you monthly.
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.
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
This software is released under the MIT license. See the license file for more details.