Migrating to AWS JavaScript SDK v3: Lessons Learned
There’s work coming your way! Node.js 16 reached end-of-life on September 11th, 2023. Also, the AWS Lambda runtime environment for Node.js 18 upgraded to v3 of the AWS SDK for JavaScript. So to upgrade Lambda functions from Node.js 16 to 18, you have to migrate to AWS JavaScript SDK to v3 as well. Unfortunately, v3 is not backward compatible with v2. In the following, I will share what I stumbled upon while upgrading many Lambda functions to v3.

When upgrading the AWS JavaScript SDK from v2 to v3, you should bookmark the following pages:
Import and Client
The first step is to import the SDK and initialize a client.
Old (v2)
v2 provided CommonJS modules only. This was how to import the SDK, the SQS client in this example.
const AWS = require('aws-sdk'); |
New (v3)
With v3, there are two options to import the SDK. Here is how to import the SQS client using ES modules.
Native JavaScript modules, or ES modules, are the modern approach to split JavaScript programs into separate modules. Learn more!
import { SQSClient } from '@aws-sdk/client-sqs'; |
By default, Lambda functions use CommonJS modules. To use ES modules, use the file suffix
.mjsinstead of.jsor settypetomodulein thepackage.json. Learn more!
In case you want to stick with CommonJS modules to avoid having to rewrite larger parts of your code, this is how to import the SQS client, for example.
const { SQSClient } = require('@aws-sdk/client-sqs'); |
Commands instead of methods
AWS decided to use a command-style approach for v3 of the AWS JS SDK. So, it’s sending commands instead of calling methods. Unfortunately, this requires to rewrite a lot of code.
Old (v2)
Instead of calling listContainerInstances(...) …
const AWS = require('aws-sdk'); |
New (v3)
… send a ListContainerInstancesCommand command. Luckily, the parameters stay the same.
const { ECSClient, ListContainerInstancesCommand } = require('@aws-sdk/client-ecs'); |
Promise
How to wait for results from AWS? I prefer using promises with the help of the async/await syntax.
Old (v2)
v2 uses callbacks by default. Therefore, it was necessary to append promise() to every method call.
const AWS = require('aws-sdk'); |
New (v3)
v3 uses promises by default.
const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3'); |
Callback
Do you prefer callbacks? Or do you want to avoid rewriting code?
Old (v2)
As mentioned above, v2 defaults to callbacks.
const AWS = require('aws-sdk'); |
New (v3)
But using callbacks is quite simple with v3 as well. The send(...) method accepts a callback function as the 2nd parameter.
const { IAMClient, DeleteAccountPasswordPolicyCommand } = require('@aws-sdk/client-iam'); |
Error handling
When things go wrong, handling errors is critical.
Old (v2)
The code property of the error includes the error code.
const AWS = require('aws-sdk'); |
New (v3)
With v3 use the name property of the error.
const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3'); |
S3 multi-part upload
Splitting large files into multiple parts when uploading them to S3 is essential to improve performance.
Old (v2)
The S3 client shipped with the high-level method upload(...), which handles multi-part uploads.
const AWS = require('aws-sdk'); |
New (v3)
AWS moved that functionality from the S3 client to a separate module with v3.
const { S3Client } = require('@aws-sdk/client-s3'); |
The AWS JavaScript SDK v3 does still not support parallel byte-range fetches. Check out widdix/s3-getobject-accelerator to accelerate fetching objects from S3.
Streaming S3 results
When dealing with large files on S3, keeping them in memory is not an option. Make use of streams instead.
The following examples show how to download, transform, and upload an object.
Old (v2)
The createReadStream(...) method allows piping an object stored on S3 into a stream.
const zlib = require('zlib'); |
New (v3)
With v3 the Body property of the GetObjectCommand, PutObjectCommand as well as the Upload functionality (see above) return or accept streams out-of-the-box.
const zlib = require('node:zlib'); |
Summary
Due to breaking changes between v2 and v3 of the AWS JavaScript SDK, migrating incurs a lot of work. But there is no way out. AWS plans to deprecate v2 soon. Also, the Node.js 18 environment for Lambda does ship with v3 only.
Further reading
- Article AWS Monitoring with EventBridge
- Article Self-hosted GitHub runners on AWS
- Article Fallback to on-demand EC2 instances if spot capacity is unavailable
- Tag lambda
- Tag sdk
