This chapter covers AWS Lambda SnapStart for Java functions, a feature introduced to dramatically reduce cold start latency for Java-based serverless applications. For the DVA-C02 exam, understanding SnapStart is critical because it addresses one of the most common performance challenges with Java on Lambda—cold starts that can exceed 5 seconds. While this is a relatively niche topic, it appears in questions about optimizing Lambda performance, especially in the 'Development' domain (Objective 1.1: Write code that optimizes performance of AWS Lambda functions). Expect 1-2 questions that test your knowledge of SnapStart's mechanism, configuration, and best practices.
Jump to a section
Imagine you're playing a complex video game that takes 5 minutes to load a new level because it has to initialize all the game engine systems, load textures, compile shaders, and set up the world state. This is like a Java Lambda function's cold start, where the JVM must initialize, load classes, and execute static initializers. SnapStart works like the game's 'quick save' feature: you play through the initial setup once, save that exact memory state to disk, and then for every subsequent playthrough, you load the saved state directly instead of going through the full initialization. The game resumes from the exact point you saved, just like Lambda SnapStart restores the JVM heap from a snapshot. The snapshot includes the initialized JVM, loaded classes, and any warmed caches. However, any randomness or unique identifiers generated during initialization (like cryptographic keys) are also captured, which can cause problems if they are reused—similar to how loading a saved game might reset a random encounter that was already triggered. To handle this, you can use the Lambda runtime hooks to run code after the snapshot is taken but before it is used, allowing you to re-randomize or refresh those values for each new invocation.
What is Lambda SnapStart?
AWS Lambda SnapStart is a feature that reduces cold start times for Java functions by caching a pre-initialized JVM snapshot. When you enable SnapStart on a Java function (Java 11 or later), Lambda takes a snapshot of the function's memory and disk state after the initialization code runs but before the handler is invoked. Subsequent invocations then resume from this snapshot, skipping the JVM startup, class loading, and static initialization phases. This can reduce cold start latency from several seconds to under 200 milliseconds.
Why SnapStart Exists
Java functions on Lambda suffer from high cold start latency because the JVM must:
Load and verify classes
Execute static initializers
Initialize the runtime
Set up dependency injection frameworks (e.g., Spring)
These steps can take 2-5 seconds or more. SnapStart eliminates this overhead by capturing the state after initialization and reusing it.
How SnapStart Works Internally
SnapStart leverages the Linux fork() system call and the CRIU (Checkpoint/Restore In Userspace) project. The process is:
Provisioning Phase: When you publish a new function version with SnapStart enabled, Lambda provisions a sandbox, runs your initialization code (the code outside the handler), and then creates a checkpoint of the entire process (memory, file descriptors, etc.) using CRIU. This checkpoint is stored as an encrypted snapshot.
Invocation Phase: When a new invocation arrives, Lambda restores the snapshot using CRIU's restore functionality. This creates a new process that is an exact copy of the original at the point of snapshot. The handler then executes immediately.
3. Runtime Hooks: Lambda provides two hooks that run during the snapshot lifecycle:
- beforeCheckpoint: Runs before the snapshot is taken. Use it to free resources, close connections, or finalize initialization.
- afterRestore: Runs after the snapshot is restored but before the handler. Use it to re-establish connections, refresh secrets, or re-randomize state.
These hooks are implemented by implementing the com.amazonaws.services.lambda.runtime.snapstart.SnapStart interface or using the @SnapStart annotation.
Key Components and Defaults
Supported Runtimes: Java 11 and Java 17 (Corretto, Amazon Linux 2).
Snapshot Storage: Snapshots are stored encrypted at rest using AWS KMS (default AWS managed key or customer managed key).
Snapshot Size: The snapshot includes memory and /tmp directory contents. There is no explicit size limit, but the snapshot must fit within the function's memory limit (128 MB to 10,240 MB).
Pricing: There is no additional charge for SnapStart beyond standard Lambda pricing.
Function Versions: SnapStart is only available on function versions (not $LATEST). You must publish a version to use SnapStart.
Concurrency: SnapStart supports provisioned concurrency. The snapshot is restored to each provisioned instance.
Ephemeral Storage: SnapStart captures the /tmp directory. This means any files written during initialization are part of the snapshot.
Configuration and Verification
To enable SnapStart via the AWS CLI:
aws lambda update-function-configuration --function-name my-function --snap-start ApplyOn=PublishedVersionsTo verify:
aws lambda get-function-configuration --function-name my-function --query 'SnapStart'Output:
{
"ApplyOn": "PublishedVersions",
"OptimizationStatus": "Optimized"
}When you publish a new version, the snapshot is created. The OptimizationStatus field indicates whether the snapshot was successfully created.
Interaction with Related Technologies
Provisioned Concurrency: SnapStart works with provisioned concurrency. When you enable provisioned concurrency on a SnapStart-enabled version, Lambda restores the snapshot to each provisioned instance. This can reduce the time to warm provisioned instances.
VPC: SnapStart works with VPC-enabled functions. The snapshot includes network connections? Actually, snapshots do not preserve network connections. You must re-establish them in afterRestore.
AWS X-Ray: SnapStart is compatible with X-Ray tracing. However, traces may show reduced initialization time.
Lambda Extensions: SnapStart is compatible with Lambda extensions, but extensions must be designed to handle snapshot/restore.
Best Practices and Pitfalls
Avoid Non-Deterministic Initialization: Any randomness during initialization (e.g., generating UUIDs, cryptographic keys) is captured in the snapshot. This means all invocations from the same snapshot will use the same random values. Use afterRestore to regenerate them.
Re-establish Connections: Database connections, HTTP connections, etc., are not preserved across snapshots. Close them in beforeCheckpoint and reopen in afterRestore.
File Handles: Open file handles are not preserved. Close files before checkpoint.
Threads: SnapStart does not capture thread states. Ensure no threads are running at checkpoint time.
Security: Snapshots are encrypted. Use a customer managed KMS key for additional control.
Testing: Test with real traffic to ensure no state-related bugs.
Exam Focus Points
SnapStart is only available for Java 11 and Java 17 (Corretto).
SnapStart is only supported on published function versions, not $LATEST.
The beforeCheckpoint hook runs before the snapshot; afterRestore runs after restore.
SnapStart does not preserve network connections, open files, or thread states.
SnapStart can reduce cold start latency from seconds to sub-second.
Provisioned concurrency can be used with SnapStart.
SnapStart is not available for other languages (Python, Node.js, etc.).
Enable SnapStart on Function
First, you must enable SnapStart on your Lambda function by updating its configuration. You set the `SnapStart` property to `ApplyOn=PublishedVersions`. This tells Lambda that when you publish a new version, it should create a snapshot of the initialization state. This step is done via the AWS Console, CLI, or SDK. The function must use Java 11 or 17 runtime. Note that SnapStart cannot be enabled on the `$LATEST` alias—only on numbered versions.
Publish a Function Version
After enabling SnapStart, you publish a new version of the function. This triggers the provisioning phase. Lambda creates a new execution environment (sandbox), runs the function's initialization code (code outside the handler), and then takes a snapshot of the entire process memory and disk state using CRIU. The snapshot is stored encrypted. The initialization code includes static initializers, dependency injection setup, and any code in the constructor or static blocks.
Run beforeCheckpoint Hook
If you have implemented the `beforeCheckpoint` hook, it runs immediately before the snapshot is taken. This is your opportunity to close database connections, release network sockets, flush buffers, and perform any cleanup. The hook must complete within the Lambda timeout limit. If it fails, the snapshot creation fails and the function version is not optimized. This hook is optional but strongly recommended for functions with external connections.
Take Snapshot with CRIU
Lambda uses CRIU (Checkpoint/Restore In Userspace) to capture the entire process state. CRIU freezes the process, dumps its memory pages, open file descriptors (except those that cannot be checkpointed), and CPU registers to a file. This snapshot is compressed and stored in an internal S3 bucket, encrypted with a KMS key. The snapshot includes the contents of `/tmp`. The process is then terminated. The snapshot is associated with the function version.
Invoke Function from Snapshot
When a new invocation arrives for a SnapStart-enabled function version, Lambda restores the snapshot using CRIU's restore functionality. A new process is created that is an exact copy of the original at the point of snapshot. The `afterRestore` hook runs immediately after restore, allowing you to re-establish connections, refresh credentials, or re-randomize state. Then the handler executes. This process typically takes under 200ms, compared to seconds for a full cold start.
Enterprise Scenario 1: High-Throughput API with Java Spring Boot
A financial services company runs a REST API on Lambda using Spring Boot. Cold starts were causing 5-second latency spikes, violating their SLA of 500ms. They enabled SnapStart, which reduced cold starts to ~200ms. They implemented beforeCheckpoint to close database connections (using HikariCP) and afterRestore to reinitialize the connection pool. They also used afterRestore to refresh a cached JWT signing key that was generated during initialization, preventing key reuse across invocations. The snapshot size was ~300MB. They also enabled provisioned concurrency for peak hours, which restored snapshots to warm instances instantly.
Enterprise Scenario 2: Data Processing with Heavy Initialization
A media company processes video metadata using a Java Lambda that loads a large ML model (1GB) from /tmp during initialization. Without SnapStart, every cold start took 10 seconds because of model loading. SnapStart captured the model in memory and /tmp, reducing cold starts to 300ms. They used beforeCheckpoint to flush any temporary files and afterRestore to verify model integrity. One issue they encountered: the model's random seed was captured in the snapshot, causing all invocations to produce identical results. They fixed this by re-seeding the random number generator in afterRestore.
Common Misconfigurations
Forgetting to close connections: If you don't close database connections in beforeCheckpoint, the snapshot will contain stale connections that fail after restore. This leads to 'broken pipe' errors.
Using $LATEST: Developers often test SnapStart on $LATEST and wonder why it doesn't work. SnapStart only applies to published versions.
Not re-randomizing: Many forget to regenerate random numbers or UUIDs in afterRestore, leading to security issues or data collisions.
Snapshot too large: If initialization writes large files to /tmp, the snapshot can become huge, increasing restore time and cost.
DVA-C02 Exam Focus on SnapStart
The DVA-C02 exam tests SnapStart under Objective 1.1: Write code that optimizes performance of AWS Lambda functions. Specific areas:
SnapStart mechanism: Understand that it uses CRIU to snapshot the JVM after initialization.
Runtime hooks: Know beforeCheckpoint and afterRestore and their purposes.
Supported runtimes: Only Java 11 and Java 17 (Corretto).
Version requirement: Only works on published versions, not $LATEST.
State limitations: SnapStart does not preserve network connections, open files, or thread states.
Common Wrong Answers and Why
"SnapStart works with all Lambda runtimes." – Wrong. Only Java 11 and 17. Candidates confuse it with general Lambda optimizations.
"SnapStart reduces cold start for every invocation." – Wrong. It only helps cold starts (first invocation after idle). Warm starts are unaffected.
"SnapStart automatically refreshes database connections." – Wrong. You must manually re-establish connections in afterRestore.
"SnapStart can be enabled on $LATEST." – Wrong. Only on published versions.
Specific Values and Terms
Java 11 and 17 (Corretto)
CRIU (Checkpoint/Restore In Userspace)
PublishedVersions (the ApplyOn value)
beforeCheckpoint and afterRestore hooks
Snapshot encryption: AWS KMS (default or customer managed)
Edge Cases
If the initialization code fails, the snapshot is not created and the function version remains non-optimized.
SnapStart is not compatible with Lambda functions that use the RequestResponse invocation type? Actually it works with both synchronous and asynchronous invocations.
If you update the function code, you must publish a new version to create a new snapshot.
SnapStart does not affect provisioned concurrency initialization time? Actually it does – provisioned concurrency uses the snapshot to restore instances faster.
How to Eliminate Wrong Answers
If an answer mentions non-Java runtimes, eliminate it.
If an answer suggests SnapStart handles network connections automatically, eliminate it.
If an answer says SnapStart works on $LATEST, eliminate it.
If an answer claims SnapStart eliminates all cold start latency, it's wrong because restore time is still non-zero.
SnapStart is only available for Java 11 and Java 17 (Corretto) runtimes.
SnapStart must be enabled on a function version (not $LATEST) via the `ApplyOn=PublishedVersions` setting.
Lambda uses CRIU (Checkpoint/Restore In Userspace) to create and restore snapshots.
Use `beforeCheckpoint` to close connections and `afterRestore` to re-establish them.
SnapStart does not preserve network connections, open files, or thread states.
SnapStart reduces cold start latency from seconds to typically under 200ms.
SnapStart can be combined with provisioned concurrency for even faster warm starts.
Random values generated during initialization are captured; regenerate them in `afterRestore`.
These come up on the exam all the time. Here's how to tell them apart.
Lambda SnapStart
Reduces cold start by restoring a pre-initialized snapshot
No additional cost for SnapStart itself
Works only with Java 11 and 17
Snapshot is created once per function version
Does not keep instances warm; restores on demand
Provisioned Concurrency
Reduces cold start by keeping a number of instances pre-warmed
Incurs cost for the provisioned instances even when idle
Works with all Lambda runtimes
Instances are kept warm continuously
Provides predictable latency with no restore overhead
Mistake
SnapStart reduces cold start for all Lambda runtimes.
Correct
SnapStart is only available for Java 11 and Java 17 (Corretto) runtimes. Other languages like Python, Node.js, or .NET do not support SnapStart.
Mistake
SnapStart eliminates cold start latency entirely.
Correct
SnapStart reduces cold start time from seconds to typically under 200ms, but there is still a small overhead for restoring the snapshot. It does not make cold starts instant.
Mistake
SnapStart automatically re-establishes network connections after restore.
Correct
Network connections are not preserved in the snapshot. You must implement the `afterRestore` hook to re-establish connections to databases, APIs, etc.
Mistake
SnapStart can be enabled on the $LATEST version of a function.
Correct
SnapStart only applies to published function versions. You cannot enable it on the $LATEST alias. You must publish a version after enabling SnapStart.
Mistake
SnapStart captures the entire function state including threads and open files.
Correct
SnapStart does not preserve thread states or open file handles. You must ensure no threads are running and close files before the snapshot using `beforeCheckpoint`.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
You can enable SnapStart by updating the function configuration to set `SnapStart.ApplyOn` to `PublishedVersions`. This can be done via the AWS Console (under 'General configuration' -> 'SnapStart'), CLI (`aws lambda update-function-configuration --function-name my-function --snap-start ApplyOn=PublishedVersions`), or SDK. After enabling, you must publish a new version of the function for the snapshot to be created. The function must use Java 11 or 17 runtime.
`beforeCheckpoint` runs before the snapshot is taken. Use it to close database connections, release network sockets, flush buffers, and perform cleanup. `afterRestore` runs after the snapshot is restored but before the handler executes. Use it to re-establish connections, refresh credentials, regenerate random values, or re-initialize state that cannot be preserved. Both hooks are optional but recommended for functions with external dependencies.
Yes, SnapStart works with VPC-enabled functions. However, network connections to resources inside the VPC are not preserved in the snapshot. You must re-establish them in the `afterRestore` hook. The snapshot itself is stored and restored outside the VPC, but the restored function runs within the VPC as configured.
Yes, SnapStart is compatible with provisioned concurrency. When you enable provisioned concurrency on a SnapStart-enabled function version, Lambda restores the snapshot to each provisioned instance. This can reduce the time it takes to initialize provisioned instances, as they start from the snapshot rather than a full cold start.
If the `beforeCheckpoint` hook fails (throws an exception), the snapshot creation fails. The function version will not be optimized (the `OptimizationStatus` will be `NotOptimized`). You must fix the hook and publish a new version to create a successful snapshot. The function code remains unchanged, but the version will not benefit from SnapStart.
No, SnapStart is only available for Java 11 and Java 17 (Corretto) runtimes. Java 8 is not supported. You must migrate to Java 11 or later to use SnapStart.
SnapStart does not affect the handler execution time (warm starts). It only reduces cold start time. The handler runs normally after the snapshot is restored. However, if your `afterRestore` hook is slow, it can add to the total invocation time. Keep `afterRestore` lightweight.
You've just covered Lambda SnapStart for Java Functions — now see how well it sticks with free DVA-C02 practice questions. Full explanations included, no account needed.
Done with this chapter?