How does code package size influence Lambda load times?

April 3, 2016

GitHub link to AWS Lambda tester

Lambda is a powerful tool provided by AWS that teases at the possibility of creating a serverless backend for your applications. Lambda allows developers to upload small modules of code which can be executed on demand. After creating a few simple hello world functions in the browser, a developer could easily start coding large backend projects.

However, such ambition could quickly become their downfall. To understand this, you must first know how AWS executes a Lambda function. AWS runs each function in isolation. When a function is first requested, none of the AWS Lambda nodes have that function cached. A node retrieves the code for the unique Lambda function, executes it, and returns the result. Future executions will now complete faster since one node already has the function loaded. If the function is repeatedly requested, more nodes will pause the request process to load the function.

This pause is hardly noticeable with a 500 byte hello world function and isn't even an issue for most small projects. However, as your project continues to grow, load times will take longer and longer. If the project grows too large, initial load times will increase substantially and users will notice when their applications randomly slow down. As projects balloon, developers will need to find ways to only upload the required code for each Lambda function. This would be manageable for a five function project, but keeping this organized in a 50 function project could get ugly.

While working through this, I wondered how the size of a code package affected function load time. AWS requires you to upload a code package for every function you wish to create. A developer could find ways to isolate individual Lambda functions so that only required code is uploaded. At what point is this a concern?

To test load times, I used a script that created fresh functions at a variety of code sizes, executed them once to see initialization time, and then deleted them. I repeated this process to get multiple measurements per code size. The code sizes used were: 665 bytes, 550 KB, 1.6 MB, 3.2 MB, 27.4 MB, 48 MB, and 68.3 MB. To reach these sizes, I found popular node modules, installed, and imported them into the function under test. All functions were executed in the nodejs environment. The results below include transit time over the network to make the request to AWS Lambda.

Unsurprisingly, function initialization time and the size of the function shared a linear relationship. Developers should be mindful of including needless libraries of excessive size. A project would have to reach substantial size to impact unlucky users. Code sizes of 25 MB compressed started to reach unacceptable load times approaching four seconds. It would be unfortunate to hit this performance wall with a large project unaware of the load constraint. Project structuring would help to minimize this issue. Ideally a function's upload to AWS should only contain lines of code used by it. Anything extra is technically waste. This could involve clever build packaging to produce minimal Lambda functions that still share code locally within a project.

Thoughts, questions, or comments? Feel free to reach out at aaronbruckner@gmail.com.