Data API for Amazon Aurora Serverless v2 with AWS SDK for Java - Part 7 Data API meets SnapStart
Tags: aws, serverless, java, database
Published: 2024-06-03 15:14:18

## Introduction

In the [part 5](https://dev.to/aws-builders/data-api-for-amazon-aurora-serverless-v2-with-aws-sdk-for-java-part-5-basic-cold-and-warm-starts-measurements-4gi9) we measured cold and warm starts of our sample application which uses Data API for Amazon Aurora Serverless v2 with AWS SDK for Java and in the [part 6](https://dev.to/aws-builders/data-api-for-amazon-aurora-serverless-v2-with-aws-sdk-for-java-part-6-comparing-cold-and-warm-starts-between-data-api-and-jdbc-56hj) we did the same measurements using the standard connection management solutions like JDBC including the usage of the Amazon RDS Proxy service and compared the result. In this part of the series we'll enable AWS SnapStart to the Lambda function communicating with Aurora Serverless v2 PostgreSQL via Data API and also apply optimization technique called priming.


##  Measuring cold and warm starts with SnapStart enabled and priming

I released a separate series about [AWS Lambda SnapStart](https://dev.to/vkazulkin/measuring-java-11-lambda-cold-starts-with-snapstart-part-1-first-impressions-30a4) where I talked about its benefits and also measured warm and cold starts for the similar  [application ](https://dev.to/aws-builders/measuring-lambda-cold-starts-with-aws-snapstart-part-9-measuring-with-java-21-5e52) which also used Java 21 managed Lambda runtime but DynamoDB database instead of Aurora Serverless v2 with Data API.

In our experiment we'll re-use the application introduced in the [part 1](https://dev.to/aws-builders/data-api-for-amazon-aurora-serverless-v2-with-aws-sdk-for-java-part-1-introduction-and-set-up-of-the-sample-application-3g71) for this which you can find [here](https://github.com/Vadym79/AWSLambdaJavaAuroraServerlessV2DataApi). 

We will measure cold and warm start for 2 approaches:

- Enable SnapStart for Lambda function [GetProductByIdViaAuroraServerlessV2DataApi ](https://github.com/Vadym79/AWSLambdaJavaAuroraServerlessV2DataApi/blob/master/template.yaml) by adding 

```
      SnapStart:
        ApplyOn: PublishedVersions
```
to the Properties: section of the Lambda function
- Additionally apply priming technique to the Lambda function with SnapStart enabled by priming the database request.  I explained priming in my article [Measuring priming, end to end latency and deployment time with Java ](https://dev.to/aws-builders/measuring-java-11-lambda-cold-starts-with-snapstart-part-5-priming-end-to-end-latency-and-deployment-time-jem). In our case I implemented additional Lambda function [GetProductByIdViaAuroraServerlessV2DataApiWithPriming](https://github.com/Vadym79/AWSLambdaJavaAuroraServerlessV2DataApi/blob/master/template.yaml).  In its implementation [GetProductByIdViaAuroraServerlessV2DataApiWithPrimingHandler](https://github.com/Vadym79/AWSLambdaJavaAuroraServerlessV2DataApi/blob/master/src/main/java/software/amazonaws/example/product/handler/GetProductByIdViaAuroraServerlessV2DataApiWithPrimingHandler.java) you can see how priming works in action :

```
public void beforeCheckpoint(org.crac.Context<? extends Resource> context) throws Exception {
            auroraServerlessV2DataApiDao.getProductById("0");
      }
```

In the **beforeCheckpoint** Lambda runtime hook method (which uses [CRaC API](https://openjdk.org/projects/crac/)) we prime database invocation by retrieving the product with id equals to 0 from the database using Data API for Aurora Serverless v2. With that we pre-initialize all the classes involved in the invocation chain and pre-initilizing synchronous HTTP client (we use the default one which is Apache) which all will be directly available after the Firecracker microVM is restored. 

For that our Lambda handler needs to implement **org.crac.Resource** interface, and register this class to be CRaC-aware with:

```
public GetProductByIdViaAuroraServerlessV2DataApiWithPrimingHandler() {
            Core.getGlobalContext().register(this);
      }
```

Additionally we need to include the following dependecy 

```
<dependency>
  <groupId>io.github.crac</groupId>
  <artifactId>org-crac</artifactId>
  <version>0.1.3</version>
</dependency>
```
in the [pom.xml](https://github.com/Vadym79/AWSLambdaJavaAuroraServerlessV2DataApi/blob/master/pom.xml).

The results of the experiments to retrieve the existing product from the database by its id see below were based on reproducing more than 100 cold and at least 30.000 warm starts with experiment which ran for approximately 1 hour. For it (and experiments from my previous article) I used the load test tool [hey](https://github.com/rakyll/hey), but you can use whatever tool you want, like [Serverless-artillery](https://www.npmjs.com/package/serverless-artillery) or [Postman](https://www.postman.com/).

**Cold (c) and warm (m) start time in ms:**

|Approach|c p50|c p75|c p90|c p99|c p99.9|c max|w p50|w p75 |w p90|w p99|w p99.9|w max|      
|---------------|----------|-----------|----------|----------|----------|----------|-----------|----------|----------|----------|----------|----------|
|No SnapStart enabled|3154.35|3237|3284.91|3581.49|3702.12|3764.92|104.68|173.96|271.32|572.11|1482.89|2179.7|
|SnapStart enabled without priming|1856.11|1994.61|2467.83|3229.11|3238.80|3241.75|61.02|113.32|185.37|639.35|1973.30|2878.5|
|SnapStart enabled with priming of database invocation via Data API|990.84|1069.04|1634.84|2120.00|2285.03|2286.9|60.06|106.35|185.37|581.27|1605.37|2658.24|

## Conclusion
In this part of the series, we applied SnapStart to the Lambda function and also convinced that it significantly reduced the cold and the warm start of our Lambda function. It was especially true when we also applied priming of Data API invocation.
In the next part of the series we'll introduce various optimization strategies for the cold and warm starts.