Free — no signup required

SnapStart: Cheating the Cold Start

3 min read

The Java Problem

Java is the dominant language in enterprise backends, but it has a painful characteristic: the JVM (Java Virtual Machine) does enormous amounts of work at startup. It loads classes, performs Just-In-Time (JIT) compilation, and — if you're using a framework like Spring Boot — runs dependency injection, component scanning, and bean initialization. This can take 6–15 seconds for a typical enterprise Spring Boot application. That's an unacceptable cold start for a user-facing API.

How SnapStart Works

SnapStart solves this by separating the Init Phase from the invocation entirely. Here's the sequence:

  1. At deployment time (not request time): When you publish a new Lambda function version, AWS boots the execution environment, runs the entire Init Phase (JVM startup, Spring Boot initialization, your global code), and then takes a memory snapshot of the fully-initialized MicroVM. This snapshot is stored encrypted in S3.

  2. At request time: When a cold start would normally occur, AWS doesn't boot a new VM from scratch. Instead, it restores the memory snapshot — essentially resuming the VM from a saved state. The JVM is already initialized, Spring Boot is already running, your global code has already executed.

The result: cold starts drop from 6–15 seconds to under 200 milliseconds for Java functions, because the expensive Init Phase has been pre-computed and cached.

SnapStart Caveats

SnapStart is not magic — it introduces constraints you must design around:

  • Uniqueness problem: If your Init Phase generates a UUID, opens a random port, or seeds a random number generator, all restored snapshots will have the same UUID/seed. AWS provides lifecycle hooks (beforeCheckpoint and afterRestore) via the CRaC (Coordinated Restore at Checkpoint) interface so you can re-initialize anything that must be unique per instance.
  • Network connections: Any TCP connections opened during Init Phase will be stale after snapshot restoration. Close connections in beforeCheckpoint and reopen them in afterRestore.
  • Supported runtimes: SnapStart is currently available for Java 11+, Python 3.12+, and .NET 8+. It is not available for custom runtimes or container images.
  • Version requirement: SnapStart only works on published Lambda versions, not on $LATEST.
// Implementing CRaC hooks for SnapStart correctness
import org.crac.Context;
import org.crac.Core;
import org.crac.Resource;

public class MyHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent>, Resource {

    private DatabaseConnection dbConn;

    public MyHandler() {
        // Runs during Init Phase (before snapshot)
        this.dbConn = DatabaseConnection.connect();
        Core.getGlobalContext().register(this); // Register for CRaC hooks
    }

    @Override
    public void beforeCheckpoint(Context<? extends Resource> context) {
        // Called before AWS takes the memory snapshot
        dbConn.close(); // Close stale-able resources
    }

    @Override
    public void afterRestore(Context<? extends Resource> context) {
        // Called after snapshot is restored, before handler runs
        dbConn = DatabaseConnection.connect(); // Reopen fresh connection
    }

    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context context) {
        return dbConn.query(event);
    }
}

This is one of 18 chapters

Get every chapter — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

See pricing