Introduction

If you use AWS Lambda in combination with Java runtimes, you will notice (or probably have already noticed) that one of the main setbacks is the cold start time. A cold start refers to the process where a Lambda is invoked for the first time and the Lambda has to be initialized. AWS needs to create a new function instance and spin it up with every initialization.

Depending on your environment and application size, it can take up to 10 seconds to complete the init phase. Especially when using frameworks such as Spring Boot where features like dependency injection and component scanning can take a lot of time to initialize. This is a delay that most want to avoid as it significantly slows down your application flow in some situations. Do mind that this is only during the init phase; once the Lambda instance is running, the cold start process is over until the next time your Lambda needs to be instantiated again.

Lambda execution lifecycle Lambda execution environment lifecycle - without SnapStart - Best practices of advanced serverless developers (AWS re:Invent 2021)

AWS has always recognized the problem and now comes with a solution called Lambda SnapStart.

What is SnapStart?

Introduced at AWS re:Invent 2022, AWS Lambda SnapStart is the newest feature to eliminate the cold start problem by initializing the function when you publish a new version of a Lambda. It takes a snapshot, through Firecracker which AWS uses to run Lambda and Fargate, encrypts and caches it so it can be instantly accessed whenever it is required. When a Lambda is invoked and needs to set up a new instance, it will simply use the cached snapshot, which greatly improves startup times (officially up to 10x).

Versions

By default, SnapStart is disabled. You can enable it, but only for published Lambda versions. This means that it only works for versions that are published on the AWS account and that it is not implemented on the $LATEST tag. If you want to make use of Lambda SnapStart, be sure to do so on a published version. The snapshot of your Lambda is created upon the version publishing process.

SnapStart overview SnapStart overview - snapshot gets created during version publishing - AWS Lambda SnapStart (AWS re:Invent 2022)

Pricing

The SnapStart feature comes with AWS Lambda and has no additional pricing.

Limitations

While SnapStart is a great feature and can save time in Lambda cold starts, it also comes with its limitations. SnapStart currently does not support the following features and services:

Uniqueness

SnapStart always requires your snapshot to be unique. This means that if you have initialization code that generates unique content, it might not always be unique in the snapshot once it is restored in other Lambda invocations. The goal is to generate this content after the initialization process, so it is not part of the snapshot. Luckily, AWS has provided a documentation page in which they provide best practices on how to tackle that problem. They even came up with a SpotBugs plugin which finds potential issues in your code that could prevent SnapStart from working correctly.

Networking

Network connections are not being shared across different environments. Thus, if network connections (for example, to other AWS services such as an RDS or SQS) are instantiated in the initialization phase, they will not be shared and will most likely fail when the snapshot is being used later again. Although most popular frameworks have automatic database connection retries, it is worth the time to make sure that it works correctly.

Ephemeral data

Data that is fetched or temporary (for example a password or secret) should be fetched after the initialization phase. Otherwise, it will save the secret in the snapshot, meaning that authentication failures (and security risks) might occur once the initial secret value has expired or has been changed.

Using SnapStart

To investigate the improvement in cold start execution time when using AWS Lambda SnapStart, we wrote a simple Lambda function in Java 11 using Spring Cloud Function. This Lambda function, when invoked, will retrieve some JSON data from a dummy REST API and return it to the user. The code can be found on Github.

We made use of the AWS Serverless Application Model (SAM) to build our Lambda function and deploy it to AWS. Enabling the SnapStart feature can be easily done by adding the following two lines to the Properties section of the Lambda function resource in the template.yaml file used by AWS SAM:

SnapStart:
  ApplyOn: PublishedVersions

We started by invoking our Lambda function’s unpublished version ($LATEST), in which case SnapStart is not used, and received the following summary from AWS:

Summary lambda without SnapStart

We can observe an Init duration of around 2.7s, i.e. the time that is spent initializing the execution environment for our Lambda function.

Next, we manually published a new version of our Lambda function using the AWS Console. This can be done by navigating to the Versions tab of our Lamdba function and pressing the Publish new version button.

Lambda function verions Versions tab listing all published versions of a Lambda function.

Invoking this newly published version provides us with the following summary:

Summary lambda with SnapStart

In this case, we can see SnapStart is used. The initialization of the execution environment, represented by the Init duration we saw earlier, now happens when publishing the new version. Only the restoration of the snapshot, represented by the Restore duration, is performed now.

It is quite clear that using Lambda SnapStart is advantageous in most cases. We managed to decrease the cold start execution time of our Lambda function from almost 5s (Init duration + Duration) to around 2.6s (Restore duration + Duration), just by enabling this feature.

Conclusion

SnapStart is a great feature and can save a lot of time in your application flow. It’s a feature that should have been present already as it comes a bit too late. But now that it is here, Java developers should take measures in order to implement this as it can save a lot of time in cold-starting their Java Lambdas. We would have liked to see it implemented by default when you create a version, but sadly, this is not the case (yet). It comes only for Java, which is understandable as Java Lambdas face this obstacle the most. Still, we certainly won’t be surprised if AWS decides to release this feature for other languages and/or frameworks.

Altogether we can definitely recommend using this new feature for your Java Lambdas.

Yolan Vloeberghs is a Java and Cloud engineer with a sharpened focus on all things related to cloud, specifically AWS. He loves to play around with various technologies and frameworks and is very passionated and eager to learn about everything related to cloud-native development.

Robbe is a Java Developer with a strong interest in back-end and cloud development. He is curious by nature, so continuous learning is very important to him.