Back to Guides

Amazon Lambda SnapStart Configuration

SnapStart is a snapshotting and restore mechanism reducing drastically the cold startup time of Java functions on AWS. This document explains the various settings you can use to leverage this feature. It is not a reference documentation on SnapStart, and it will not cover how SnapStart works in details.

This feature is only available on AWS Lambda, and not in all regions. Please check the AWS documentation to verify the eligibility of your AWS region.

Enabling / Disabling SnapStart Optimizations

If you use the Quarkus Amazon Lambda extension, SnapStart optimizations are automatically enabled. However, you can enable/disable it explicitly using:

quarkus.snapstart.enabled=true|false
It does not enable/disable SnapStart for your function, only the Quarkus optimizations.

Class Preloading

Classloading has a huge impact on your function execution time. This optimization allows preloading classes during the snapshotting process of SnapStart.

The classes to preload are listed in two places:

  1. extensions can produce a list of classes (using the io.quarkus.deployment.builditem.PreloadClassBuildItem build item)

  2. you can add a src/main/resources/META-INF/quarkus-preload-classes.txt file listing the classes to preload, such as:

com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal
com.fasterxml.jackson.annotation.JsonAlias
com.fasterxml.jackson.annotation.JsonFormat$Feature
com.fasterxml.jackson.core.exc.InputCoercionException
com.fasterxml.jackson.core.exc.StreamWriteException
com.fasterxml.jackson.core.io.ContentReference
com.fasterxml.jackson.core.io.IOContext
com.fasterxml.jackson.core.io.JsonEOFException
com.fasterxml.jackson.core.io.MergedStream
com.fasterxml.jackson.core.io.NumberInput
com.fasterxml.jackson.core.io.NumberOutput
com.fasterxml.jackson.core.io.UTF32Reader
com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper
com.fasterxml.jackson.core.json.JsonReadContext
com.fasterxml.jackson.core.json.JsonWriteContext
com.fasterxml.jackson.core.json.UTF8StreamJsonParser
com.fasterxml.jackson.core.JsonEncoding
com.fasterxml.jackson.core.JsonGenerationException
com.fasterxml.jackson.core.JsonLocation
com.fasterxml.jackson.core.JsonStreamContext
com.fasterxml.jackson.core.JsonToken
...

The format is simple: one class per line.

Computing the class list

That step is particularly not user-friendly. We plan to improve it.

To compute the list of classes, we recommend deploying your function and setting the JAVA_TOOL_OPTIONS environment variable to -verbose:class. Then execute your function and retrieve the log (in CloudWatch). You should be able to extract the class names using sed/awk or any text editor.

Application class list

By default, Quarkus generates the class list of the classes included in your application (including the classes generated by Quarkus). So, you do not have to repeat them in the quarkus-preload-classes.txt file.

You can disable this feature using:

quarkus.snapstart.generate-application-class-list=false

Disable preloading

You can disable the preloading of classes using:

quarkus.snapstart.preload-classes=false

Skipping class initialization

By default, when the classes are preloaded, they are also initialized, meaning it also resolves the dependent classes. You can disable this behavior using:

quarkus.snapstart.initialize-classes=false

Client Priming

Client priming is a technique that allows initializing a client during the snapshotting process, so it’s already fully functional during the application runtime.

There are two ways to achieve priming:

  1. initialize the client in a static block, which, thanks to class preloading will be executed before the snapshot

  2. register a CRaC Resource doing the initialization

(1) can be achieved as follows:

@ApplicationScoped
public class HeroRepository {
    private static final DynamoDbClient client;

    static {
        client = DynamoDbClient.builder()
                .region(Region.US_EAST_2)
                .credentialsProvider(DefaultCredentialsProvider.create())
                .build();
        client.describeEndpoints();
    }
    // ...
}
Implementing priming using a static block may prevent the native compilation of your application. Client initialization may start threads or open connections which are not compatible with the native compilation if the class is initialized at build time.

The next section covers (2).

Resource registration

SnapStart uses the CRaC API to allow the application to execute custom code before the snapshotting or during the restoration.

While it’s the CRaC API, SnapStart is not CRaC and can do things that would not work with others CRaC implementations.
package org.acme.hello;

import io.quarkus.runtime.Startup;
import org.crac.Context;
import org.crac.Core;
import org.crac.Resource;
import org.jboss.logging.Logger;

import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

@Startup
@ApplicationScoped
public class HelloPriming implements Resource {

    @Inject
    Logger logger;

    @PostConstruct
    void init() {
        // Important - register the resource
        Core.getGlobalContext().register(this);
    }

    @Override
    public void beforeCheckpoint(Context<? extends Resource> context) throws Exception {
        logger.info("before checkout hook");
        // initialize your client here.
    }

    @Override
    public void afterRestore(Context<? extends Resource> context) throws Exception {
        logger.info("after checkout hook");
        // if there is anything to do during the restoration, do it here.
    }
}
Restoration is limited to 2 seconds.

TieredCompilation

It is also recommended to use tiered compilation when using SnapStart. To achieve this, set the JAVA_TOOL_OPTIONS environment property to -XX:+TieredCompilation -XX:TieredStopAtLevel=1.

TieredCompilation can also be interesting for regular Lambda functions.