Skip to content

Migrate from AWS SDK v2 to AWS SDK v3 #685

@zjawol

Description

@zjawol

Migrate from AWS SDK v2 to AWS SDK v3

Scope & Context

The serverless-appsync-plugin currently depends on AWS SDK v2 (aws-sdk: ^2.1265.0) for all AWS API calls — AppSync, CloudFormation, CloudWatch Logs, Route53, and ACM. AWS has officially announced end-of-life for SDK v2 on September 1, 2025, after which it will no longer receive security patches or feature updates.

The plugin's src/index.ts imports types and clients directly from aws-sdk/clients/* (v2). A partial migration already exists in lib/aws-client-factory.js which uses @aws-sdk/client-* (v3) packages, but the source src/index.ts still relies on v2 types and package.json still declares aws-sdk as a production dependency.


Current behavior

All AWS API interactions in src/index.ts use AWS SDK v2:

import { ... } from 'aws-sdk/clients/cloudformation';
import { ... } from 'aws-sdk/clients/appsync';
import { ... } from 'aws-sdk/clients/cloudwatchlogs';
import { ... } from 'aws-sdk/clients/route53';
import { ... } from 'aws-sdk/clients/acm';

The package.json declares:

"dependencies": {
  "aws-sdk": "^2.1265.0"
}

This means:

  • The plugin ships ~180 MB of SDK v2 to every user's node_modules
  • Users on Node.js >= 18 receive deprecation warnings at runtime
  • After September 2025, the dependency will receive no security fixes
  • The monolithic v2 bundle cannot be tree-shaken, increasing install size
  • New AppSync API operations introduced after SDK v2 EOL are unavailable (see below)

Expected behavior

All AWS clients should use AWS SDK v3 (@aws-sdk/client-*) exclusively. The aws-sdk v2 dependency should be removed from package.json.

Relevant AWS documentation:

Benefits of completing the migration

Benefit Details
Smaller install footprint Only required service clients are installed instead of the full aws-sdk bundle (~180 MB)
Tree-shaking support ES module builds allow bundlers to eliminate unused code
Active maintenance v3 is the only supported SDK going forward — security patches, new features
Composable middleware v3's middleware stack makes it easy to add retries, logging, and custom auth
Native Promise support No more .promise() call wrappers — await client.send(new Command(...))
First-class TypeScript types Per-service types shipped with each package
New AppSync API operations Access to operations not available in SDK v2 (see below)

New AppSync API operations unlocked by SDK v3

Migrating to SDK v3 gives the plugin access to AppSync API operations that were either unavailable or incomplete in SDK v2. These can be used to extend the plugin's CLI commands.

EvaluateCode — test JS resolvers without deploying

Evaluates an APPSYNC_JS resolver or pipeline function handler against mock context data, without saving or deploying the code.

import { EvaluateCodeCommand } from '@aws-sdk/client-appsync';

await client.send(new EvaluateCodeCommand({
  runtime: { name: 'APPSYNC_JS', runtimeVersion: '1.0.0' },
  code: fs.readFileSync('resolvers/getUser.js', 'utf8'),
  context: JSON.stringify({ arguments: { id: '123' }, identity: { sub: 'abc' } }),
  function: 'request', // or 'response'
}));

Use case for the plugin: extend sls appsync evaluate to support JS resolvers (currently only VTL is supported via EvaluateMappingTemplate).

AWS docs: EvaluateCode · Testing resolver handlers


EvaluateMappingTemplate — test VTL templates without deploying

Evaluates a VTL request or response mapping template against mock context data.

import { EvaluateMappingTemplateCommand } from '@aws-sdk/client-appsync';

await client.send(new EvaluateMappingTemplateCommand({
  template: fs.readFileSync('templates/getUser.request.vtl', 'utf8'),
  context: JSON.stringify({ arguments: { id: '123' } }),
}));

Use case for the plugin: power the existing sls appsync evaluate command with the official API instead of local VTL evaluation.

AWS docs: EvaluateMappingTemplate


EvaluateCode — comprehensive context object mocking (February 2025)

As of February 2025, EvaluateCode supports comprehensive mocking of all $context properties, including:

  • identity (Cognito, IAM, Lambda, OIDC)
  • stash variables across pipeline functions
  • error and result for response handler testing
  • prev.result for pipeline function chaining

AWS announcement: AppSync enhances resolver testing with comprehensive context object mocking


StartDataSourceIntrospection / GetDataSourceIntrospection — auto-generate schema from RDS

Starts an introspection job against a relational database data source and retrieves the result, which can be used to auto-generate a GraphQL schema.

import {
  StartDataSourceIntrospectionCommand,
  GetDataSourceIntrospectionCommand,
} from '@aws-sdk/client-appsync';

const { introspectionId } = await client.send(
  new StartDataSourceIntrospectionCommand({ rdsDataApiConfig: { ... } })
);

const result = await client.send(
  new GetDataSourceIntrospectionCommand({ introspectionId, includeModelsSDL: true })
);

Use case for the plugin: new CLI command sls appsync introspect-datasource to auto-generate schema fragments from RDS/Aurora data sources.

AWS docs: StartDataSourceIntrospection · GetDataSourceIntrospection


PutGraphqlApiEnvironmentVariables / GetGraphqlApiEnvironmentVariables

Manage AppSync native environment variables at runtime without redeployment. The plugin already has sls appsync env get and sls appsync env set commands — these operations are the direct API backing for them and are only available in SDK v3.

AWS docs: PutGraphqlApiEnvironmentVariables


Technical inputs

Dependency changes (package.json)

Remove:

"aws-sdk": "^2.1265.0"

Add to dependencies:

"@aws-sdk/client-appsync": "^3.x",
"@aws-sdk/client-cloudformation": "^3.x",
"@aws-sdk/client-cloudwatch-logs": "^3.x",
"@aws-sdk/client-route-53": "^3.x",
"@aws-sdk/client-acm": "^3.x",
"@aws-sdk/credential-providers": "^3.x"

Update engines:

"engines": {
  "node": ">=20.0.0",
  "npm": ">=10.0.0"
}

Source changes

  • Migrate all type imports in src/index.ts from aws-sdk/clients/* to the corresponding @aws-sdk/client-* packages
  • Replace ServiceConfigurationOptions reference in src/types/serverless.d.ts with @aws-sdk/types
  • Commit the source src/aws-client-factory.ts (compiled version already exists in lib/) and wire it into src/index.ts
  • Replace .promise() call chains with native async/await using the client.send(new XxxCommand(...)) pattern
  • Extend AwsClientFactory with typed methods for any new commands used

CLI command extensions

  • Extend sls appsync evaluate to support JS resolvers via EvaluateCodeCommand (currently only VTL is supported)
  • Add full $context mock support to sls appsync evaluate using the February 2025 comprehensive mocking capability
  • Consider a new sls appsync introspect-datasource command backed by StartDataSourceIntrospectionCommand

Tests

  • Update all test mocks that stub AWS clients — v3 uses client.send(Command) instead of client.method().promise()
  • No changes expected to CloudFormation snapshot tests (output is unaffected)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions