Quarkus support for AWS Lambda SnapStart

Quarkus support for AWS Lambda SnapStart

Amazon Web Services (AWS) announced the SnapStart feature for AWS Lambda. SnapStart for Java reduces startup latency for Java-based functions running on AWS Lambda, and Quarkus supports it from day one!

Quarkus is supersonic subatomic Java with a focus on cloud-native applications. The idea behind Quarkus has always been to do at build-time what traditional frameworks do at runtime. Quarkus is optimized for low memory usage and fast startup times. Quarkus brings back developer joy to Java and enables every Java developer out there to use their skills to develop cloud-native apps, including AWS Lambda workloads.

Quarkus uses the ‘quarkus-amazon-lambda’ extension to build and deploy functions to AWS Lambda. The extension allows developers to use the Quarkus development model like live coding, continuous testing, etc., and the ability to use CDI Injections and additional quarkus extensions. Developers can deploy functions to AWS Lambda using native or Java mode. With today’s announcement, the SnapStart feature is now an additional option to build and deploy functions written with Quarkus to AWS Lambda.

What is SnapStart?

Typically AWS Lambda creates a new execution environment when invoking a new function for the first time or when it is scaled up to handle the traffic. SnapStart takes a different approach by taking a snapshot of the execution environment(memory and application state) of the initialized function execution environment. Furthermore, it persists the snapshot and caches it for low-latency access. When invoking the function, it does not need to spend time initializing code, dependencies, or framework. Instead, Lambda resumes the new execution environment from the persisted snapshot.

SnapStart considerations

Because of how SnapStart works with snapshots and resumes the execution environment with low latency, this benefits functions written with Quarkus. Quarkus can leverage the snapshotting and warm-up code paths for the libraries Quarkus supports.

For the Developer’s code and libraries, they need to consider particular cases when utilizing SnapStart:

Resource connections over the network: Snapshots do not guarantee connections back to remote hosts when a function is resumed. Developers will need to ensure and validate the state of connections.
Pulling in-memory data from sources: Often, one needs to pull data from a different source into memory. This can also lead to inconsistency if the data at the source has changed or even expired. Ensure and verify the state of such data.
Randomness: Lambda SnapStart speeds up applications by re-using a single initialized snapshot many times over to resume execution environments. As a result, unique content which was included in the snapshot during initialization may be reused across execution environments and so may no longer remain unique. Ensure that unique content is generated after initialization, and avoid caching unique content during initialization. Refer to the feature documentation to understand these considerations around uniqueness and interfaces available to customers to restore uniqueness.

Quarkus fast startup times and integration with SnapStart

A typical Java application uses JIT (Just in time) compilation. When an application starts up, it needs time for specific warm-up code paths to perform better, which means additional CPU cycles for warm-up times. Cloud-native applications demand a faster startup time. Ahead-of-time (AOT) compilation enables that by doing most of the optimizations at build time. A good example here is Quarkus. As a result, we have full speed from startup and no CPU overhead for compilations at startup time. Quarkus application initialization has two phases: static initialization and runtime initialization. This distinction follows the principles of the GraalVM native compilation, inlining the static initialization in the resulting executable, while the runtime initialization happens during the regular execution. We compared multiple functions to understand the benefits of each feature we added:

  • The Hello function is a simple function returning “Hello” and using the Quarkus AWS Lambda extension

  • The Heroes function implements a CRUD interface on top of DynamoDB. It uses the Quarkus AWS Lamdba HTTP and RESTEasy Reactive. Invocations go through an AWS API Gateway.

For each function, we compare:

  • The invocation duration, memory, and billed duration without SnapStart

  • The invocation duration, memory, and billed duration with a full startup during the warmup phase and the preloading of the classes.

The class preloading loads and initializes all the classes used by the application.

Results

Hello Function Without SnapStart With SnapStart Native

Total duration

2230 ms

202 ms

-90.93%

356 ms

-84.05%

Billed duration

131 ms

109 ms

-16.79%

356 ms

171.76%

Memory

115 MB

104 MB

-9.57%

59 MB

-48.70%

Heroes Function Without SnapStart With SnapStart Native

Total duration

15728 ms

965 ms

-93.87%

1112 ms

-92.93%

Billed duration

12550 ms

885 ms

-92.95%

1113 ms

-91.13%

Memory

222 MB

173 MB

-22.07%

96 MB

-56.76%

Quarkus together with AWS Lambda SnapStart functions enables further runtime optimizations close to the native performance and much faster than the regular Java ones. For some functions, SnapStart is faster than a cold start of a native executable in AWS Lambda. For others, memory usage is better with the native image.

Conclusion

Developers now have three options to build and deploy functions to AWS Lambda; JVM mode, Native mode, and the latest inclusion of the SnapStart feature. All three have different use cases. It is important to note that SnapStart is an AWS Lambda feature only.

With the SnapStart feature, it is possible to run Quarkus in JVM mode with similar and, in some cases, faster startup times than the native image in the AWS Lambda environment. For this to work, developers need to ensure that applications can startup in a safe state, e.g., network connections, resources, etc. Luckily if you are using Quarkus a lot of this is done for you.

With PR #29108 merged into the Quarkus main branch, Quarkus applications can use the SnapStart features on AWS Lambda. The feature will land in the 2.15 platform release as an experimental feature.

If you are an AWS Lambda user we encourage you to try out Quarkus with and without AWS Snapstart and compare. Let us know your results and feedback.

For more technical details, visit the AWS Lambda SnapStart blog here.