If you use the AWS SDK inside of an AWS Lambda, which seems like a requirement for doing anything useful, you introduce a 2 second delay to the cold start time. This occurs even if you load it from the environment, instead of packaging it into your deployment, like a good citizen.
This graph shows the cold start and then avg runtime (hot runs) of several lambdas that just returns success after loading an npm package.
exports.handler = handler
function handler (lambdaEvent, context, callback) {
context.callbackWaitsForEmptyEventLoop = false
var AWS = require('aws-sdk')
callback(null, { statusCode: 200 })
}

Garbage is a lambda with a 20mb bin file that is not read, "bare" is a lambda with no loaded dependencies. I wanted to test whether it was loading into RAM or just loading onto disk that was expensive. Thankfully it looks like RAM is the only cost in time.
This is pretty grim. If you just need to do some CRUD with dynamo you have to load all 2.3MB of the SDK every time. This issue says you can use the SDK builder to build smaller packages, but the SDK builder makes a package that can only run in the browser (it has hard dependencies on the window and window.navigator objects).
Since AWS Lambda is such a big part of AWS's offering it would be nice to see a better solution here. Making an SDK builder that produced node-compatible packages would be nice, but even then SDK builder's output is larger than it needs to be (200kb for a dynamo only package!). That same issue claims it is due to the request signing infrastructure, but this package signs requests and builds down to 20kb. This dynamo db package uses it and builds down to 50kb. These targets are not unreasonable, and have a *full 2 second * improvement to cold start time.
@tyrsius
Thanks for the detailed analysis. Are your results indicating that it actually takes longer to load the SDK that's in Lambda rather than the one you package up? Have you tried moving the SDK import outside of the handler function (that may only affect runtime, not cold start).
You can build a smaller, node.js compatible bundle of the SDK using webpack or browserify.
Here's some instructions for configuring webpack to generate a node.js bundle:
http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/webpack.html#webpack-nodejs-bundles
You can also require individual services in your code so that only the services you use get pulled into your bundle:
http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/webpack.html#webpack-importing-services
Example: var DynamoDB = require('aws-sdk/clients/dynamodb');
It's true the bunded size of the SDK is still ~200KB when minified. Part of that is because the core of the SDK includes logic for handling requests/responses for any service. That means if a service uses JSON, we are still including the XML builder/parser. We are exploring ways to pull in just what's needed for an individual service, but I don't have a timeline for that yet.
Please let me know if the above suggestions have an appreciable affect on your timings.
@chrisradek Just the opposite, the aws-sdk-external bar indicates that the SDK was loaded from the environment, not packaged with the deployment.
That webpack bundler option looks promising, but its not easily findable. I did a lot of searching and never encountered it. You should really consider putting a link that on "https://sdk.amazonaws.com/builder/js/", or even better add an option to that builder to build a node version with webpack.
Getting the size of individual pieces down would be a major improvement, I hope you guys consider this a priority. 200kb for a dynamo client is pretty steep.
I tried packaging the aws-sdk/clients/dynamodb client, and here is the result.
βββ [email protected] (74 files) 388.4 kB
βββ xmlbuilder (17 files) 49.7 kB
βββ lodash (140 files) 114.5 kB
βββ util (2 files) 16.7 kB
βββ process (1 files) 3 kB
βββ object-assign-polyfill (1 files) 1 kB
βββ jmespath (1 files) 57.1 kB
βββ fs (1 files) 283 Bytes
βββ uuid (5 files) 5.4 kB
βββ crypto (1 files) 291 Bytes
βββ buffer (1 files) 54.8 kB
βββ base64-js (1 files) 3.6 kB
βββ ieee754 (1 files) 2.2 kB
βββ stream (1 files) 291 Bytes
βββ url (1 files) 285 Bytes
βββ querystring (1 files) 4.3 kB
βββ xml2js (3 files) 18.7 kB
βββ sax (1 files) 43.1 kB
βββ events (1 files) 9.8 kB
βββ http (1 files) 287 Bytes
βββ path (1 files) 6 kB
Bundle
Size: 780 kB
Time: 547ms
Bundle (Uglified)
Size: 292 kB
Time: 2s 490ms
A couple things jump out.
lodash library. I know lodash is awesome, but you really shouldn't use it in a library. Adding 114KB so that you can save a little time while coding is a big weight to push onto your consumers.xml. Its only 2.9kb, compared to 49kb for xmlbuilderTotally agree on getting the size of core down. lodash is actually a dependency of XML Builder, so if we can remove (or replace) the XML dependency for services that don't use XML, that should help considerably as well.
@chrisradek Oh man, you can get rid of lodash now then, because the latest xmlbuilder no longer depends on it!
@tyrsius Unfortunately, we're already on the latest version of XMLBuilder that is guaranteed to work with Node 0.8. Updating that dependency isn't an option, but replacing it with something smaller or with a smaller dependency graph could be.
Why are you maintaining comparability with node 0.8? It has been
end-of-life'd. So has node 0.12.
On Wed, Apr 26, 2017 at 7:35 AM Jonathan Eskew notifications@github.com
wrote:
@tyrsius https://github.com/tyrsius Unfortunately, we're already on the
latest version of XMLBuilder that is guaranteed to work with Node 0.8.
Updating that dependency isn't an option, but replacing it with something
smaller or with a smaller dependency graph could be.β
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/aws/aws-sdk-js/issues/1469#issuecomment-297428424,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABIeaEukJrMXzuQbrS50UKJBJbsJrgPVks5rz1ZJgaJpZM4NDQ5f
.
We still have many users running EOL'd versions of Node. Linux distros maintain and patch older versions of Node; running apt-get install nodejs on a fresh installation of Ubuntu 14.04, which will be supported by Canonical through 2019, will install Node 0.10.
Outside of a major version bump of the SDK, we wouldn't drop support for a platform unless doing so were unavoidable, and I believe we could probably replace XML Builder while still maintaining compatibility with older versions of Node.
Man, that's rough. I'm not sure asking people to upgrade node on a fresh install of an OS is too big of an ask, but this sounds like a pretty firm commitment.
I've been testing out what it would take to get the dynamo client under 100kb, and I've made really good progress, but not with Node 0.10 support. I might just have to fork this work. I am doing this for lambda's, which only support 4.3 and up, so maybe its worth having an AWS Lambda SDK fork that can optimize for that environment.
@jeskew @chrisradek Im still doing performance work, and I thought you guys might be interested in this flame graph of the aws sdk being loaded in a lambda

here is an interactive version
Just lazy loading the xmlbuilder until its used, which seems rare, could take 1/4 out of the cold start.
while i subscribe to the points above, I am also interested in the zipped and unzipped size of aws-sdk-js
2.138.0 for instance looks like this - untouched, without the dist folder, without the dist and the apis folder
16M aws-sdk
7.1M aws-sdk-no-dist
2.0M aws-sdk-no-dist-apis
2.6M aws-sdk.zip
1.1M aws-sdk-no-dist.zip
480K aws-sdk-no-dist-apis.zip
From a node (lambda) perspective, dist folder is not needed, and apis folder - I see only one require pointing to ../apis/metadata.json but I guess it is still very much needed.
Anyways, my point is that it would be nice to at least document (is it already? sorry but I cannot find anything) what is really needed for the library to run on node, and node alone. This way, at least we can clean up aws-sdk-js before generating the lambda zip. Thanks!
PS: maybe scripts and dist-tools should be added to .npmignore ?
@tyrsius
I just wanted to chime in that v3 of the SDK is available now as a preview. It has a modular design that should improve performance in Lambda and elsewhere.
Greetings! Weβre closing this issue because it has been open a long time and hasnβt been updated in a while and may not be getting the attention it deserves. We encourage you to check if this is still an issue in the latest release and if you find that this is still a problem, please feel free to comment or open a new issue.
Most helpful comment
@tyrsius
Thanks for the detailed analysis. Are your results indicating that it actually takes longer to load the SDK that's in Lambda rather than the one you package up? Have you tried moving the SDK import outside of the
handlerfunction (that may only affect runtime, not cold start).You can build a smaller, node.js compatible bundle of the SDK using webpack or browserify.
Here's some instructions for configuring webpack to generate a node.js bundle:
http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/webpack.html#webpack-nodejs-bundles
You can also require individual services in your code so that only the services you use get pulled into your bundle:
http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/webpack.html#webpack-importing-services
Example:
var DynamoDB = require('aws-sdk/clients/dynamodb');It's true the bunded size of the SDK is still ~200KB when minified. Part of that is because the core of the SDK includes logic for handling requests/responses for any service. That means if a service uses JSON, we are still including the XML builder/parser. We are exploring ways to pull in just what's needed for an individual service, but I don't have a timeline for that yet.
Please let me know if the above suggestions have an appreciable affect on your timings.