Introduction
In this article series, we already introduced how to develop, run, and optimize a GraalVM Native Image application on AWS Lambda deployed as a Lambda Custom Runtime. In part 5, we upgraded our sample application to use GraalVM 23 and Native Image. In November 2024, AWS CRT Client for Java added GraalVM Native Image support. In this article, we'll modify our sample application to use AWS CRT HTTP client instead of Apache one and measure the performance (cold and warm start time) of the Lambda function, and make a comparison between these 2 HTTP clients.
How to write an AWS Lambda function with GraalVM 23 and AWS CRT HTTP Client
The sample simple application introduced in the part 5 remains the same, see the architecture below:
But I modified it to use AWS CRT HTTP Client and published the source code in the pure-lambda-graalvm-23-native-image-with-aws-crt-http-client repository.
The following changes needed to be done in part 5 to use AWS CRT HTTP Client instead of the Apache one:
1) In pom.xml,
declare AWS CRT HTTP Client :
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>aws-crt-client</artifactId>
</dependency>
and exclude Apache HTTP Client :
<exclusions>
<exclusion>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
</exclusion>
</exclusions>
2) In DynamoProductDao set AWS CRT HTTP Client:
private static final DynamoDbClient dynamoDbClient = DynamoDbClient.builder()
....
.httpClient(AwsCrtHttpClient.create())
.build();
3) In native.xml include during the build process automatically generated libaws-crt-jni.so (as described in the article AWS CRT Client for Java added GraalVM Native Image support) to be added to the Lambda Custom Runtime zip file:
<fileSet>
...
<includes>
<include>aws-pure-lambda-graalvm-23-native-image-aws-crt-http-client </include>
<include>libaws-crt-jni.so</include>
</includes>
</fileSet>
The following needs to be installed to build and deploy the sample application:
- Java 21, for example Amazon Corretto 21
- Apache Maven
- AWS CLI
- AWS SAM
- GraalVM, for example GraalVM 23.0.1
- Native Image
To build the application, execute mvn clean package.
To build the application, execute sam deploy -g.
To create the product with id equal to 1, execute
curl -m PUT -d '{ "id": 1, "name": "Print 10x13", "price": 0.15 }' -H "X-API-Key: a6ZbcDefQW12BN56WEC23" https://{$API_GATEWAY_URL}/prod/products
To retrieve the product with id equal to 1, execute
curl -H "X-API-Key: a6ZbcDefQW12BN56WEC23" https://{$API_GATEWAY_URL}/prod/products/1
What I noticed was that the compiled artifact size to be deployed using AWS CRT HTTP Client was bigger than using the Apache one (37.600 vs 34.700 KB), mainly due to an additional native .so file. Bigger artifact sizes generally contribute to the higher cold start times. So, let's see.
Measuring cold and warm start time of the AWS Lambda function with GraalVM 23 and AWS CRT HTTP Client
How to measure AWS Lambda performance, introduced in part 5, remains valid.
The results of the experiment below were also based on reproducing more than 100 cold and approximately 100.000 warm starts with the Lambda function GetProductByIdFunction with a 1024 MB memory setting for the duration of 1 hour. The experiments have been performed with the Lambda Custom Runtime version provided:al2023.v56. For it, I used the load test tool hey, but you can use whatever tool you want, like Serverless-artillery or Postman.
So let's provide the results of the measurements. I will also add measurements from part 5 performed with the Apache HTTP Client, for better visualization.
Abbreviation c stands for the cold start, and w stands for the warm start.
Cold (c) and warm (w) start time in ms:
| HTTP Client | 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 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Apache | 618.18 | 628.78 | 638.28 | 667.64 | 705.37 | 705.61 | 4.03 | 4.62 | 5.25 | 10.33 | 38.76 | 103.27 |
| AWS CRT | 675.02 | 685.22 | 699.75 | 743.74 | 930.12 | 930.37 | 3.91 | 4.37 | 4.97 | 9.31 | 64.03 | 228.41 |
Conclusion
In this article, we modified our sample application to use the AWS CRT HTTP client instead of the Apache one and measured the performance (cold and warm start time) of the Lambda function.
We observe that the cold start times for Apache HTTP Client are lower than for AWS CRT for all percentiles (for the higher ones significantly). The warm start times for lower percentiles are slightly better for AWS CRT HTTP Client and become worse compared to Apache HTTP Client for the higher percentiles.
As long as I don't identify any optimization potential for my sample application, I'd prefer to use Apache HTTP Client, but the measurements and therefore the choice may be different for your application. So measure it yourself!
If you have read my articles and liked their content, please support me by following me on my GitHub account and giving my repos a star.

Top comments (0)