What does AWS-SDK v3 mean for node.js Lambda?

Best practice is about to get easier.

Yesterday I found out about @aws-sdk — the Javascript version of the AWS-SDK — is hitting version 3! I’m a bit behind the curve as this has been in developer preview since the end of November. But you’d have to be some sort of mad man to keep track of every AWS release note…

One of the things you find out when developing serverless functions is that you want to keep the deployment size small. You also learn that the aws-sdk is “just there” when you deploy a node.js function, so you can save some space by not bundling it. A little bit later you learn that the aws-sdk available to you is version 2.290.0, and that using library from August 2018 (and circa 200 versions behind the latest) will lead to missing features and unexpected behaviours.

And so the “best practice” has been to deploy with the version (hopefully latest!) of the aws-sdk that you developed, built and tested your function against.

The snag is that the aws-sdk is not all that light. The third iteration of the sdk aims to fix this by making the services truly modular. And in the spirit of adventure, I thought I’d check out just how well this was working.

I’ve created a benchmarking repo (you can find it here: https://github.com/thomasmichaelwallace/lambda-aws-sdk-size-benchmark). Effectively it’s a simple “get from dynamo” lambda function, that bundles with webpack (so we can enjoy the wonders of tree shaking).

v2/External: 743b (1x)

This version “mocks” the aws-sdk, which would be the same as relying on the external (2.290.0) version that node.js lambda functions deploy with. This version of the function deploys in an impressive 743 bytes zip file.

v2/Import: 573kb (771x)

In this version we deploy with the full aws-sdk, relying on webpack’s treeshaking to get the deployment size down. It does ok, but inflates our function by a factor of 771, taking us up to 573 kilobytes.

I also tried the import AWS from 'aws-sdk' variation of this to see if it would make much of a difference, but it turns out webpack was one step ahead of me and it’s exactly the same size.

v2/Direct: 90kb (121x)

It’s worth noting that version 2 of the SDK already supports importing specific clients directly. In the above approach I take the guesswork out for webpack and point it directly at the client I want to use. For my efforts I get the file down to a respectable 90 kilobytes (or a 121-fold increase from external).

v3: 31kb (41x)

Version 3 of the AWS-SDK (which apparently is packaged as the “v2 client”- it’s not up to us to understand the naming), defaults to modularised packages. However it also makes a modern node.js specific package available, which allows for additional optimisations. All this pays off when we get our package down to a very nice 31 kilobytes, just 41x the code size of nothing-at-all!

Using the external (lit. built-in) aws-sdk in your javascript lambda functions can be very tempting. However StackOverflow is filled with the bones of those who have lost many an hour to debugging as a consequence of mismatched versions and missing features.

Best practice therefore dictates that you should package the aws-sdk which you used to build and test the function. Previously people would baulk at including a 3mb library with every deployment. But thanks to the fantastic efforts of the JavaScript AWS-SDK team, this is becoming a much more palatable option.

The lesson: Using AWS-SDK v3 allows you to significantly reduce the size of your node.js lambda functions.

ed. after writing this I discovered that Yan Cui has done some much better research showing the time-cost of deploying with the aws-sdk, which is definitely worth a read too: https://theburningmonk.com/2019/03/just-how-expensive-is-the-full-aws-sdk/