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 constantly 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 last 70 measurements). The warm start times were nearly the same besides 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 how this priming technique behaves with less memory given to the Lambda function as I always give it 1024 MBs as a starting point. Trying out different Lambda memory settings is one of the biggest factors which impacts Lambda performance and cost. Maybe even 256 MBs 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 of Lambda performance as described in the part 27 but with different Lambda memory setting between 256 MBs and 1792 MBs. 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 MBs 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 to your use case memory setting between 512 MBs and 1024 MBs may be very acceptable. Given Lambda more memory between 1024 MBs and 1280 MBs for this particular use case leads to only slight improvement of the Lambda performance but much higher cost. This might be an acceptable trade-off from the business perspective. Giving Lambda function more memory than 1280 MBs didn't improve Lambda performance (besides the max value for the warm start times) but leads to the much higher Lambda cost. Trying out to set more than 1792 MBs 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 maximal of 10 GBs of Lambda memory to be set we get access to maximal 6 full vCPUs.

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 constantly 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 last 70 measurements). The warm start times were nearly the same besides 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 how this priming technique behaves with less memory given to the Lambda function as I always give it 1024 MBs as a starting point. Trying out different Lambda memory settings is one of the biggest factors which impacts Lambda performance and cost. Maybe even 256 MBs 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 of Lambda performance as described in the part 27 but with different Lambda memory setting between 256 MBs and 1792 MBs. 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 MBs 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 to your use case memory setting between 512 MBs and 1024 MBs may be very acceptable. Given Lambda more memory between 1024 MBs and 1280 MBs for this particular use case leads to only slight improvement of the Lambda performance but much higher cost. This might be an acceptable trade-off from the business perspective. Giving Lambda function more memory than 1280 MBs didn't improve Lambda performance (besides the max value for the warm start times) but leads to the much higher Lambda cost. Trying out to set more than 1792 MBs 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 maximal of 10 GBs of Lambda memory to be set we get access to maximal 6 full vCPUs.