Optimizing Lambda performance sits squarely in the DVA-C02 Troubleshooting and Optimization domain (18% of the exam), whose objectives include “optimize applications by using AWS services and features.” Cold starts are the classic version of that problem, and AWS keeps adding features to fix them. SnapStart is the one candidates most often get wrong, because the exam-prep folklore is out of date — it started as a Java-only feature, and plenty of study notes still say so. As of 2026 that is no longer true, and the details AWS added along the way (which runtimes, what it costs, what breaks) are exactly the kind of thing a well-written optimization question probes.
This guide is a focused deep dive on SnapStart specifically. It assumes you already understand why cold starts happen — the execution environment lifecycle, the Init phase, and how provisioned concurrency keeps environments warm are all covered in the Lambda versions, aliases, and concurrency guide, and this article deliberately does not re-teach them. Here we answer a narrower question the exam cares about: what is SnapStart, how does it change the lifecycle, and when do you choose it?
What SnapStart Actually Does
The biggest contributor to cold-start latency is the initialization work Lambda does before your handler runs for the first time in a new execution environment: loading your code, starting the runtime, and running your initialization code (framework startup, dependency injection, connection setup). For a heavy Java or .NET application this can take several seconds.
SnapStart moves that work out of the invocation path. When you publish a function version with SnapStart enabled, Lambda:
- Runs your initialization code once, ahead of time.
- Takes a Firecracker microVM snapshot of the memory and disk state of that fully initialized execution environment.
- Encrypts the snapshot and caches it, keeping several copies for resiliency and automatically patching them with runtime and security updates.
Then, when the function version is first invoked — and as invocations scale up — Lambda resumes new execution environments from the cached snapshot instead of initializing them from scratch. The expensive init already happened at publish time, so startup can drop from seconds to as low as sub-second, typically with no changes to your function code.
The key mental shift for the exam: with SnapStart, initialization happens when you publish a version, not when the function is invoked. That single sentence explains almost everything else — the versioning requirement, the pricing, the logging changes, and the state hazards.
The Versions and Aliases Requirement
Because the snapshot is created at publish time, SnapStart only works on published function versions and aliases that point to versions. You cannot use SnapStart on the unpublished $LATEST version.
This connects SnapStart directly to the versioning and alias workflow you already know: enable SnapStart, publish a version (which triggers snapshot creation), point an alias at that version, and invoke through the alias. If a question shows SnapStart enabled but the function being invoked as $LATEST and asks why there is no improvement, the answer is that SnapStart does not apply to $LATEST. For a refresher on versions and aliases themselves, see the versions and aliases guide.
Supported Runtimes (This Is Where Old Notes Lie)
SnapStart launched as a Java-only feature, and this is the most common stale fact in circulation. The current managed-runtime support is:
| Runtime | SnapStart support |
|---|---|
| Java | 11 and later |
| Python | 3.12 and later |
| .NET | 8 and later |
| Node.js, Ruby | Not supported |
OS-only (provided.*) runtimes | Not supported |
Support spans both ZIP and container-image deployment formats for those runtimes. If a DVA-C02 question offers “enable SnapStart” as a fix for a slow Node.js function, that option is wrong — SnapStart does not support Node.js. The right cold-start levers for unsupported runtimes are provisioned concurrency and slimming the package.
Pricing: The Detail the Exam Rewards
SnapStart pricing is not uniform across runtimes, and that nuance is very exam-friendly:
- For Java managed runtimes, there is no additional charge for SnapStart. You pay the normal Lambda request and duration charges only.
- For Python and .NET, SnapStart adds two charges:
- A caching charge for every published version with SnapStart enabled — priced by the memory you allocate, billed for a minimum of 3 hours, and continuing as long as the function version remains active.
- A restoration charge each time a function instance is restored from a snapshot — also priced by allocated memory.
The practical consequence: on Python/.NET, publishing many SnapStart versions and never cleaning them up quietly accrues caching cost. AWS recommends deleting unused versions (via ListVersionsByFunction + DeleteFunction) to control it. On the exam, remember the headline: Java = no extra cost; Python/.NET = caching + restoration charges.
The Catch: Uniqueness and State Hazards
Here is the part that separates people who use SnapStart from people who just enabled it. Because Lambda uses one snapshot as the initial state for many execution environments, anything captured during initialization is copied into every environment restored from that snapshot. That breaks any assumption that init-time state is fresh or unique per environment.
Three categories to watch, straight from the AWS guidance:
- Uniqueness — If your init code generates a unique value (a random ID, a token, a secret, or seeds a pseudo-random number generator), that value gets baked into the snapshot and reused across every restored environment. You must generate unique content after initialization. The classic bug: seeding an RNG at init time so every environment produces the same “random” sequence.
- Network connections — Connections opened during init are not guaranteed to still be valid when Lambda resumes from a snapshot. Validate and re-establish them as needed. Connections created by an AWS SDK usually resume automatically; database and custom TCP connections often do not.
- Temporary data — Ephemeral data fetched at init (temporary credentials, cached timestamps) may be stale after restore. Refresh it in the handler before use — good practice even without SnapStart.
Runtime Hooks: Fixing State at the Right Moment
To fix those hazards cleanly, SnapStart gives you runtime hooks: beforeCheckpoint (runs just before Lambda takes the snapshot) and afterRestore (runs just after Lambda resumes from the snapshot). Use beforeCheckpoint to release resources you do not want captured; use afterRestore to re-establish connections and regenerate unique state.
Java uses the open-source CRaC (Coordinated Restore at Checkpoint) API:
import org.crac.Core;
import org.crac.Context;
import org.crac.Resource;
public class Handler implements Resource {
public Handler() {
Core.getGlobalContext().register(this);
}
@Override
public void beforeCheckpoint(Context<? extends Resource> context) {
// Release connections / resources before the snapshot is taken
}
@Override
public void afterRestore(Context<? extends Resource> context) {
// Re-open connections and regenerate anything that must be unique
}
}
Python uses the snapshot_restore_py helpers:
from snapshot_restore_py import register_before_snapshot, register_after_restore
def before_snapshot():
# runs before the snapshot is taken
pass
def after_restore():
# re-establish connections, regenerate unique values
pass
register_before_snapshot(before_snapshot)
register_after_restore(after_restore)
.NET registers hooks via SnapshotRestore.RegisterBeforeSnapshot(...) and SnapshotRestore.RegisterAfterRestore(...). In all three cases, the pattern is identical: clean up before the checkpoint, restore correctness after the resume.
Enabling SnapStart
For the DVA-C02 you should recognize how SnapStart is turned on across the common surfaces. The property is SnapStart with an ApplyOn value of either PublishedVersions (enable) or None (disable).
AWS CLI — update the configuration, then publish a version to trigger snapshot creation:
# 1. Enable SnapStart on the function
aws lambda update-function-configuration \
--function-name my-function \
--snap-start ApplyOn=PublishedVersions
# 2. Publish a version — this is what triggers the snapshot
aws lambda publish-version \
--function-name my-function
# 3. Confirm it is ready
aws lambda get-function-configuration \
--function-name my-function:1
A ready version reports:
"SnapStart": {
"ApplyOn": "PublishedVersions",
"OptimizationStatus": "On"
},
"State": "Active"
AWS SAM — declare it in the function properties (see the SAM deployments guide for the surrounding template):
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: python3.12
Handler: app.handler
SnapStart:
ApplyOn: PublishedVersions
AutoPublishAlias: live # publishes a version + alias on each deploy
CloudFormation exposes the same SnapStart property on AWS::Lambda::Function, and the CDK provides a SnapStartProperty. In every case the flow is the same: set ApplyOn: PublishedVersions, then publish a version.
Function States You Should Recognize
Because snapshot creation takes time, SnapStart introduces state transitions the exam may reference:
| State | Meaning |
|---|---|
| Pending | Lambda is initializing your code and taking the snapshot. Invocations of that version fail until it is ready. |
| Active | Snapshot creation is complete; you can invoke the published version (not $LATEST). |
| Inactive | Occurs when Lambda regenerates snapshots to apply updates. For Java, a version not invoked for 14 days goes inactive; invoking it then returns SnapStartNotReadyException while a new snapshot is built. |
| Failed | Lambda hit an error running your init code or creating the snapshot. |
The SnapStartNotReadyException / 14-day behavior is Java-specific and a genuine operational gotcha — if a rarely invoked Java function occasionally errors on the first call after a long idle period, an unready snapshot is the cause.
Reading the Logs: Restore Duration, Not Init Duration
SnapStart changes what shows up in CloudWatch, and log interpretation is a recurring theme in the Troubleshooting and Optimization domain:
- The
REPORTline for a SnapStart function does not includeInit Duration— because initialization happened at publish time, not on invocation. The Init phase details (including anybeforeCheckpointhook time) appear in a separateINIT_REPORTrecord instead. - When a new environment is restored, the
REPORTline includesRestore Duration(time to restore the snapshot, load the runtime, and runafterRestorehooks) andBilled Restore Duration(the portion you are actually billed for — runtime load plus after-restore hooks). - The effective cold-start time for the request is
Restore Duration+Duration.
In X-Ray, SnapStart functions show a Restore subsegment instead of an Initialization subsegment, and you are not billed for the portion of restore that happens outside the microVM. See the monitoring and troubleshooting guide for how these fit into broader Lambda observability.
SnapStart vs Provisioned Concurrency vs a Slimmer Package
A common optimization-question framing is “which cold-start fix fits this situation?” Here is the decision table. Note one hard constraint that questions test directly: SnapStart and provisioned concurrency are mutually exclusive — you cannot enable both on the same function.
| Approach | How it helps | Best when | Watch out for |
|---|---|---|---|
| SnapStart | Restores from a pre-initialized snapshot | Java/Python/.NET with heavy init; latency-sensitive at scale | Not for Node.js/Ruby; state uniqueness hazards; not on $LATEST; can’t combine with provisioned concurrency |
| Provisioned concurrency | Keeps a set number of environments warm and ready | Strict, predictable low latency that SnapStart can’t meet; any supported runtime | Extra cost for kept-warm capacity; configured per version/alias (covered in the concurrency guide) |
| Slim the package / lazy-load | Less code and fewer deps to initialize | Any runtime; first optimization to try | Only reduces init, doesn’t eliminate the cold start |
AWS’s own guidance: use provisioned concurrency when you have strict cold-start latency requirements that SnapStart cannot adequately meet; use SnapStart to cut multi-second init latency on supported runtimes at scale without paying to keep environments permanently warm. Other limits to remember: SnapStart does not support Amazon EFS, ephemeral storage greater than 512 MB, or provisioned concurrency, and it is available in all commercial Regions except Asia Pacific (New Zealand) and Asia Pacific (Taipei).
Scenario Cue Cheat Sheet
| The question describes… | The answer is… |
|---|---|
| ”Slow Java/Python/.NET cold starts, at scale, no code rewrite” | SnapStart |
| ”SnapStart enabled but no improvement” | Invoking $LATEST instead of a published version |
| ”Same ‘random’ value across many invocations after enabling SnapStart” | Uniqueness broken at init → regenerate in afterRestore / the handler |
| ”Strict, guaranteed low latency SnapStart can’t meet” | Provisioned concurrency |
| ”Enable SnapStart on a Node.js function” | Invalid — Node.js isn’t supported |
| ”Rare Java function errors on first call after days idle” | SnapStartNotReadyException after 14-day inactivity |
”No Init Duration in the REPORT log” | Expected for SnapStart — look for Restore Duration |
Common Mistakes to Avoid
| Mistake | Reality |
|---|---|
| ”SnapStart is Java-only” | Now supports Java 11+, Python 3.12+, and .NET 8+. |
Enabling SnapStart and invoking $LATEST | SnapStart applies only to published versions and aliases. |
| Assuming SnapStart is always free | Free for Java; Python/.NET add caching + restoration charges. |
| Seeding randomness or opening connections only at init | Snapshot copies that state everywhere — regenerate in afterRestore. |
| Trying to combine SnapStart with provisioned concurrency | They are mutually exclusive. |
| Expecting SnapStart to work with EFS or >512 MB ephemeral storage | Both are unsupported with SnapStart. |
Frequently Asked Questions
Which runtimes does Lambda SnapStart support in 2026? Java 11 and later, Python 3.12 and later, and .NET 8 and later, across both ZIP and container-image packaging. Node.js, Ruby, and OS-only runtimes are not supported.
Does SnapStart cost extra? For Java managed runtimes there is no additional charge. For Python and .NET you pay a caching charge per published SnapStart version (by memory, minimum 3 hours, while active) and a restoration charge each time an environment is restored from a snapshot.
Why did enabling SnapStart not speed up my function?
The most common reasons: you are invoking $LATEST instead of a published version or alias, your runtime is unsupported (e.g. Node.js), or your function is invoked too infrequently to benefit — SnapStart shines with invocations at scale.
Can I use SnapStart and provisioned concurrency together? No. They are mutually exclusive on the same function. Use provisioned concurrency when you need strict, predictable low latency SnapStart cannot meet; use SnapStart to cut heavy init latency without paying to keep environments warm.
What is the difference between Restore Duration and Init Duration?
For SnapStart functions, initialization happens at publish time, so Init Duration does not appear in the invocation REPORT line (it moves to an INIT_REPORT record). Instead the REPORT line shows Restore Duration (restore the snapshot + load runtime + afterRestore hooks) and Billed Restore Duration. Cold-start time ≈ Restore Duration + Duration.
How do I keep unique values unique with SnapStart?
Do not generate unique IDs, secrets, or random seeds during initialization — they get captured in the snapshot and reused. Generate them after initialization, either in the handler or in an afterRestore runtime hook.
What is SnapStartNotReadyException?
A Java-specific behavior: if a SnapStart-enabled Java function version is not invoked for 14 days, its snapshot is deleted and the version goes Inactive. The next invocation returns SnapStartNotReadyException while Lambda builds a fresh snapshot; wait for Active, then invoke again.
Practice the Optimization Domain Under Exam Conditions
SnapStart questions reward precise recall: which runtimes, what it costs, why $LATEST is excluded, the uniqueness trap, and how the logs change. That precision comes from repetition against realistic scenarios, not from re-reading a feature list.
Sailor.sh’s AWS Developer Associate (DVA-C02) mock exam bundle — 8 full-length exams with detailed explanations — covers Lambda performance, deployment, and troubleshooting the way the real exam frames them, so you practice choosing between SnapStart, provisioned concurrency, and package optimization under time pressure. To see the question style first, work through the free DVA-C02 practice questions.
To round out the serverless and optimization topics around SnapStart, pair this with the Lambda versions, aliases & concurrency guide (the execution-environment lifecycle and provisioned concurrency), the serverless applications guide, the SAM deployments guide, and the monitoring, troubleshooting & optimization guide. New to the exam? Start with the DVA-C02 exam guide for 2026 and plan your prep with the DVA-C02 study plan.