Introduction
AWS Lambda SnapStart is a game-changing feature launched in 2022 and optimized in 2026 that reduces cold start times (cold starts) for Java Lambda functions by over 90% on average. Unlike traditional cold starts, where the runtime environment (JVM) initializes on every invocation, SnapStart creates a snapshot of a pre-initialized JVM stored immutably.
Why does it matter? In a serverless world, cold starts hurt user latency and increase costs (more invocations to compensate). For an e-commerce API, dropping from 2 seconds to 200 ms is transformative. This beginner tutorial walks you through it step by step: from a simple Java function to enabling SnapStart with AWS SAM, including concrete benchmarks. By the end, you'll have production-ready Lambdas. Estimated time: 20 minutes.
Prerequisites
- Free AWS account (with us-east-1 region for SnapStart)
- AWS CLI v2 installed and configured (
aws configure) - SAM CLI v1.100+ (
sam --version) - JDK 11 or 17 (x86_64, not ARM)
- Maven 3.9+ (for Java builds)
- Git to clone optional examples
Install and Verify SAM CLI
# Quick installation via official script (Linux/Mac)
# curl -L https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip -o sam.zip
# unzip sam.zip -d sam-installation
# sudo ./sam-installation/install
# Verification
sam --version
aws --version
# Configure AWS if not done
aws configure set region us-east-1
aws sts get-caller-identityThis script installs SAM CLI, the official tool for developing and deploying Lambdas locally. Check versions: SAM must be >=1.100 for SnapStart v2. The us-east-1 region is required since SnapStart isn't available everywhere; get-caller-identity confirms your IAM authentication.
Create the Base SAM Project
We'll use AWS SAM for its simplicity: a template.yaml that defines the CloudFormation stack. Create a 'hello-world' project in Java 17, x86_64 architecture, without SnapStart initially.
Initialize the SAM Project
sam init --runtime java17 --name snapstart-demo --app-template hello-world --location . --use-image
cd snapstart-demo
# Preview the generated template.yaml
cat template.yaml
# Initial build (creates .aws-sam)
sam buildsam init generates a complete boilerplate: Java handler, pom.xml for Maven, and template.yaml. --use-image uses containers for reproducible builds. sam build compiles the code into deployment-ready artifacts, creating the .aws-sam/build folder.
Basic Java Handler (Unoptimized)
package com.example;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import java.util.HashMap;
import java.util.Map;
public class Handler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
context.getLogger().log("COLD START détecté: " + context.getLogger().logGroupName());
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
.withHeaders(headers)
.withStatusCode(200)
.withBody("{\"message\": \"Hello sans SnapStart! Temps init: " + System.currentTimeMillis() + "\"}");
return response;
}
}This simple handler responds to an API Gateway request with JSON. It logs to detect cold starts (via logGroupName()). Copy-paste this code to replace the boilerplate; it simulates heavy work by logging the timestamp, perfect for measuring latencies.
Deploy Without SnapStart and Test
Note: Create an IAM role for SAM via sam deploy --guided. Note the generated API Gateway URL.
Initial Deployment (Without SnapStart)
# First guided deployment
sam deploy --guided --stack-name snapstart-demo --capabilities CAPABILITY_IAM --resolve-s3
# Retrieve the API Gateway URL (replace <stack> with snapstart-demo)
API_URL=$(aws cloudformation describe-stacks --stack-name snapstart-demo --query 'Stacks[0].Outputs[?OutputKey==`HelloWorldApi`].OutputValue' --output text)
echo "URL: $API_URL"
# Test cold start (wait 15min inactivity for cold)
curl "$API_URL/GET/" -w "%{time_total} secondes\n"sam deploy --guided creates the CloudFormation stack with an auto IAM role. The URL is extracted from outputs. curl -w measures total response time; after 15min inactivity, expect ~1-2s for classic cold start.
Enable SnapStart in the Template
Edit template.yaml to add SnapStart. Publish a $LATEST version, then a numbered version.
YAML Template with SnapStart Enabled
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 'snapstart-demo'
Globals:
Function:
Timeout: 20
Runtime: java17
Architectures:
- x86_64
MemorySize: 512
Environment:
Variables:
JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: com.example.Handler::handleRequest
Runtime: java17
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api
Properties:
Path: /{proxy+}
Method: any
SnapStart:
ApplyOn: PublishedVersions
Environment:
Variables:
JAVA_TOOL_OPTIONS: -Djava.awt.headless=true -XX:InitialRAMFraction=0.5 -XX:MaxRAMFraction=0.7 -XX:+UseContainerSupport
Metadata: sam-resource-id: HelloWorldFunction
Outputs:
HelloWorldApi:
Description: "API Gateway endpoint URL"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
HelloWorldFunction:
Description: "Hello World Lambda Function ARN"
Value: !GetAtt HelloWorldFunction.Arn
HelloWorldActiveVersion:
Description: "Version of Hello World Lambda being invoked"
Value: !Ref HelloWorldFunction
Key: SnapStart: ApplyOn: PublishedVersions enables SnapStart on published versions (not $LATEST). JAVA_TOOL_OPTIONS optimizes the JVM for containers (RAM, headless). Architectures: x86_64 is required. This generates a snapshot in ~3min after publishing.
Build, Deploy, and Test with SnapStart
# Build after template changes
sam build
# Deploy (updates the stack)
sam deploy --stack-name snapstart-demo --capabilities CAPABILITY_IAM --no-confirm-changeset --no-fail-on-empty-changeset
# Publish a version (required for SnapStart)
aws lambda publish-version --function-name snapstart-demo-HelloWorldFunction-1U5K5Z5Z5Z5Z --description "v1 SnapStart"
# Wait for snapshot (3-5min), update alias if needed
aws lambda update-alias --function-name snapstart-demo-HelloWorldFunction-1U5K5Z5Z5Z5Z --name prod --function-version 1
# Test cold start after 15min
curl "$API_URL/GET/" -w "%{time_total} secondes\n"
# Logs to confirm (no 'COLD START')
aws logs tail /aws/lambda/snapstart-demo-HelloWorldFunction --since 10mpublish-version creates an immutable version; SnapStart snapshot generates automatically. update-alias points 'prod' to the version. Cold start time drops to <300ms. logs tail confirms no cold start logs.
Best Practices
- Optimize JAVA_TOOL_OPTIONS: Use
-XX:MaxRAMFraction=0.7to cap heap at 70% RAM, avoiding long GC pauses. - Publish stable versions: SnapStart works only on published versions, not $LATEST; use aliases for prod.
- Monitor snapshots: Via CloudWatch > Lambda > Snapshots (size ~100MB, free up to 1GB/function).
- Test production-like: Use X-Ray for latency tracing; enable Provisioned Concurrency for bursty traffic.
- Clean up:
aws lambda delete-function --function-name arn...andaws cloudformation delete-stack --stack-name snapstart-demo.
Common Errors to Avoid
- ARM architecture: SnapStart is NOT supported on arm64; force
x86_64or getInvalidRuntimeerror. - No published version: Invocations on $LATEST ignore SnapStart; always
publish-version. - Unsupported region: Limited to us-east-1, eu-west-1, etc.; check AWS docs.
- JDK <11: Requires Java 11/17/21; snapshot fails otherwise.
Next Steps
- Official docs: AWS Lambda SnapStart
- Advanced benchmarks: Tools like
aws-lambda-power-tuning - Expert training: Check out our AWS Serverless courses at Learni
- GitHub repo: Fork aws-samples/aws-lambda-snapstart-samples