AWS SDK JS v2 Simplifies Serverless Development
Serverless architectures are becoming more and more popular for building cloud-native applications. The growth of cloud services like AWS Lambda has made it easier than ever to implement serverless designs. At the same time, Node.js has emerged as a favorite language for writing serverless functions. This combination of serverless and Node.js is enabling developers to build highly scalable apps with minimal operational overhead.
To support these serverless Node.js applications, AWS has released version 2 of the AWS SDK for JavaScript (AWS SDK JS v2). This new major version includes significant improvements that streamline working with AWS services from Node.js. Modular architecture, auto-pagination, expanded service clients, and simplified authentication are some of the key enhancements in v2. These features all aim to make building serverless applications faster and easier.
Introduction
The AWS SDK JS v2 represents a major leap forward compared to v1. It has been rewritten from the ground up to provide a better developer experience for modern JavaScript environments like Node.js. The goals of v2 are improving modularity, optimizing performance, and removing cross-service dependencies.
At the core of v2 is a modular architecture with separate client packages for each AWS service. This allows including only the specific service clients your app needs. For example, you could install just the DynamoDB and S3 packages rather than the entire SDK. Modularity enables smaller bundle sizes and lazy loading of resources only when required.
For serverless apps, these improvements translate to faster cold starts, lower costs, and easier deployments. As Node.js and serverless continue their rapid growth, v2 simplifies building these cloud-native applications. Its enhancements directly target the needs of modern serverless development.
Comparison to Version 1
The AWS SDK JS v1 had a monolithic architecture containing all service clients in a single large package. This required deploying substantial unused code even if an app only used one or two services.
In contrast, v2's modular design allows installing individual service packages. For a serverless app using just DynamoDB and S3, the bundle size is reduced significantly compared to v1. Only those two service clients are included after tree shaking strips away all unused code.
The v2 SDK is broken down into granular client packages while v1 was one large SDK package. This fundamental change in architecture is key to optimizing bundle sizes and cold start performance.
Initializing Clients
Using specific AWS service clients in v2 is simple. First install the required packages:
npm install @aws-sdk/client-s3 @aws-sdk/client-dynamodb
Then import and instantiate clients as needed:
import { S3Client } from '@aws-sdk/client-s3';
const s3 = new S3Client({
region: 'us-east-1'
});
Only the S3 and DynamoDB clients are loaded rather than the entire SDK.
Lazy Loading Clients
The independent packaging in v2 enables lazy loading of service clients. For example, you may only need DynamoDB if a request accesses a table:
async function handler(event) {
if (event.table) {
const { DynamoDBClient } = await import('@aws-sdk/client-dynamodb');
// Use DynamoDB client
}
}
The DynamoDB client is imported dynamically when required instead of on startup. This optimizes performance and cost by deferring initialization until necessary.
Auto-Pagination
Another major addition in v2 is auto-pagination support. Pagination is frequently required when working with AWS APIs. Many service responses are paginated by default with additional results across multiple pages.
The SDK now handles pagination transparently for commands like list, scan, and query. When responses are paginated, the SDK will automatically request additional pages in the background. This streamlines working with paged results in services like S3, DynamoDB, Lambda, etc.
For example, calling s3.listObjects
will return all matching objects across any number of response pages. The SDK deals with the page iteration internally so your code stays simple.
S3 Select
One great use case for auto-pagination is retrieving data from S3 Select. S3 Select allows running SQL queries directly on objects in S3 buckets to filter and process data. Results are paginated by default.
With the SDK handling pagination, all matching rows across pages are fetched with no extra code:
const data = await s3.selectObjectContent({
Bucket: bucketName,
Key: objectKey,
Expression: 'SELECT * FROM S3Object',
ExpressionType: 'SQL'
});
This simplifies using S3 Select by abstracting pagination of result sets.
Pagination Settings
Auto-pagination includes configurable settings to customize behavior. You can tune page size, max results, and concurrency mode to balance performance and cost.
Smaller page sizes reduce memory overhead but increase requests. Sequential mode minimizes throttling risk while parallel mode improves latency. Tweaking these settings allows optimizing pagination to your specific workload.
Async Iteration
The SDK supports async iteration with auto-pagination. You can cleanly iterate over all results using a for-await-of
loop rather than implementing manual pagination logic:
async function listObjects(bucket) {
const results = [];
for await (const page of s3.listObjectsPaginator({Bucket: bucket})) {
results.push(...page.Contents);
}
return results;
}
This abstracts handling multiple result pages when calling AWS APIs that return paginated responses.
Expanded Service Clients
Version 2.0 launched with a selection of the most commonly used AWS service clients. Since then, support has rapidly expanded to now include over 45 services.
Some of the major new clients added are for DynamoDB, SQS, EventBridge, ECS, CloudWatch Logs, etc. This breadth of services makes v2 suitable for building full-stack serverless applications. Several clients are still in public preview like Kafka and Honeycode while AppFlow is currently in beta.
The v2 documentation provides a full list of available client packages. These can be installed individually from NPM after prefixing with @aws-sdk/client-
.
Updated Existing Clients
In addition to new services, the existing clients in v2 also include upgrades. The S3 and Lambda clients have additions like S3 Select and Lambda container image support. Some previous client names like Cognito Identity Provider were also renamed for clarity.
There can be breaking changes when switching from v1 so consult the migration guide. But overall v2 maintains wide compatibility with v1 configurations.
Compatibility
The SDK retains compatibility in many aspects to ease the transition from v1. For example, the credentials and configuration systems are familiar:
const credentials = new AWS.Credentials(accessKeyId, secretAccessKey);
const s3 = new S3Client({
credentials: credentials,
region: 'us-west-2'
});
Types like AWS.Credentials and AWS.Config are still available for consistency. Updating existing apps is simplified by this compatibility with common credential patterns.
Streamlined Authentication
Authentication and authorization have been streamlined in v2. A unified credentials provider now supports all mechanisms like environment credentials, EC2 instance metadata, ECS tasks, shared config files, and more.
The credentials provider is passed during client initialization:
import { Credentials } from '@aws-sdk/types';
import { S3Client } from '@aws-sdk/client-s3';
const s3 = new S3Client({
credentials: getCredentials()
});
async function getCredentials() {
return new DefaultCredentials();
}
This standardizes handling credentials from various sources. Mocking credentials for testing is also simpler without custom implementations.
Cognito Identity Support
For serverless apps, the SDK has built-in support for Cognito Identity. Here is an example configuring a Cognito Identity client as the credentials provider:
import { CognitoIdentityClient } from '@aws-sdk/client-cognito-identity';
import { fromCognitoIdentity } from '@aws-sdk/credential-provider-cognito-identity';
const client = new CognitoIdentityClient({
region: 'us-east-1'
});
const s3 = new S3Client({
credentials: fromCognitoIdentity({
client,
identityPoolId: 'IDENTITY_POOL_ID'
}),
region: 'us-east-1'
});
The client handles transparently getting credentials from a Cognito Identity Pool and renewing them automatically.
Cognito is commonly used to manage permissions to AWS resources for serverless functions. The simplified integration makes it easier to securely call AWS services from handlers.
Regional Endpoints
Another authentication enhancement is directly configuring regional endpoints. This allows targeting requests to specific AWS regions which reduces latency.
For instance, when running in Tokyo you may want to set:
const s3 = new S3Client({
region: 'ap-northeast-1',
endpoint: 'https://s3.ap-northeast-1.amazonaws.com'
});
To keep traffic within Asia Pacific regions. Regional endpoints can optimize performance for apps hosted in particular geographic areas.
Summary
The AWS SDK JS v2 introduces major improvements like modular architecture and auto-pagination that streamline building serverless apps. Tree shaking, lazy loading, and simplified authentication provide additional benefits for Node.js developers.
As serverless architectures and Node.js continue gaining popularity, v2 makes these workloads easier to implement and scale. The expanded service clients and transparent handling of common needs like pagination further reduce friction.
Overall v2 represents a big step forward in optimizing the SDK for cloud-native development. Serverless developers on Node.js should consider upgrading to leverage the simplifications and enhancements available today in the AWS SDK for JavaScript v2.
For teams looking to build serverless apps with Node.js and AWS, DevHunt provides a great platform to launch and promote your tools. With visibility across a wide developer audience interested in serverless, DevHunt can help showcase what your product offers.