This repository was archived by the owner on Oct 1, 2025. It is now read-only.

Repository files navigation

Lambda Warmer

npmnpmBuild StatusCoverage Statusdependencies

A module to optimize AWS Lambda function cold starts

At a recent AWS Startup Day event in Boston, MA, Chris Munns, the Senior Developer Advocate for Serverless at AWS, discussed Cold Starts and how to mitigate them. According to Chris (although he acknowledged that it is a "hack") using the CloudWatch Events "ping" method is really the only way to do it right now. He gave a number of good tips on how to do this "correctly":

  • Don’t ping more often than every 5 minutes
  • Invoke the function directly (i.e. don’t use API Gateway to invoke it)
  • Pass in a test payload that can be identified as such
  • Create handler logic that replies accordingly without running the whole function

He also mentioned that if you want to keep several concurrent functions warm, that you need to invoke the same function multiple times with delayed executions. This prevents the system from reusing the same container.

You can read the key takeaways from his talk here.

Following these "best practices", I created Lambda Warmer. It is a lightweight module (with no dependencies) that can be added to your Lambda functions to manage "warming" events as well as handling automatic fan-out for initializing concurrent functions. Just instrument your code and schedule a "ping".

NOTE: Lambda Warmer will invoke the function multiple times using the AWS-SDK in order to scale concurrency (if you want to). Your functions MUST have lambda:InvokeFunction permissions so that they can invoke themselves. Following the Principle of Least Privilege, you should limit the Resource to the function itself, e.g.:

- Effect: "Allow"Action:
- "lambda:InvokeFunction"Resource: "arn:aws:lambda:us-east-1:{AWS-ACCOUNT-ID}:function:my-test-function"

If you'd like to know more about how Lambda Warmer works, and why you might (or might not) want to use it, read this Lambda Warmer: Optimize AWS Lambda Function Cold Starts post.

Installation

Install Lambda Warmer from NPM as a project dependency.

npm i lambda-warmer

Instrumenting your Lambda functions

Adding Lambda Warmer to your functions is simple. Require lambda-warmer outside of your main handler and then pass the event as the first argument into your declared variable. Lambda Warmer will return a resolved promise with either true, meaning this is a warming invocation, or false, this isn't a warming invocation.

If you're using async/await, you can await the result of Lambda Warmer and return if true. This will short circuit your function and prevent it from executing the rest of the main handler.

constwarmer=require('lambda-warmer')exports.handler=async(event)=>{// if a warming eventif(awaitwarmer(event))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

If you are using callbacks, use Lambda Warmer to start a promise chain and then make your handler logic conditional depending on its result.

constwarmer=require('lambda-warmer')exports.handler=(event,context,callback)=>{// Start a promise chainwarmer(event).then(isWarmer=>{// if a warming eventif(isWarmer){callback(null,'warmed')// else proceed with handler logic}else{callback(null,'Hello from Lambda')}})}

Configuration Options

You can send in a configuration object as the second parameter to change Lambda Warmer's default behavior. All of the settings are optional. Here is a sample configuration object.

{flag: 'warmer',concurrency: 'concurrency',test: 'test',log: true,correlationId: 'XXXXXXXXXXXXX',delay: 75}

flag (string)

Name of the event field used to notify Lambda Warmer that this is a "warming" invocation. Defaults to warmer.

concurrency (string)

Name of the event field used to specify the number of concurrent functions you'd like to warm. Defaults to concurrency.

test (string)

Name of the event field used to flag a warming invocation as a test. Defaults to test.

log (boolean)

Flag to control whether or not CloudWatch logs are automatically generated. Defaults to true.

correlationId (string)

Identifier that gets passed to all concurrent Lambda invocations. This can be used to group invocations within your logs. If no correlationId is passed, it will default to the id generated for the invoked function. Passing the context.awsRequestId is good practice.

delay (number)

Minimum amount of time (in milliseconds) for concurrent functions to run. Concurrent functions are invoked asynchronously. Setting a delay enforces Lambda to create multiple invocations. Defaults to 75 to attempt sub 100ms invocation times.

Example passing a configuration:

exports.handler=async(event,context)=>{// if a warming eventif(awaitwarmer(event,{correlationId: context.awsRequestId,delay: 50}))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

Warming your Lambda functions

Lambda Warmer facilitates the warming of your functions by analyzing invocation events and appropriately managing handler processing. It DOES NOT manage the periodic invocation of your functions. In order to keep your functions warm, you must create a CloudWatch Rule that invokes your functions on a predetermined schedule.

A rule that invokes your function should contain a Constant (JSON text) under the "Configure input" setting. The following is a sample event (using the default configuration and a concurrency of 3):

{"warmer":true,"concurrency":3}

The names of warmer and concurrency can be changed using the configuration option when instrumenting your code.

NOTE: Non-VPC functions are kept warm for approximately 5 minutes whereas VPC-based functions are kept warm for 15 minutes. Set your schedule for invocations accordingly. There is no need to ping your functions more often than the minimum warm time.

TIP: Preparing for traffic spikes

If your application experiences periodic traffic spikes throughout the day, you can set up multiple CloudWatch Rules that change the concurrency based on the time of day or day itself.

Using a SAM Template

To add a schedule event to your Lambda functions, you can add a Type: Schedule to the Events section of your function in a SAM template:

AWSTemplateFormatVersion: '2010-09-09'Transform: 'AWS::Serverless-2016-10-31'Resources:
MyFunction:
Type: 'AWS::Serverless::Function'Properties:
Handler: index.handlerRuntime: nodejs8.10CodeUri: 's3://my-bucket/function.zip'Events:
WarmingSchedule:
Type: ScheduleProperties:
Schedule: rate(5 minutes)Input: '{ "warmer":true,"concurrency":3 }'

Using the Serverless Framework

If you are using the Serverless Framework, you can include a schedule event for your functions using the following format:

myFunction:
name: myFunctionhandler: myFunction.handlerevents:
- schedule:
name: warmer-schedule-namerate: rate(5 minutes)enabled: trueinput:
warmer: trueconcurrency: 1

Logs

Logs are automatically generated unless the log configuration option is set to false. Logs contain useful information beyond just invocation data. The warm field indicates whether or not the Lambda function was already warm when invoked. The lastAccessed field is the timestamp (in milliseconds) of the last time the function was accessed by a non-warming event. Similarly, the lastAccessedSeconds gives you a counter (in seconds) of how long it's been since it has been accessed. These can be used to determine if your concurrency can be lowered.

Sample log:

{action: 'warmer',// identifierfunction: 'my-test-function',// function nameid: '1531413096993-0568',// unique function instance idcorrelationId: '1531413096993-0568',// correlation idcount: 1,// function number of total concurrent e.g. 3 of 10concurrency: 2,// number of concurrent functions being invokedwarm: true,// was this function already warmlastAccessed: 1531413096995,// timestamp (in ms) of last non-warming accesslastAccessedSeconds: '25.6'// time since last non-warming access}

Sponsors

IOpipe

IOpipe is all about making it more fun to be a developer through the support of the open source serverless community. Sign up with IOpipe for free to get real-time visibility into the most detailed behaviors of your Lambda applications.

Contributing

I've created a number of custom scripts to do similar cold start mitigation, but I figured I'd share this more complete version to save everyone some time (including my future self). If you would like to contribute, please submit a PR or add issues for bug reports and feature ideas.

About

A module to optimize AWS Lambda function cold starts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
This repository was archived by the owner on Oct 1, 2025. It is now read-only.

Repository files navigation

Lambda Warmer

npmnpmBuild StatusCoverage Statusdependencies

A module to optimize AWS Lambda function cold starts

At a recent AWS Startup Day event in Boston, MA, Chris Munns, the Senior Developer Advocate for Serverless at AWS, discussed Cold Starts and how to mitigate them. According to Chris (although he acknowledged that it is a "hack") using the CloudWatch Events "ping" method is really the only way to do it right now. He gave a number of good tips on how to do this "correctly":

  • Don’t ping more often than every 5 minutes
  • Invoke the function directly (i.e. don’t use API Gateway to invoke it)
  • Pass in a test payload that can be identified as such
  • Create handler logic that replies accordingly without running the whole function

He also mentioned that if you want to keep several concurrent functions warm, that you need to invoke the same function multiple times with delayed executions. This prevents the system from reusing the same container.

You can read the key takeaways from his talk here.

Following these "best practices", I created Lambda Warmer. It is a lightweight module (with no dependencies) that can be added to your Lambda functions to manage "warming" events as well as handling automatic fan-out for initializing concurrent functions. Just instrument your code and schedule a "ping".

NOTE: Lambda Warmer will invoke the function multiple times using the AWS-SDK in order to scale concurrency (if you want to). Your functions MUST have lambda:InvokeFunction permissions so that they can invoke themselves. Following the Principle of Least Privilege, you should limit the Resource to the function itself, e.g.:

- Effect: "Allow"Action:
- "lambda:InvokeFunction"Resource: "arn:aws:lambda:us-east-1:{AWS-ACCOUNT-ID}:function:my-test-function"

If you'd like to know more about how Lambda Warmer works, and why you might (or might not) want to use it, read this Lambda Warmer: Optimize AWS Lambda Function Cold Starts post.

Installation

Install Lambda Warmer from NPM as a project dependency.

npm i lambda-warmer

Instrumenting your Lambda functions

Adding Lambda Warmer to your functions is simple. Require lambda-warmer outside of your main handler and then pass the event as the first argument into your declared variable. Lambda Warmer will return a resolved promise with either true, meaning this is a warming invocation, or false, this isn't a warming invocation.

If you're using async/await, you can await the result of Lambda Warmer and return if true. This will short circuit your function and prevent it from executing the rest of the main handler.

constwarmer=require('lambda-warmer')exports.handler=async(event)=>{// if a warming eventif(awaitwarmer(event))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

If you are using callbacks, use Lambda Warmer to start a promise chain and then make your handler logic conditional depending on its result.

constwarmer=require('lambda-warmer')exports.handler=(event,context,callback)=>{// Start a promise chainwarmer(event).then(isWarmer=>{// if a warming eventif(isWarmer){callback(null,'warmed')// else proceed with handler logic}else{callback(null,'Hello from Lambda')}})}

Configuration Options

You can send in a configuration object as the second parameter to change Lambda Warmer's default behavior. All of the settings are optional. Here is a sample configuration object.

{flag: 'warmer',concurrency: 'concurrency',test: 'test',log: true,correlationId: 'XXXXXXXXXXXXX',delay: 75}

flag (string)

Name of the event field used to notify Lambda Warmer that this is a "warming" invocation. Defaults to warmer.

concurrency (string)

Name of the event field used to specify the number of concurrent functions you'd like to warm. Defaults to concurrency.

test (string)

Name of the event field used to flag a warming invocation as a test. Defaults to test.

log (boolean)

Flag to control whether or not CloudWatch logs are automatically generated. Defaults to true.

correlationId (string)

Identifier that gets passed to all concurrent Lambda invocations. This can be used to group invocations within your logs. If no correlationId is passed, it will default to the id generated for the invoked function. Passing the context.awsRequestId is good practice.

delay (number)

Minimum amount of time (in milliseconds) for concurrent functions to run. Concurrent functions are invoked asynchronously. Setting a delay enforces Lambda to create multiple invocations. Defaults to 75 to attempt sub 100ms invocation times.

Example passing a configuration:

exports.handler=async(event,context)=>{// if a warming eventif(awaitwarmer(event,{correlationId: context.awsRequestId,delay: 50}))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

Warming your Lambda functions

Lambda Warmer facilitates the warming of your functions by analyzing invocation events and appropriately managing handler processing. It DOES NOT manage the periodic invocation of your functions. In order to keep your functions warm, you must create a CloudWatch Rule that invokes your functions on a predetermined schedule.

A rule that invokes your function should contain a Constant (JSON text) under the "Configure input" setting. The following is a sample event (using the default configuration and a concurrency of 3):

{"warmer":true,"concurrency":3}

The names of warmer and concurrency can be changed using the configuration option when instrumenting your code.

NOTE: Non-VPC functions are kept warm for approximately 5 minutes whereas VPC-based functions are kept warm for 15 minutes. Set your schedule for invocations accordingly. There is no need to ping your functions more often than the minimum warm time.

TIP: Preparing for traffic spikes

If your application experiences periodic traffic spikes throughout the day, you can set up multiple CloudWatch Rules that change the concurrency based on the time of day or day itself.

Using a SAM Template

To add a schedule event to your Lambda functions, you can add a Type: Schedule to the Events section of your function in a SAM template:

AWSTemplateFormatVersion: '2010-09-09'Transform: 'AWS::Serverless-2016-10-31'Resources:
MyFunction:
Type: 'AWS::Serverless::Function'Properties:
Handler: index.handlerRuntime: nodejs8.10CodeUri: 's3://my-bucket/function.zip'Events:
WarmingSchedule:
Type: ScheduleProperties:
Schedule: rate(5 minutes)Input: '{ "warmer":true,"concurrency":3 }'

Using the Serverless Framework

If you are using the Serverless Framework, you can include a schedule event for your functions using the following format:

myFunction:
name: myFunctionhandler: myFunction.handlerevents:
- schedule:
name: warmer-schedule-namerate: rate(5 minutes)enabled: trueinput:
warmer: trueconcurrency: 1

Logs

Logs are automatically generated unless the log configuration option is set to false. Logs contain useful information beyond just invocation data. The warm field indicates whether or not the Lambda function was already warm when invoked. The lastAccessed field is the timestamp (in milliseconds) of the last time the function was accessed by a non-warming event. Similarly, the lastAccessedSeconds gives you a counter (in seconds) of how long it's been since it has been accessed. These can be used to determine if your concurrency can be lowered.

Sample log:

{action: 'warmer',// identifierfunction: 'my-test-function',// function nameid: '1531413096993-0568',// unique function instance idcorrelationId: '1531413096993-0568',// correlation idcount: 1,// function number of total concurrent e.g. 3 of 10concurrency: 2,// number of concurrent functions being invokedwarm: true,// was this function already warmlastAccessed: 1531413096995,// timestamp (in ms) of last non-warming accesslastAccessedSeconds: '25.6'// time since last non-warming access}

Sponsors

IOpipe

IOpipe is all about making it more fun to be a developer through the support of the open source serverless community. Sign up with IOpipe for free to get real-time visibility into the most detailed behaviors of your Lambda applications.

Contributing

I've created a number of custom scripts to do similar cold start mitigation, but I figured I'd share this more complete version to save everyone some time (including my future self). If you would like to contribute, please submit a PR or add issues for bug reports and feature ideas.

About

A module to optimize AWS Lambda function cold starts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Oct 1, 2025. It is now read-only.

Repository files navigation

Lambda Warmer

npmnpmBuild StatusCoverage Statusdependencies

A module to optimize AWS Lambda function cold starts

At a recent AWS Startup Day event in Boston, MA, Chris Munns, the Senior Developer Advocate for Serverless at AWS, discussed Cold Starts and how to mitigate them. According to Chris (although he acknowledged that it is a "hack") using the CloudWatch Events "ping" method is really the only way to do it right now. He gave a number of good tips on how to do this "correctly":

  • Don’t ping more often than every 5 minutes
  • Invoke the function directly (i.e. don’t use API Gateway to invoke it)
  • Pass in a test payload that can be identified as such
  • Create handler logic that replies accordingly without running the whole function

He also mentioned that if you want to keep several concurrent functions warm, that you need to invoke the same function multiple times with delayed executions. This prevents the system from reusing the same container.

You can read the key takeaways from his talk here.

Following these "best practices", I created Lambda Warmer. It is a lightweight module (with no dependencies) that can be added to your Lambda functions to manage "warming" events as well as handling automatic fan-out for initializing concurrent functions. Just instrument your code and schedule a "ping".

NOTE: Lambda Warmer will invoke the function multiple times using the AWS-SDK in order to scale concurrency (if you want to). Your functions MUST have lambda:InvokeFunction permissions so that they can invoke themselves. Following the Principle of Least Privilege, you should limit the Resource to the function itself, e.g.:

- Effect: "Allow"Action:
- "lambda:InvokeFunction"Resource: "arn:aws:lambda:us-east-1:{AWS-ACCOUNT-ID}:function:my-test-function"

If you'd like to know more about how Lambda Warmer works, and why you might (or might not) want to use it, read this Lambda Warmer: Optimize AWS Lambda Function Cold Starts post.

Installation

Install Lambda Warmer from NPM as a project dependency.

npm i lambda-warmer

Instrumenting your Lambda functions

Adding Lambda Warmer to your functions is simple. Require lambda-warmer outside of your main handler and then pass the event as the first argument into your declared variable. Lambda Warmer will return a resolved promise with either true, meaning this is a warming invocation, or false, this isn't a warming invocation.

If you're using async/await, you can await the result of Lambda Warmer and return if true. This will short circuit your function and prevent it from executing the rest of the main handler.

constwarmer=require('lambda-warmer')exports.handler=async(event)=>{// if a warming eventif(awaitwarmer(event))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

If you are using callbacks, use Lambda Warmer to start a promise chain and then make your handler logic conditional depending on its result.

constwarmer=require('lambda-warmer')exports.handler=(event,context,callback)=>{// Start a promise chainwarmer(event).then(isWarmer=>{// if a warming eventif(isWarmer){callback(null,'warmed')// else proceed with handler logic}else{callback(null,'Hello from Lambda')}})}

Configuration Options

You can send in a configuration object as the second parameter to change Lambda Warmer's default behavior. All of the settings are optional. Here is a sample configuration object.

{flag: 'warmer',concurrency: 'concurrency',test: 'test',log: true,correlationId: 'XXXXXXXXXXXXX',delay: 75}

flag (string)

Name of the event field used to notify Lambda Warmer that this is a "warming" invocation. Defaults to warmer.

concurrency (string)

Name of the event field used to specify the number of concurrent functions you'd like to warm. Defaults to concurrency.

test (string)

Name of the event field used to flag a warming invocation as a test. Defaults to test.

log (boolean)

Flag to control whether or not CloudWatch logs are automatically generated. Defaults to true.

correlationId (string)

Identifier that gets passed to all concurrent Lambda invocations. This can be used to group invocations within your logs. If no correlationId is passed, it will default to the id generated for the invoked function. Passing the context.awsRequestId is good practice.

delay (number)

Minimum amount of time (in milliseconds) for concurrent functions to run. Concurrent functions are invoked asynchronously. Setting a delay enforces Lambda to create multiple invocations. Defaults to 75 to attempt sub 100ms invocation times.

Example passing a configuration:

exports.handler=async(event,context)=>{// if a warming eventif(awaitwarmer(event,{correlationId: context.awsRequestId,delay: 50}))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

Warming your Lambda functions

Lambda Warmer facilitates the warming of your functions by analyzing invocation events and appropriately managing handler processing. It DOES NOT manage the periodic invocation of your functions. In order to keep your functions warm, you must create a CloudWatch Rule that invokes your functions on a predetermined schedule.

A rule that invokes your function should contain a Constant (JSON text) under the "Configure input" setting. The following is a sample event (using the default configuration and a concurrency of 3):

{"warmer":true,"concurrency":3}

The names of warmer and concurrency can be changed using the configuration option when instrumenting your code.

NOTE: Non-VPC functions are kept warm for approximately 5 minutes whereas VPC-based functions are kept warm for 15 minutes. Set your schedule for invocations accordingly. There is no need to ping your functions more often than the minimum warm time.

TIP: Preparing for traffic spikes

If your application experiences periodic traffic spikes throughout the day, you can set up multiple CloudWatch Rules that change the concurrency based on the time of day or day itself.

Using a SAM Template

To add a schedule event to your Lambda functions, you can add a Type: Schedule to the Events section of your function in a SAM template:

AWSTemplateFormatVersion: '2010-09-09'Transform: 'AWS::Serverless-2016-10-31'Resources:
MyFunction:
Type: 'AWS::Serverless::Function'Properties:
Handler: index.handlerRuntime: nodejs8.10CodeUri: 's3://my-bucket/function.zip'Events:
WarmingSchedule:
Type: ScheduleProperties:
Schedule: rate(5 minutes)Input: '{ "warmer":true,"concurrency":3 }'

Using the Serverless Framework

If you are using the Serverless Framework, you can include a schedule event for your functions using the following format:

myFunction:
name: myFunctionhandler: myFunction.handlerevents:
- schedule:
name: warmer-schedule-namerate: rate(5 minutes)enabled: trueinput:
warmer: trueconcurrency: 1

Logs

Logs are automatically generated unless the log configuration option is set to false. Logs contain useful information beyond just invocation data. The warm field indicates whether or not the Lambda function was already warm when invoked. The lastAccessed field is the timestamp (in milliseconds) of the last time the function was accessed by a non-warming event. Similarly, the lastAccessedSeconds gives you a counter (in seconds) of how long it's been since it has been accessed. These can be used to determine if your concurrency can be lowered.

Sample log:

{action: 'warmer',// identifierfunction: 'my-test-function',// function nameid: '1531413096993-0568',// unique function instance idcorrelationId: '1531413096993-0568',// correlation idcount: 1,// function number of total concurrent e.g. 3 of 10concurrency: 2,// number of concurrent functions being invokedwarm: true,// was this function already warmlastAccessed: 1531413096995,// timestamp (in ms) of last non-warming accesslastAccessedSeconds: '25.6'// time since last non-warming access}

Sponsors

IOpipe

IOpipe is all about making it more fun to be a developer through the support of the open source serverless community. Sign up with IOpipe for free to get real-time visibility into the most detailed behaviors of your Lambda applications.

Contributing

I've created a number of custom scripts to do similar cold start mitigation, but I figured I'd share this more complete version to save everyone some time (including my future self). If you would like to contribute, please submit a PR or add issues for bug reports and feature ideas.

About

A module to optimize AWS Lambda function cold starts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Oct 1, 2025. It is now read-only.

Repository files navigation

Lambda Warmer

npmnpmBuild StatusCoverage Statusdependencies

A module to optimize AWS Lambda function cold starts

At a recent AWS Startup Day event in Boston, MA, Chris Munns, the Senior Developer Advocate for Serverless at AWS, discussed Cold Starts and how to mitigate them. According to Chris (although he acknowledged that it is a "hack") using the CloudWatch Events "ping" method is really the only way to do it right now. He gave a number of good tips on how to do this "correctly":

  • Don’t ping more often than every 5 minutes
  • Invoke the function directly (i.e. don’t use API Gateway to invoke it)
  • Pass in a test payload that can be identified as such
  • Create handler logic that replies accordingly without running the whole function

He also mentioned that if you want to keep several concurrent functions warm, that you need to invoke the same function multiple times with delayed executions. This prevents the system from reusing the same container.

You can read the key takeaways from his talk here.

Following these "best practices", I created Lambda Warmer. It is a lightweight module (with no dependencies) that can be added to your Lambda functions to manage "warming" events as well as handling automatic fan-out for initializing concurrent functions. Just instrument your code and schedule a "ping".

NOTE: Lambda Warmer will invoke the function multiple times using the AWS-SDK in order to scale concurrency (if you want to). Your functions MUST have lambda:InvokeFunction permissions so that they can invoke themselves. Following the Principle of Least Privilege, you should limit the Resource to the function itself, e.g.:

- Effect: "Allow"Action:
- "lambda:InvokeFunction"Resource: "arn:aws:lambda:us-east-1:{AWS-ACCOUNT-ID}:function:my-test-function"

If you'd like to know more about how Lambda Warmer works, and why you might (or might not) want to use it, read this Lambda Warmer: Optimize AWS Lambda Function Cold Starts post.

Installation

Install Lambda Warmer from NPM as a project dependency.

npm i lambda-warmer

Instrumenting your Lambda functions

Adding Lambda Warmer to your functions is simple. Require lambda-warmer outside of your main handler and then pass the event as the first argument into your declared variable. Lambda Warmer will return a resolved promise with either true, meaning this is a warming invocation, or false, this isn't a warming invocation.

If you're using async/await, you can await the result of Lambda Warmer and return if true. This will short circuit your function and prevent it from executing the rest of the main handler.

constwarmer=require('lambda-warmer')exports.handler=async(event)=>{// if a warming eventif(awaitwarmer(event))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

If you are using callbacks, use Lambda Warmer to start a promise chain and then make your handler logic conditional depending on its result.

constwarmer=require('lambda-warmer')exports.handler=(event,context,callback)=>{// Start a promise chainwarmer(event).then(isWarmer=>{// if a warming eventif(isWarmer){callback(null,'warmed')// else proceed with handler logic}else{callback(null,'Hello from Lambda')}})}

Configuration Options

You can send in a configuration object as the second parameter to change Lambda Warmer's default behavior. All of the settings are optional. Here is a sample configuration object.

{flag: 'warmer',concurrency: 'concurrency',test: 'test',log: true,correlationId: 'XXXXXXXXXXXXX',delay: 75}

flag (string)

Name of the event field used to notify Lambda Warmer that this is a "warming" invocation. Defaults to warmer.

concurrency (string)

Name of the event field used to specify the number of concurrent functions you'd like to warm. Defaults to concurrency.

test (string)

Name of the event field used to flag a warming invocation as a test. Defaults to test.

log (boolean)

Flag to control whether or not CloudWatch logs are automatically generated. Defaults to true.

correlationId (string)

Identifier that gets passed to all concurrent Lambda invocations. This can be used to group invocations within your logs. If no correlationId is passed, it will default to the id generated for the invoked function. Passing the context.awsRequestId is good practice.

delay (number)

Minimum amount of time (in milliseconds) for concurrent functions to run. Concurrent functions are invoked asynchronously. Setting a delay enforces Lambda to create multiple invocations. Defaults to 75 to attempt sub 100ms invocation times.

Example passing a configuration:

exports.handler=async(event,context)=>{// if a warming eventif(awaitwarmer(event,{correlationId: context.awsRequestId,delay: 50}))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

Warming your Lambda functions

Lambda Warmer facilitates the warming of your functions by analyzing invocation events and appropriately managing handler processing. It DOES NOT manage the periodic invocation of your functions. In order to keep your functions warm, you must create a CloudWatch Rule that invokes your functions on a predetermined schedule.

A rule that invokes your function should contain a Constant (JSON text) under the "Configure input" setting. The following is a sample event (using the default configuration and a concurrency of 3):

{"warmer":true,"concurrency":3}

The names of warmer and concurrency can be changed using the configuration option when instrumenting your code.

NOTE: Non-VPC functions are kept warm for approximately 5 minutes whereas VPC-based functions are kept warm for 15 minutes. Set your schedule for invocations accordingly. There is no need to ping your functions more often than the minimum warm time.

TIP: Preparing for traffic spikes

If your application experiences periodic traffic spikes throughout the day, you can set up multiple CloudWatch Rules that change the concurrency based on the time of day or day itself.

Using a SAM Template

To add a schedule event to your Lambda functions, you can add a Type: Schedule to the Events section of your function in a SAM template:

AWSTemplateFormatVersion: '2010-09-09'Transform: 'AWS::Serverless-2016-10-31'Resources:
MyFunction:
Type: 'AWS::Serverless::Function'Properties:
Handler: index.handlerRuntime: nodejs8.10CodeUri: 's3://my-bucket/function.zip'Events:
WarmingSchedule:
Type: ScheduleProperties:
Schedule: rate(5 minutes)Input: '{ "warmer":true,"concurrency":3 }'

Using the Serverless Framework

If you are using the Serverless Framework, you can include a schedule event for your functions using the following format:

myFunction:
name: myFunctionhandler: myFunction.handlerevents:
- schedule:
name: warmer-schedule-namerate: rate(5 minutes)enabled: trueinput:
warmer: trueconcurrency: 1

Logs

Logs are automatically generated unless the log configuration option is set to false. Logs contain useful information beyond just invocation data. The warm field indicates whether or not the Lambda function was already warm when invoked. The lastAccessed field is the timestamp (in milliseconds) of the last time the function was accessed by a non-warming event. Similarly, the lastAccessedSeconds gives you a counter (in seconds) of how long it's been since it has been accessed. These can be used to determine if your concurrency can be lowered.

Sample log:

{action: 'warmer',// identifierfunction: 'my-test-function',// function nameid: '1531413096993-0568',// unique function instance idcorrelationId: '1531413096993-0568',// correlation idcount: 1,// function number of total concurrent e.g. 3 of 10concurrency: 2,// number of concurrent functions being invokedwarm: true,// was this function already warmlastAccessed: 1531413096995,// timestamp (in ms) of last non-warming accesslastAccessedSeconds: '25.6'// time since last non-warming access}

Sponsors

IOpipe

IOpipe is all about making it more fun to be a developer through the support of the open source serverless community. Sign up with IOpipe for free to get real-time visibility into the most detailed behaviors of your Lambda applications.

Contributing

I've created a number of custom scripts to do similar cold start mitigation, but I figured I'd share this more complete version to save everyone some time (including my future self). If you would like to contribute, please submit a PR or add issues for bug reports and feature ideas.

About

A module to optimize AWS Lambda function cold starts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
This repository was archived by the owner on Oct 1, 2025. It is now read-only.

Repository files navigation

Lambda Warmer

npmnpmBuild StatusCoverage Statusdependencies

A module to optimize AWS Lambda function cold starts

At a recent AWS Startup Day event in Boston, MA, Chris Munns, the Senior Developer Advocate for Serverless at AWS, discussed Cold Starts and how to mitigate them. According to Chris (although he acknowledged that it is a "hack") using the CloudWatch Events "ping" method is really the only way to do it right now. He gave a number of good tips on how to do this "correctly":

  • Don’t ping more often than every 5 minutes
  • Invoke the function directly (i.e. don’t use API Gateway to invoke it)
  • Pass in a test payload that can be identified as such
  • Create handler logic that replies accordingly without running the whole function

He also mentioned that if you want to keep several concurrent functions warm, that you need to invoke the same function multiple times with delayed executions. This prevents the system from reusing the same container.

You can read the key takeaways from his talk here.

Following these "best practices", I created Lambda Warmer. It is a lightweight module (with no dependencies) that can be added to your Lambda functions to manage "warming" events as well as handling automatic fan-out for initializing concurrent functions. Just instrument your code and schedule a "ping".

NOTE: Lambda Warmer will invoke the function multiple times using the AWS-SDK in order to scale concurrency (if you want to). Your functions MUST have lambda:InvokeFunction permissions so that they can invoke themselves. Following the Principle of Least Privilege, you should limit the Resource to the function itself, e.g.:

- Effect: "Allow"Action:
- "lambda:InvokeFunction"Resource: "arn:aws:lambda:us-east-1:{AWS-ACCOUNT-ID}:function:my-test-function"

If you'd like to know more about how Lambda Warmer works, and why you might (or might not) want to use it, read this Lambda Warmer: Optimize AWS Lambda Function Cold Starts post.

Installation

Install Lambda Warmer from NPM as a project dependency.

npm i lambda-warmer

Instrumenting your Lambda functions

Adding Lambda Warmer to your functions is simple. Require lambda-warmer outside of your main handler and then pass the event as the first argument into your declared variable. Lambda Warmer will return a resolved promise with either true, meaning this is a warming invocation, or false, this isn't a warming invocation.

If you're using async/await, you can await the result of Lambda Warmer and return if true. This will short circuit your function and prevent it from executing the rest of the main handler.

constwarmer=require('lambda-warmer')exports.handler=async(event)=>{// if a warming eventif(awaitwarmer(event))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

If you are using callbacks, use Lambda Warmer to start a promise chain and then make your handler logic conditional depending on its result.

constwarmer=require('lambda-warmer')exports.handler=(event,context,callback)=>{// Start a promise chainwarmer(event).then(isWarmer=>{// if a warming eventif(isWarmer){callback(null,'warmed')// else proceed with handler logic}else{callback(null,'Hello from Lambda')}})}

Configuration Options

You can send in a configuration object as the second parameter to change Lambda Warmer's default behavior. All of the settings are optional. Here is a sample configuration object.

{flag: 'warmer',concurrency: 'concurrency',test: 'test',log: true,correlationId: 'XXXXXXXXXXXXX',delay: 75}

flag (string)

Name of the event field used to notify Lambda Warmer that this is a "warming" invocation. Defaults to warmer.

concurrency (string)

Name of the event field used to specify the number of concurrent functions you'd like to warm. Defaults to concurrency.

test (string)

Name of the event field used to flag a warming invocation as a test. Defaults to test.

log (boolean)

Flag to control whether or not CloudWatch logs are automatically generated. Defaults to true.

correlationId (string)

Identifier that gets passed to all concurrent Lambda invocations. This can be used to group invocations within your logs. If no correlationId is passed, it will default to the id generated for the invoked function. Passing the context.awsRequestId is good practice.

delay (number)

Minimum amount of time (in milliseconds) for concurrent functions to run. Concurrent functions are invoked asynchronously. Setting a delay enforces Lambda to create multiple invocations. Defaults to 75 to attempt sub 100ms invocation times.

Example passing a configuration:

exports.handler=async(event,context)=>{// if a warming eventif(awaitwarmer(event,{correlationId: context.awsRequestId,delay: 50}))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

Warming your Lambda functions

Lambda Warmer facilitates the warming of your functions by analyzing invocation events and appropriately managing handler processing. It DOES NOT manage the periodic invocation of your functions. In order to keep your functions warm, you must create a CloudWatch Rule that invokes your functions on a predetermined schedule.

A rule that invokes your function should contain a Constant (JSON text) under the "Configure input" setting. The following is a sample event (using the default configuration and a concurrency of 3):

{"warmer":true,"concurrency":3}

The names of warmer and concurrency can be changed using the configuration option when instrumenting your code.

NOTE: Non-VPC functions are kept warm for approximately 5 minutes whereas VPC-based functions are kept warm for 15 minutes. Set your schedule for invocations accordingly. There is no need to ping your functions more often than the minimum warm time.

TIP: Preparing for traffic spikes

If your application experiences periodic traffic spikes throughout the day, you can set up multiple CloudWatch Rules that change the concurrency based on the time of day or day itself.

Using a SAM Template

To add a schedule event to your Lambda functions, you can add a Type: Schedule to the Events section of your function in a SAM template:

AWSTemplateFormatVersion: '2010-09-09'Transform: 'AWS::Serverless-2016-10-31'Resources:
MyFunction:
Type: 'AWS::Serverless::Function'Properties:
Handler: index.handlerRuntime: nodejs8.10CodeUri: 's3://my-bucket/function.zip'Events:
WarmingSchedule:
Type: ScheduleProperties:
Schedule: rate(5 minutes)Input: '{ "warmer":true,"concurrency":3 }'

Using the Serverless Framework

If you are using the Serverless Framework, you can include a schedule event for your functions using the following format:

myFunction:
name: myFunctionhandler: myFunction.handlerevents:
- schedule:
name: warmer-schedule-namerate: rate(5 minutes)enabled: trueinput:
warmer: trueconcurrency: 1

Logs

Logs are automatically generated unless the log configuration option is set to false. Logs contain useful information beyond just invocation data. The warm field indicates whether or not the Lambda function was already warm when invoked. The lastAccessed field is the timestamp (in milliseconds) of the last time the function was accessed by a non-warming event. Similarly, the lastAccessedSeconds gives you a counter (in seconds) of how long it's been since it has been accessed. These can be used to determine if your concurrency can be lowered.

Sample log:

{action: 'warmer',// identifierfunction: 'my-test-function',// function nameid: '1531413096993-0568',// unique function instance idcorrelationId: '1531413096993-0568',// correlation idcount: 1,// function number of total concurrent e.g. 3 of 10concurrency: 2,// number of concurrent functions being invokedwarm: true,// was this function already warmlastAccessed: 1531413096995,// timestamp (in ms) of last non-warming accesslastAccessedSeconds: '25.6'// time since last non-warming access}

Sponsors

IOpipe

IOpipe is all about making it more fun to be a developer through the support of the open source serverless community. Sign up with IOpipe for free to get real-time visibility into the most detailed behaviors of your Lambda applications.

Contributing

I've created a number of custom scripts to do similar cold start mitigation, but I figured I'd share this more complete version to save everyone some time (including my future self). If you would like to contribute, please submit a PR or add issues for bug reports and feature ideas.

About

A module to optimize AWS Lambda function cold starts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Oct 1, 2025. It is now read-only.

Repository files navigation

Lambda Warmer

npmnpmBuild StatusCoverage Statusdependencies

A module to optimize AWS Lambda function cold starts

At a recent AWS Startup Day event in Boston, MA, Chris Munns, the Senior Developer Advocate for Serverless at AWS, discussed Cold Starts and how to mitigate them. According to Chris (although he acknowledged that it is a "hack") using the CloudWatch Events "ping" method is really the only way to do it right now. He gave a number of good tips on how to do this "correctly":

  • Don’t ping more often than every 5 minutes
  • Invoke the function directly (i.e. don’t use API Gateway to invoke it)
  • Pass in a test payload that can be identified as such
  • Create handler logic that replies accordingly without running the whole function

He also mentioned that if you want to keep several concurrent functions warm, that you need to invoke the same function multiple times with delayed executions. This prevents the system from reusing the same container.

You can read the key takeaways from his talk here.

Following these "best practices", I created Lambda Warmer. It is a lightweight module (with no dependencies) that can be added to your Lambda functions to manage "warming" events as well as handling automatic fan-out for initializing concurrent functions. Just instrument your code and schedule a "ping".

NOTE: Lambda Warmer will invoke the function multiple times using the AWS-SDK in order to scale concurrency (if you want to). Your functions MUST have lambda:InvokeFunction permissions so that they can invoke themselves. Following the Principle of Least Privilege, you should limit the Resource to the function itself, e.g.:

- Effect: "Allow"Action:
- "lambda:InvokeFunction"Resource: "arn:aws:lambda:us-east-1:{AWS-ACCOUNT-ID}:function:my-test-function"

If you'd like to know more about how Lambda Warmer works, and why you might (or might not) want to use it, read this Lambda Warmer: Optimize AWS Lambda Function Cold Starts post.

Installation

Install Lambda Warmer from NPM as a project dependency.

npm i lambda-warmer

Instrumenting your Lambda functions

Adding Lambda Warmer to your functions is simple. Require lambda-warmer outside of your main handler and then pass the event as the first argument into your declared variable. Lambda Warmer will return a resolved promise with either true, meaning this is a warming invocation, or false, this isn't a warming invocation.

If you're using async/await, you can await the result of Lambda Warmer and return if true. This will short circuit your function and prevent it from executing the rest of the main handler.

constwarmer=require('lambda-warmer')exports.handler=async(event)=>{// if a warming eventif(awaitwarmer(event))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

If you are using callbacks, use Lambda Warmer to start a promise chain and then make your handler logic conditional depending on its result.

constwarmer=require('lambda-warmer')exports.handler=(event,context,callback)=>{// Start a promise chainwarmer(event).then(isWarmer=>{// if a warming eventif(isWarmer){callback(null,'warmed')// else proceed with handler logic}else{callback(null,'Hello from Lambda')}})}

Configuration Options

You can send in a configuration object as the second parameter to change Lambda Warmer's default behavior. All of the settings are optional. Here is a sample configuration object.

{flag: 'warmer',concurrency: 'concurrency',test: 'test',log: true,correlationId: 'XXXXXXXXXXXXX',delay: 75}

flag (string)

Name of the event field used to notify Lambda Warmer that this is a "warming" invocation. Defaults to warmer.

concurrency (string)

Name of the event field used to specify the number of concurrent functions you'd like to warm. Defaults to concurrency.

test (string)

Name of the event field used to flag a warming invocation as a test. Defaults to test.

log (boolean)

Flag to control whether or not CloudWatch logs are automatically generated. Defaults to true.

correlationId (string)

Identifier that gets passed to all concurrent Lambda invocations. This can be used to group invocations within your logs. If no correlationId is passed, it will default to the id generated for the invoked function. Passing the context.awsRequestId is good practice.

delay (number)

Minimum amount of time (in milliseconds) for concurrent functions to run. Concurrent functions are invoked asynchronously. Setting a delay enforces Lambda to create multiple invocations. Defaults to 75 to attempt sub 100ms invocation times.

Example passing a configuration:

exports.handler=async(event,context)=>{// if a warming eventif(awaitwarmer(event,{correlationId: context.awsRequestId,delay: 50}))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

Warming your Lambda functions

Lambda Warmer facilitates the warming of your functions by analyzing invocation events and appropriately managing handler processing. It DOES NOT manage the periodic invocation of your functions. In order to keep your functions warm, you must create a CloudWatch Rule that invokes your functions on a predetermined schedule.

A rule that invokes your function should contain a Constant (JSON text) under the "Configure input" setting. The following is a sample event (using the default configuration and a concurrency of 3):

{"warmer":true,"concurrency":3}

The names of warmer and concurrency can be changed using the configuration option when instrumenting your code.

NOTE: Non-VPC functions are kept warm for approximately 5 minutes whereas VPC-based functions are kept warm for 15 minutes. Set your schedule for invocations accordingly. There is no need to ping your functions more often than the minimum warm time.

TIP: Preparing for traffic spikes

If your application experiences periodic traffic spikes throughout the day, you can set up multiple CloudWatch Rules that change the concurrency based on the time of day or day itself.

Using a SAM Template

To add a schedule event to your Lambda functions, you can add a Type: Schedule to the Events section of your function in a SAM template:

AWSTemplateFormatVersion: '2010-09-09'Transform: 'AWS::Serverless-2016-10-31'Resources:
MyFunction:
Type: 'AWS::Serverless::Function'Properties:
Handler: index.handlerRuntime: nodejs8.10CodeUri: 's3://my-bucket/function.zip'Events:
WarmingSchedule:
Type: ScheduleProperties:
Schedule: rate(5 minutes)Input: '{ "warmer":true,"concurrency":3 }'

Using the Serverless Framework

If you are using the Serverless Framework, you can include a schedule event for your functions using the following format:

myFunction:
name: myFunctionhandler: myFunction.handlerevents:
- schedule:
name: warmer-schedule-namerate: rate(5 minutes)enabled: trueinput:
warmer: trueconcurrency: 1

Logs

Logs are automatically generated unless the log configuration option is set to false. Logs contain useful information beyond just invocation data. The warm field indicates whether or not the Lambda function was already warm when invoked. The lastAccessed field is the timestamp (in milliseconds) of the last time the function was accessed by a non-warming event. Similarly, the lastAccessedSeconds gives you a counter (in seconds) of how long it's been since it has been accessed. These can be used to determine if your concurrency can be lowered.

Sample log:

{action: 'warmer',// identifierfunction: 'my-test-function',// function nameid: '1531413096993-0568',// unique function instance idcorrelationId: '1531413096993-0568',// correlation idcount: 1,// function number of total concurrent e.g. 3 of 10concurrency: 2,// number of concurrent functions being invokedwarm: true,// was this function already warmlastAccessed: 1531413096995,// timestamp (in ms) of last non-warming accesslastAccessedSeconds: '25.6'// time since last non-warming access}

Sponsors

IOpipe

IOpipe is all about making it more fun to be a developer through the support of the open source serverless community. Sign up with IOpipe for free to get real-time visibility into the most detailed behaviors of your Lambda applications.

Contributing

I've created a number of custom scripts to do similar cold start mitigation, but I figured I'd share this more complete version to save everyone some time (including my future self). If you would like to contribute, please submit a PR or add issues for bug reports and feature ideas.

About

A module to optimize AWS Lambda function cold starts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Oct 1, 2025. It is now read-only.

Repository files navigation

Lambda Warmer

npmnpmBuild StatusCoverage Statusdependencies

A module to optimize AWS Lambda function cold starts

At a recent AWS Startup Day event in Boston, MA, Chris Munns, the Senior Developer Advocate for Serverless at AWS, discussed Cold Starts and how to mitigate them. According to Chris (although he acknowledged that it is a "hack") using the CloudWatch Events "ping" method is really the only way to do it right now. He gave a number of good tips on how to do this "correctly":

  • Don’t ping more often than every 5 minutes
  • Invoke the function directly (i.e. don’t use API Gateway to invoke it)
  • Pass in a test payload that can be identified as such
  • Create handler logic that replies accordingly without running the whole function

He also mentioned that if you want to keep several concurrent functions warm, that you need to invoke the same function multiple times with delayed executions. This prevents the system from reusing the same container.

You can read the key takeaways from his talk here.

Following these "best practices", I created Lambda Warmer. It is a lightweight module (with no dependencies) that can be added to your Lambda functions to manage "warming" events as well as handling automatic fan-out for initializing concurrent functions. Just instrument your code and schedule a "ping".

NOTE: Lambda Warmer will invoke the function multiple times using the AWS-SDK in order to scale concurrency (if you want to). Your functions MUST have lambda:InvokeFunction permissions so that they can invoke themselves. Following the Principle of Least Privilege, you should limit the Resource to the function itself, e.g.:

- Effect: "Allow"Action:
- "lambda:InvokeFunction"Resource: "arn:aws:lambda:us-east-1:{AWS-ACCOUNT-ID}:function:my-test-function"

If you'd like to know more about how Lambda Warmer works, and why you might (or might not) want to use it, read this Lambda Warmer: Optimize AWS Lambda Function Cold Starts post.

Installation

Install Lambda Warmer from NPM as a project dependency.

npm i lambda-warmer

Instrumenting your Lambda functions

Adding Lambda Warmer to your functions is simple. Require lambda-warmer outside of your main handler and then pass the event as the first argument into your declared variable. Lambda Warmer will return a resolved promise with either true, meaning this is a warming invocation, or false, this isn't a warming invocation.

If you're using async/await, you can await the result of Lambda Warmer and return if true. This will short circuit your function and prevent it from executing the rest of the main handler.

constwarmer=require('lambda-warmer')exports.handler=async(event)=>{// if a warming eventif(awaitwarmer(event))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

If you are using callbacks, use Lambda Warmer to start a promise chain and then make your handler logic conditional depending on its result.

constwarmer=require('lambda-warmer')exports.handler=(event,context,callback)=>{// Start a promise chainwarmer(event).then(isWarmer=>{// if a warming eventif(isWarmer){callback(null,'warmed')// else proceed with handler logic}else{callback(null,'Hello from Lambda')}})}

Configuration Options

You can send in a configuration object as the second parameter to change Lambda Warmer's default behavior. All of the settings are optional. Here is a sample configuration object.

{flag: 'warmer',concurrency: 'concurrency',test: 'test',log: true,correlationId: 'XXXXXXXXXXXXX',delay: 75}

flag (string)

Name of the event field used to notify Lambda Warmer that this is a "warming" invocation. Defaults to warmer.

concurrency (string)

Name of the event field used to specify the number of concurrent functions you'd like to warm. Defaults to concurrency.

test (string)

Name of the event field used to flag a warming invocation as a test. Defaults to test.

log (boolean)

Flag to control whether or not CloudWatch logs are automatically generated. Defaults to true.

correlationId (string)

Identifier that gets passed to all concurrent Lambda invocations. This can be used to group invocations within your logs. If no correlationId is passed, it will default to the id generated for the invoked function. Passing the context.awsRequestId is good practice.

delay (number)

Minimum amount of time (in milliseconds) for concurrent functions to run. Concurrent functions are invoked asynchronously. Setting a delay enforces Lambda to create multiple invocations. Defaults to 75 to attempt sub 100ms invocation times.

Example passing a configuration:

exports.handler=async(event,context)=>{// if a warming eventif(awaitwarmer(event,{correlationId: context.awsRequestId,delay: 50}))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

Warming your Lambda functions

Lambda Warmer facilitates the warming of your functions by analyzing invocation events and appropriately managing handler processing. It DOES NOT manage the periodic invocation of your functions. In order to keep your functions warm, you must create a CloudWatch Rule that invokes your functions on a predetermined schedule.

A rule that invokes your function should contain a Constant (JSON text) under the "Configure input" setting. The following is a sample event (using the default configuration and a concurrency of 3):

{"warmer":true,"concurrency":3}

The names of warmer and concurrency can be changed using the configuration option when instrumenting your code.

NOTE: Non-VPC functions are kept warm for approximately 5 minutes whereas VPC-based functions are kept warm for 15 minutes. Set your schedule for invocations accordingly. There is no need to ping your functions more often than the minimum warm time.

TIP: Preparing for traffic spikes

If your application experiences periodic traffic spikes throughout the day, you can set up multiple CloudWatch Rules that change the concurrency based on the time of day or day itself.

Using a SAM Template

To add a schedule event to your Lambda functions, you can add a Type: Schedule to the Events section of your function in a SAM template:

AWSTemplateFormatVersion: '2010-09-09'Transform: 'AWS::Serverless-2016-10-31'Resources:
MyFunction:
Type: 'AWS::Serverless::Function'Properties:
Handler: index.handlerRuntime: nodejs8.10CodeUri: 's3://my-bucket/function.zip'Events:
WarmingSchedule:
Type: ScheduleProperties:
Schedule: rate(5 minutes)Input: '{ "warmer":true,"concurrency":3 }'

Using the Serverless Framework

If you are using the Serverless Framework, you can include a schedule event for your functions using the following format:

myFunction:
name: myFunctionhandler: myFunction.handlerevents:
- schedule:
name: warmer-schedule-namerate: rate(5 minutes)enabled: trueinput:
warmer: trueconcurrency: 1

Logs

Logs are automatically generated unless the log configuration option is set to false. Logs contain useful information beyond just invocation data. The warm field indicates whether or not the Lambda function was already warm when invoked. The lastAccessed field is the timestamp (in milliseconds) of the last time the function was accessed by a non-warming event. Similarly, the lastAccessedSeconds gives you a counter (in seconds) of how long it's been since it has been accessed. These can be used to determine if your concurrency can be lowered.

Sample log:

{action: 'warmer',// identifierfunction: 'my-test-function',// function nameid: '1531413096993-0568',// unique function instance idcorrelationId: '1531413096993-0568',// correlation idcount: 1,// function number of total concurrent e.g. 3 of 10concurrency: 2,// number of concurrent functions being invokedwarm: true,// was this function already warmlastAccessed: 1531413096995,// timestamp (in ms) of last non-warming accesslastAccessedSeconds: '25.6'// time since last non-warming access}

Sponsors

IOpipe

IOpipe is all about making it more fun to be a developer through the support of the open source serverless community. Sign up with IOpipe for free to get real-time visibility into the most detailed behaviors of your Lambda applications.

Contributing

I've created a number of custom scripts to do similar cold start mitigation, but I figured I'd share this more complete version to save everyone some time (including my future self). If you would like to contribute, please submit a PR or add issues for bug reports and feature ideas.

About

A module to optimize AWS Lambda function cold starts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
This repository was archived by the owner on Oct 1, 2025. It is now read-only.

Repository files navigation

Lambda Warmer

npmnpmBuild StatusCoverage Statusdependencies

A module to optimize AWS Lambda function cold starts

At a recent AWS Startup Day event in Boston, MA, Chris Munns, the Senior Developer Advocate for Serverless at AWS, discussed Cold Starts and how to mitigate them. According to Chris (although he acknowledged that it is a "hack") using the CloudWatch Events "ping" method is really the only way to do it right now. He gave a number of good tips on how to do this "correctly":

  • Don’t ping more often than every 5 minutes
  • Invoke the function directly (i.e. don’t use API Gateway to invoke it)
  • Pass in a test payload that can be identified as such
  • Create handler logic that replies accordingly without running the whole function

He also mentioned that if you want to keep several concurrent functions warm, that you need to invoke the same function multiple times with delayed executions. This prevents the system from reusing the same container.

You can read the key takeaways from his talk here.

Following these "best practices", I created Lambda Warmer. It is a lightweight module (with no dependencies) that can be added to your Lambda functions to manage "warming" events as well as handling automatic fan-out for initializing concurrent functions. Just instrument your code and schedule a "ping".

NOTE: Lambda Warmer will invoke the function multiple times using the AWS-SDK in order to scale concurrency (if you want to). Your functions MUST have lambda:InvokeFunction permissions so that they can invoke themselves. Following the Principle of Least Privilege, you should limit the Resource to the function itself, e.g.:

- Effect: "Allow"Action:
- "lambda:InvokeFunction"Resource: "arn:aws:lambda:us-east-1:{AWS-ACCOUNT-ID}:function:my-test-function"

If you'd like to know more about how Lambda Warmer works, and why you might (or might not) want to use it, read this Lambda Warmer: Optimize AWS Lambda Function Cold Starts post.

Installation

Install Lambda Warmer from NPM as a project dependency.

npm i lambda-warmer

Instrumenting your Lambda functions

Adding Lambda Warmer to your functions is simple. Require lambda-warmer outside of your main handler and then pass the event as the first argument into your declared variable. Lambda Warmer will return a resolved promise with either true, meaning this is a warming invocation, or false, this isn't a warming invocation.

If you're using async/await, you can await the result of Lambda Warmer and return if true. This will short circuit your function and prevent it from executing the rest of the main handler.

constwarmer=require('lambda-warmer')exports.handler=async(event)=>{// if a warming eventif(awaitwarmer(event))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

If you are using callbacks, use Lambda Warmer to start a promise chain and then make your handler logic conditional depending on its result.

constwarmer=require('lambda-warmer')exports.handler=(event,context,callback)=>{// Start a promise chainwarmer(event).then(isWarmer=>{// if a warming eventif(isWarmer){callback(null,'warmed')// else proceed with handler logic}else{callback(null,'Hello from Lambda')}})}

Configuration Options

You can send in a configuration object as the second parameter to change Lambda Warmer's default behavior. All of the settings are optional. Here is a sample configuration object.

{flag: 'warmer',concurrency: 'concurrency',test: 'test',log: true,correlationId: 'XXXXXXXXXXXXX',delay: 75}

flag (string)

Name of the event field used to notify Lambda Warmer that this is a "warming" invocation. Defaults to warmer.

concurrency (string)

Name of the event field used to specify the number of concurrent functions you'd like to warm. Defaults to concurrency.

test (string)

Name of the event field used to flag a warming invocation as a test. Defaults to test.

log (boolean)

Flag to control whether or not CloudWatch logs are automatically generated. Defaults to true.

correlationId (string)

Identifier that gets passed to all concurrent Lambda invocations. This can be used to group invocations within your logs. If no correlationId is passed, it will default to the id generated for the invoked function. Passing the context.awsRequestId is good practice.

delay (number)

Minimum amount of time (in milliseconds) for concurrent functions to run. Concurrent functions are invoked asynchronously. Setting a delay enforces Lambda to create multiple invocations. Defaults to 75 to attempt sub 100ms invocation times.

Example passing a configuration:

exports.handler=async(event,context)=>{// if a warming eventif(awaitwarmer(event,{correlationId: context.awsRequestId,delay: 50}))return'warmed'// else proceed with handler logicreturn'Hello from Lambda'}

Warming your Lambda functions

Lambda Warmer facilitates the warming of your functions by analyzing invocation events and appropriately managing handler processing. It DOES NOT manage the periodic invocation of your functions. In order to keep your functions warm, you must create a CloudWatch Rule that invokes your functions on a predetermined schedule.

A rule that invokes your function should contain a Constant (JSON text) under the "Configure input" setting. The following is a sample event (using the default configuration and a concurrency of 3):

{"warmer":true,"concurrency":3}

The names of warmer and concurrency can be changed using the configuration option when instrumenting your code.

NOTE: Non-VPC functions are kept warm for approximately 5 minutes whereas VPC-based functions are kept warm for 15 minutes. Set your schedule for invocations accordingly. There is no need to ping your functions more often than the minimum warm time.

TIP: Preparing for traffic spikes

If your application experiences periodic traffic spikes throughout the day, you can set up multiple CloudWatch Rules that change the concurrency based on the time of day or day itself.

Using a SAM Template

To add a schedule event to your Lambda functions, you can add a Type: Schedule to the Events section of your function in a SAM template:

AWSTemplateFormatVersion: '2010-09-09'Transform: 'AWS::Serverless-2016-10-31'Resources:
MyFunction:
Type: 'AWS::Serverless::Function'Properties:
Handler: index.handlerRuntime: nodejs8.10CodeUri: 's3://my-bucket/function.zip'Events:
WarmingSchedule:
Type: ScheduleProperties:
Schedule: rate(5 minutes)Input: '{ "warmer":true,"concurrency":3 }'

Using the Serverless Framework

If you are using the Serverless Framework, you can include a schedule event for your functions using the following format:

myFunction:
name: myFunctionhandler: myFunction.handlerevents:
- schedule:
name: warmer-schedule-namerate: rate(5 minutes)enabled: trueinput:
warmer: trueconcurrency: 1

Logs

Logs are automatically generated unless the log configuration option is set to false. Logs contain useful information beyond just invocation data. The warm field indicates whether or not the Lambda function was already warm when invoked. The lastAccessed field is the timestamp (in milliseconds) of the last time the function was accessed by a non-warming event. Similarly, the lastAccessedSeconds gives you a counter (in seconds) of how long it's been since it has been accessed. These can be used to determine if your concurrency can be lowered.

Sample log:

{action: 'warmer',// identifierfunction: 'my-test-function',// function nameid: '1531413096993-0568',// unique function instance idcorrelationId: '1531413096993-0568',// correlation idcount: 1,// function number of total concurrent e.g. 3 of 10concurrency: 2,// number of concurrent functions being invokedwarm: true,// was this function already warmlastAccessed: 1531413096995,// timestamp (in ms) of last non-warming accesslastAccessedSeconds: '25.6'// time since last non-warming access}

Sponsors

IOpipe

IOpipe is all about making it more fun to be a developer through the support of the open source serverless community. Sign up with IOpipe for free to get real-time visibility into the most detailed behaviors of your Lambda applications.

Contributing

I've created a number of custom scripts to do similar cold start mitigation, but I figured I'd share this more complete version to save everyone some time (including my future self). If you would like to contribute, please submit a PR or add issues for bug reports and feature ideas.

About

A module to optimize AWS Lambda function cold starts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages