Back to Blog

AWS Lambda SnapStart for the DVA-C02 Exam: Faster Cold Starts, the Snapshot Lifecycle, Runtime Support & When to Use It

A practitioner's deep dive into AWS Lambda SnapStart for the DVA-C02 exam. How the snapshot-on-publish, restore-on-invoke lifecycle works, current runtime support (Java, Python, .NET), pricing differences, the uniqueness and state hazards you must fix with runtime hooks, how to enable it via CLI and SAM, reading Restore Duration in the logs, and how SnapStart compares to provisioned concurrency.

By Sailor Team , September 26, 2026

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:

  1. Runs your initialization code once, ahead of time.
  2. Takes a Firecracker microVM snapshot of the memory and disk state of that fully initialized execution environment.
  3. 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:

RuntimeSnapStart support
Java11 and later
Python3.12 and later
.NET8 and later
Node.js, RubyNot supported
OS-only (provided.*) runtimesNot 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:

StateMeaning
PendingLambda is initializing your code and taking the snapshot. Invocations of that version fail until it is ready.
ActiveSnapshot creation is complete; you can invoke the published version (not $LATEST).
InactiveOccurs 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.
FailedLambda 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 REPORT line for a SnapStart function does not include Init Duration — because initialization happened at publish time, not on invocation. The Init phase details (including any beforeCheckpoint hook time) appear in a separate INIT_REPORT record instead.
  • When a new environment is restored, the REPORT line includes Restore Duration (time to restore the snapshot, load the runtime, and run afterRestore hooks) and Billed 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.

ApproachHow it helpsBest whenWatch out for
SnapStartRestores from a pre-initialized snapshotJava/Python/.NET with heavy init; latency-sensitive at scaleNot for Node.js/Ruby; state uniqueness hazards; not on $LATEST; can’t combine with provisioned concurrency
Provisioned concurrencyKeeps a set number of environments warm and readyStrict, predictable low latency that SnapStart can’t meet; any supported runtimeExtra cost for kept-warm capacity; configured per version/alias (covered in the concurrency guide)
Slim the package / lazy-loadLess code and fewer deps to initializeAny runtime; first optimization to tryOnly 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

MistakeReality
”SnapStart is Java-only”Now supports Java 11+, Python 3.12+, and .NET 8+.
Enabling SnapStart and invoking $LATESTSnapStart applies only to published versions and aliases.
Assuming SnapStart is always freeFree for Java; Python/.NET add caching + restoration charges.
Seeding randomness or opening connections only at initSnapshot copies that state everywhere — regenerate in afterRestore.
Trying to combine SnapStart with provisioned concurrencyThey are mutually exclusive.
Expecting SnapStart to work with EFS or >512 MB ephemeral storageBoth 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.

Limited Time Offer: Get 80% off all Mock Exam Bundles | Sale ends in 7 days. Start learning today.

Claim Now