AWS SDK for Javascript v2 Reaches End of Life: Important Facts
Safely Upgrade Your Lambda Functions to V3
The AWS SDK for JavaScript v2 is reaching its End of Life, yet it is still downloaded nearly 9 million times every week. This is despite AWS advising customers for over a year to start using v3 of the SDK. In fact, to discourage the use of v2, newer versions of the Lambda runtime on Node.js no longer come with aws-sdk
pre-installed. Instead, all Node.js runtimes starting from v18 now come with @aws-sdk
, which is v3 of the SDK.
The obvious solution is to migrate your applications to v3. However, migrating to another component isn't always as straightforward as we'd like, especially when there's a deep dependence on that component. This dependence can leave developers unable to upgrade to the latest version.
One reason developers avoid upgrading such components is the risk of introducing unintended bugs. I mean, if it's not broken, why fix it? Another reason could be that the team doesn't have the capacity to take on such a complex change due to other pressing priorities.
In this article, we'll discuss how you can safely and gradually migrate to AWS SDK for javascript v3.
Before we go further, let's gets some terms clarified.
aws-sdk
: this is v2 of the sdk.@aws-sdk
: this is v3 of the sdk.
One way to make aws-sdk available on Lambda running on Node.js 18+ is by bundling the SDK with your application. However, this is not recommended as it increases bundle size and leads to longer cold start times.
To safely migrate to @aws-sdk
, we'll split the process into two phases:
Lift & Shift
Refactor application code
Phase 1: Lift & Shift
This phase involves creating a Lambda layer that includes the aws-sdk package. The layer is then attached to your Lambda function, similar to how AWS makes the SDK available in earlier Node.js runtimes. This can be implemented by:
Creating a zipped file with the SDK
#!/bin/bash
echo \
'{
"name": "aws-sdk-v2",
"version": "1.0.0",
"description": "A module containing aws-sdk v2",
"dependencies": {
"aws-sdk": "^2.1691.0"
}
}' >> package.json
npm install
mkdir nodejs
mv node_modules nodejs
zip -rqm aws-sdk-v2.zip nodejs
rm package.json package-lock.json
Bundling the zipped as a Lambda layer
# Terraform
resource "aws_lambda_layer_version" "aws_sdk_v2" {
compatible_runtimes = ["nodejs18.x", "nodejs20.x"]
description = "Layer container aws-sdk v2"
filename = "./aws-sdk-v2.zip"
layer_name = "aws-sdk-v2"
source_code_hash = filebase64sha256("./aws-sdk-v2.zip")
}
Using the layer in a Lambda function
# Terraform
resource "aws_lambda_function" "function_with_aws_sdk_v2" {
...
layers = [aws_lambda_layer_version.aws_sdk_v2.arn]
}
The full project is on my github repository.
If, like me, you get annoyed by the EOL message the package emits, you can disable it by setting the following environment variable: AWS_SDK_JS_SUPPRESS_MAINTENANCE_MODE_MESSAGE=1
.
This solution offers several benefits. One of them is that no changes are needed in the application code; everything continues to work as it is. Another benefit is that it gives developers enough time to move on to the next phase while running on newer versions of Nodejs runtime.
Phase 2: Refactor Application Code
With enough time and Lambda running on the latest Node.js runtime, we can gradually update our application code to v3 of the SDK.
@aws-sdk
offers many benefits, including a smaller bundle size, S3 multipart upload, and TypeScript support, among other things. For example, to download a file from S3 using v2, you'd need to import the entire SDK, resulting in a large file size.
const AWS = require('aws-sdk');
const s3Client = new AWS.S3({ region: "REGION" });
let objectData;
s3Client.getObject({
Bucket: 'website-bucket',
Key: 'static-file.pdf'
}, (err, data) => {
objectData = data.Body.toString('utf-8');
});
With v3, the client for each AWS service is released as its own npm package. For instance, the S3 client is @aws-sdk/s3-client
.
const { S3Client, CopyObjectCommand } = require('@aws-sdk/client-s3');
const s3Client = new S3Client({ region: "REGION" });
const command = new CopyObjectCommand({
Bucket: 'website-bucket',
Key: 'static-file.pdf'
});
const response = await s3Client.send(command);
This strategy of making each client its own package not only results in a smaller bundle size but also faster load times since we're importing only the service we need.
Updating your code base can be a daunting task, but it doesn't have to be. AWS provides a utility that developers can use to automatically convert code written in v2 to v3. This tool is an npm package named aws-sdk-js-codemod
, and you can read all about it here.
It's important to understand that this is just a tool to speed up the process. As developers, it's our responsibility to ensure the code generated by this tool is correct, bug-free, and well tested.
Conclusion
As AWS draws the curtain on version 2 of the SDK, we need to be ready to transition to the new version, especially if we want to use the latest features or runtimes released by AWS.
References
https://aws.amazon.com/blogs/developer/announcing-end-of-support-for-aws-sdk-for-javascript-v2/
https://github.com/ben-x/cloudpedia/tree/master/content/lambda-layer-with-aws-sdk-v2
PS: If you like content like this, please hit the like button.