March 14, 2021 / 5 minutes / #AWS #DynamoDB #NoSQL #GraphQL #Serverless
In this blog post, I show upgrading strategies from AWS SDK V2 to V3 for a few most common use cases in Serverless, at least for me. Official docs are describing three migration paths, but for the purpose of this article, we'll focus only on the 3rd Path - the proper one using the Command objects and fully
async/await based approach.
The most frequent complaint regarding the new DynamoDB client from AWS SDK V3 was a lack of
DocumentClient library. Instead, we were forced to call
unmarshall() whenever inserting, putting or getting items from DynamoDB. This was introducing a lot of unnecessary complexity and caused code to be harder to follow and test.
In V2, once we had our
DocumentClient constructed, interaction with DynamoDB in Node.js was boiling down to using methods like
query and ending them with
DocumentClient is imported from a different package and created using
Moreover, you can call the document client operations using Command objects.
If you don't like this new style, you can still use the old
.put() method too. However, in this case, you need to import
DynamoDBDocument instead of
Interacting with Simple Storage from Lambdas is a widespread pattern. Let's talk about uploading, downloading, and preparing pre-signed URLs.
The complexity of uploading large files to S3 in V2 is hidden inside the
upload method. It takes care of initiating the multipart upload, uploading parts, and calculating checksums. There's also a famous
.promise() call at the end to promisify the call.
In V3, we are not only forced to import SDK in a modular way, but also we have to import two packages:
client-s3 - responsible for communicating with AWS S3, and
lib-storage, which is a high-level helper library containing classes like
Upload which now take care of multipart upload orchestration.
Pre-signed URLs are useful when you need to expose some data to the client in a secure way or allow them to upload files from the client directly to the S3. In such a scenario, the client requests a backend for a pre-signed URL, the backend sends it back to the client, and the client initiates uploading procedure to the S3 directly using provided URL.
In V2, you had two options to generate pre-signed URLs - synchronously and asynchronously.
In V3, there's only one option - asynchronous one. Moreover, it requires you to import
@aws-sdk/s3-request-presigner package and call
getSignedUrl using the client and the Command object.
Even though invoking functions from functions is considered as an antipattern by some, I believe that's not the case if you know what you're doing.
In V2, invoking Lambda asynchronously or synchronously required just the
FunctionName parameters. Optional params like
LogType: 'Tail' are helpful if we want to forward up to 4KB of logs from the invoked Lambda to the caller.
In V3, the signature is almost identical. The difference is in the
Payload parameter. While V2 accepted
string, V3 accepts only
Uint8Array. Since in Node.js
Buffer instances are also
Uint8Array instances, we can use them instead.
Up to version 3.7.0, using SSO credentials was impossible. The workaround was to copy & paste credentials provided by the SSO as environment variables. Luckily, this issue is now solved.
As I'm writing this, AWS SDK V3 is not working correctly with X-Ray, which is a showstopper for many of us. This is due to the new middleware architecture, which is incompatible with how the X-Ray SDK hooks into the version 2.x. But, there's a pull request already reviewed as ☑️, waiting to be merged
Currently, AWS SDK V3 is not supporting this. This is especially useful in multi-tenant SaaS environments where your Lambdas/Containers/VMs have to assume a dynamic role-based on runtime input/context.
In V2, there was this famous Keep-Alive trick which forced AWS SDK to reuse HTTP connections. This reduced the number of HTTP handshakes performed and improved overall Lambda performance. In V3, this is happening automatically.