DEV Community

Vadym Kazulkin for AWS Heroes

Posted on • Edited on

AWS SnapStart - Part 28 Measuring cold and warm starts with Java 21, APIGatewayProxyRequestEvent priming and memory settings

Introduction

In the part 27 of this article series, we introduced (full) APIGatewayProxyRequestEvent SnapStart priming and compared its Lambda performance with DynamoDB request invocation priming. We saw that the former has consistently lower (up to several hundred milliseconds, depending on the percentile) cold start times, which is quite impressive. Particularly, the effect of the APIGatewayProxyRequestEvent Lambda SnapStart priming was noticeable with respect to the SnapStart tiered cache (see the last 70 measurements). The warm start times were nearly the same, except for the max values, as the proper priming reduces one-time initialization during handleRequest method invocation as well. It's up to you to adopt this for your use case or not, because yes, it requires some additional (but simple) code to be written.

One of the readers asked the question of how this priming technique behaves with less memory given to the Lambda function, as I always give it 1024 MB as a starting point. Trying out different Lambda memory settings is one of the biggest factors that impact Lambda performance and cost. Maybe even 256 MB would be acceptable and deliver a good performance, and we can save money?

Measuring cold and warm start time of the AWS Lambda function with the different memory settings

We'll use the same sample project and way of measuring Lambda performance as described in part 27, but with different Lambda memory settings between 256 MB and 1792 MB. Here are the results:

Cold (c) and warm (w) start time in ms:

Scenario Number 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
SnapStart enabled with full APIGatewayProxyRequestEvent priming, all, 256 MB 1374 1423 1877 1901 1901 1902 6.21 14.10 21.23 63.93 159.38 1230
SnapStart enabled with full APIGatewayProxyRequestEvent, last 70, 256 MB 1357 1393 1432 1543 1543 1543 6.02 13.66 20.57 61.95 149.65 1001
SnapStart enabled with full APIGatewayProxyRequestEvent priming, all, 512 MB 888 970 1385 1399 1399 1400 5.47 6.21 7.87 31.83 93.67 866
SnapStart enabled with full APIGatewayProxyRequestEvent, last 70, 512 MB 869 906 983 1182 1182 1182 5.47 6.11 7.75 31.33 81.20 523
SnapStart enabled with full APIGatewayProxyRequestEvent priming, all, 768 MB 720 757 1348 1386 1397 1398 5.55 6.30 7.51 20.41 53.74 736
SnapStart enabled with full APIGatewayProxyRequestEvent, last 70, 768 MB 713 732 780 921 921 921 5.47 6.21 7.39 20.09 50.44 334
SnapStart enabled with full APIGatewayProxyRequestEvent priming, all, 1024 MB 642 671 1207 1227 1232 1241 5.64 6.30 7.27 15.50 38.45 748
SnapStart enabled with full APIGatewayProxyRequestEvent, last 70, 1024 MB 628 652 686 791 791 791 5.59 6.25 7.21 15.14 36.37 264
SnapStart enabled with full APIGatewayProxyRequestEvent priming, all, 1280 MB 596 682 1144 1157 1158 1160 5.59 6.30 7.33 13.43 37.25 639
SnapStart enabled with full APIGatewayProxyRequestEvent, last 70, 1280 MB 579 616 677 773 773 773 5.50 6.20 7.16 12.80 35.23 201
SnapStart enabled with full APIGatewayProxyRequestEvent priming, all, 1536 MB 604 661 1147 1160 1173 1174 5.59 6.25 7.33 13.01 36.08 551
SnapStart enabled with full APIGatewayProxyRequestEvent, last 70, 1536 MB 582 604 640 689 689 689 5.59 6.25 7.33 13.11 32.79 176
SnapStart enabled with full APIGatewayProxyRequestEvent priming, all, 1792 MB 604 662 1182 1192 1195 1197 5.64 6.35 7.51 13.22 37.84 730
SnapStart enabled with full APIGatewayProxyRequestEvent, last 70, 1792 MB 585 595 644 670 670 670 5.59 6.30 7.39 13.11 33.31 190

Conclusion

We see that setting 256 MB of memory to the Lambda function, even with the full APIGatewayProxyRequestEvent priming, leads to very high Lambda cold and warm start times. Depending on the performance and cost requirements of our use case, memory settings between 512 MB and 1024 MB may be very acceptable. Giving Lambda more memory between 1024 MB and 1280 MB for this particular use case leads to only a slight improvement in the Lambda performance but a much higher cost. This might be an acceptable trade-off from the business perspective. Giving the Lambda function more memory than 1280 MB didn't improve Lambda performance (besides the max value for the warm start times) but led to a much higher Lambda cost. Trying out to set more than 1792 MB of memory only makes sense if our application can benefit from doing things in parallel, but our sample application is single-threaded. When the allocated memory crosses the Lambda memory size limit of 1.792 MB, it adds the equivalent of one full vCPU (one vCPU-second of credits per second), so for the maximum of 10 GB of Lambda memory to be set, we get access to maximal 6 full vCPUs.

Update from 7 July 2025
As described in the part 27, I discovered that the aws-lambda-java-serialization dependency is also provided by the AWS Lambda Java Runtime Interface Client, so we can set its scope to provided in pom.xml like this :

<dependency>
   <groupId>com.amazonaws</groupId>
   <artifactId>aws-lambda-java-serialization</artifactId>
   <version>1.1.5</version>
   <scope>provided</scope>
</dependency>
Enter fullscreen mode Exit fullscreen mode

That's why, please re-measure Lambda performance for the above-provided Lambda memory settings by not packaging the aws-lambda-java-serialization dependency in the deployment artifact. We've already re-measured it for the 1024 MB memory setting in part 27 and saw some slight improvements in the Lambda performance.

Top comments (0)