At re:Invent 2022 in Las Vegas AWS has announced a new feature for AWS Lambda that allows you to reduce your lambda startup times for Java based functions – SnapStart. With this post you are going to understand how the feature works, how it can be enabled, how you will benefit from it and how it will reduce your costs for AWS lambda. The functionality needs to be activated (“opt-in”) and has a few pre-requites for your functions that I will also share with you. It is currently only available if you use Java (Corretto 11) as a runtime. Other runtimes (e.g. Python, Typescript) will be available at a later date.
What is AWS Lambda SnapStart – and reduced latency for cold starts?
SnapStart is a new feature that helps to improve the “cold starts” of your lambda function.
AWS Lambda is a serverless possibility to execute code or a part of your application on AWS. The service can be used with different languages – Typescript/Node.JS, Python, Golang, … and Java. Lambda can be seen as “function as a service” with very convenient integration possibilities. Under the hood of Lambda, AWS has a very quick and mature provisioning system that brings up a container that executes your code. AWS Lambda as a “serverless” service allows you to not pay anything for your deployed infrastructure if it is not being used – this is also known as “scale-to-zero”. AWS Lambda is billed by “usage time” of the capacity that your lambda functions use – a lambda function can run up to 15min, but most of the lambda functions execute within a few seconds. Because of the “scale-to-zero” functionality, there is not always a “running” version of your code on AWS. This is where AWS distinguishes between “cold starts” and “warm starts” for your lambda function.
When SnapStart is enabled, function code is initialized once when a function version is published. Lambda then takes a snapshot of the memory and disk state of the initialized execution environment, persists the encrypted snapshot, and caches it for low-latency access. When the function is first invoked or subsequently scaled, Lambda resumes new execution environments from the persisted snapshot instead of initializing from scratch, avoiding several seconds of variable latency.
So – why is SnapStart an “opt-in” feature?
AWS has decided to not make SnapStart a default functionality of AWS Lambda, because there are certain pre-requisites for being able to use this new functionality.
The most important one is that the code executed as part of the lambda function cannot rely on the “randomization” features of Java, and this has implications for the code that you write. Please read the SnapChart documentation for further details – the FAQ is very detailed on this. This does not only include the code that YOU write as part of your lambda function but also the code of every library that you use as part of your code.
Other things to consider are that you cannot rely on network connections that you created/set up during the initialization of your code to be still valid and available when your function is resumed from a snapshort. This means that you will need to verify any network connections (e.g. connections for a backend database) before you actually use it.
Any ephemeral data that you rely on can be invalid when your function is resumed from a snapshot – and this means that you will need to ensure that any ephemeral data is still valid if you want to access it. This could be temporary credentials, machine learning models or just temporary data that you use within your function.
In it’s documentation, AWS also provides a bunch of examples and best practices to make sure that your code is “SnapSafe” and can work with this new functionality without causing problems.
How do you activate AWS Lambda SnapStart?
You can activate AWS Lambda either in the AWS console or through the AWS cli. Surprisingly this feature also comes with direct CloudFormation, CDK and SDK support. Please remember that after activating it, you will need to create a new version of lambda function that you want to test.
Further details can be found in the AWS documentation.
Let’s go back to the “teaser” of this post – How can YOU safe costs with this functionality?
For Lambda functions you are based on the number of requests for your functions, the allocated memory and the time that it takes to execute your java code. The duration is calculated from the time your code begins executing until it returns or otherwise terminated, rounded up to the nearest 1ms.
The total duration is a combination of the initialization code (in the constructor of your function) and the code in the “handler”.
With SnapStart enabled, the “initialization code” / phase is moved to the provisioning of the function (when you set it up) – and when the function is executed the “initialization phase” is replaced by re-starting the function from the already created snapshot.
This means that for functions, that have an intense “initialization” phase the potential savings are bigger than for functions that run all of their code in the “handler”. More details around how to optimize your Java functions for cold starts can be found in this blog.
Let’s do a few calculations on how this helps us to safe money:
The table assumes that the initialization phase is reduced to 25 milliseconds (which is not technically correct according to the AWS documentation, but its as close as I can guess today).
What this table shows is that the SnapStart feature will help us to reduce our costs for AWS Lambda significantly, if we have Lambda functions that have a longer initialization time than “handler” execution time.
Overall I calculated between 10% and 60% savings with this feature, depending on your use case. Please be aware: This is calculation/guessing only, I have not yet measured that during a test! For further analysis and details you will need to analyze your current performance metrics of your lambda functions and perform additional tests and calculations.
Before you can use the feature, as already mentioned, you will need to verify that your lambda code is “SnapSafe”.