AWS Amplify & AWS Lambda SnapStart activation: serverless Java with CRaC and CRIU
This article aims to help automate the activation of the SnapStart function, especially in case when Lambda is used with Java 11/17/21 environment in applications based on Amplify or deployed with CloudFormation.
Skipping definitions ofAWS Amplify, AWS Lambda, and AWS CloudFormation, we will stop on the statement that “cold starts” — are slow. It happens because it takes some time to reserve and prepare MicroVM to run our code.
However, Lambda terminates execution environments every few hours to allow for runtime updates and maintenance — even for functions that are invoked continuously
SnapStart in a nutshell
To improve cold starts of Java apps deployed to Lambda the AWS integrated and provided an interface for JVM feature named Coordinated Restore at Checkpoint (CRaC) by Azul. However, AWS named it SnapStart.
⚠️ To understand the underneath of JVM CRaC, I strongly suggest watching this awesome video. Want to dig more — CRaC’s roots originate from the CRIU project released in 2012.
What is the problem
In the case of AWS Lambda SnapStart, there are two steps required to start using it:
- Enabling. There are no blockers to enable it using CLI, SDK, SAM, or CF: guides are there.
- Activation. This step is trickier because it is required to publish a new version, explicitly. Thus, whatever invokes Lambda, API Gateway, SQS, EventBridge, or any other source, it has to specify ARN of that particular published version to invoke. Also, we don’t want to change ARN as it will force CloudFormation to recreate related IAM roles, policies that make the redeploy process very slow.
Solution(s)
Lambda alias can be used to invoke Function by constant ARN but it needs to be recreated for every newly published version. Thus, there are at least two approaches:
- Run 2 AWS CLI/SDK commands: 1. To publish new version 2. To update the alias.
- Update CloudFormation template accordingly, for every build.
We will consider approach #2 as in this case it is better to modify the CloudFrmation template as it reduces the complexity of consistency.
This is the approximate sample of how the CloudFormation template looks within the AWS Amplify project (/amplify/backend/function/…):
In this snippet, we defined three AWS resources:
- Function LambdaFunction
- Version LambdaFunctionVersionBLDVER54
- Alias LambdaFunctionAlias
That suffix BLDVER54 is a random sequence of characters that fits CF Name type rules, the purpose of it is to make AWS create a new Version and redefine Alias to use that Version. Therefore, the ARN of Alias will be a constant e.g.:
arn:aws:lambda:us-east-2:0123456789:function:myFunction-prod:live
That is pretty much it. The way how and when to change resource names depends on implemented CI pipeline.
Please, let me know if you need additional explanations or samples for particular CI.