Skip to content

New plan for AWS SDK v3#188

Merged
GrahamCampbell merged 12 commits into
mainfrom
sdk-v3-fixes
Apr 28, 2026
Merged

New plan for AWS SDK v3#188
GrahamCampbell merged 12 commits into
mainfrom
sdk-v3-fixes

Conversation

@GrahamCampbell
Copy link
Copy Markdown
Contributor

@GrahamCampbell GrahamCampbell commented Apr 27, 2026

The AWS SDK v3 compatibility shim is the wrong long-term architecture.

This PR removes the v2-style SDK v3 request layer and lays the foundation for the new approach:

  • Core remains backed by AWS SDK v2 for existing internal AWS calls.
  • SLS_AWS_SDK_V3 is removed as a runtime mode switch.
  • The COMMAND_MAP / CLIENT_MAP compatibility layer is removed.
  • Plugins should use AWS SDK v3 directly.
  • Serverless provides AWS SDK v3 configuration and credential resolution via provider.getAwsSdkV3Config().
  • A future optional compatibility package can restore legacy provider.request() / provider.sdk behavior for old plugins.

Why The Shim Is Removed

The shim tries to keep this AWS SDK v2-era abstraction alive:

await provider.request('S3', 'putObject', params);

AWS SDK v3 does not model AWS calls that way. Its native model is:

const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');

const s3 = new S3Client(config);
await s3.send(new PutObjectCommand(params));

Preserving provider.request(service, method, params) under SDK v3 requires Serverless to maintain a translation layer for every service and method. That creates permanent maintenance cost and an unclear plugin contract.

The right fix is not to make the maps extensible. The right fix is to remove the maps.

Scope

In scope:

  • Remove the AWS SDK v3 request shim.
  • Remove SLS_AWS_SDK_V3 everywhere.
  • Remove COMMAND_MAP and CLIENT_MAP.
  • Remove shim-only tests.
  • Remove unused AWS SDK v3 client dependencies.
  • Keep runtime core AWS requests on the existing AWS SDK v2 path.
  • Add provider.getAwsSdkV3Config() as the foundation for direct SDK v3 usage.
  • Document the new AWS SDK v3 plugin integration path.

Out of scope:

  • Migrating core internals to direct AWS SDK v3 clients.
  • Extracting AWS provider into a separate package.
  • Building the legacy compatibility package.
  • Updating third-party plugins.
  • Removing provider.request() entirely.
  • Removing provider.sdk entirely.

New Public Foundation API

The AWS provider now exposes:

const config = await provider.getAwsSdkV3Config(options);

The returned config is directly usable with AWS SDK v3 clients:

const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');

const config = await provider.getAwsSdkV3Config({ service: 'S3' });
const s3 = new S3Client(config);

await s3.send(new PutObjectCommand(params));

The returned config includes:

  • region
  • async credentials
  • requestHandler when proxy, CA, or timeout config requires it
  • maxAttempts
  • retryMode
  • customUserAgent when provided
  • other AWS SDK v3 client options passed through by the caller

Plugin Model

Plugins should own their AWS SDK v3 dependencies.

Example plugin package.json:

{
  "dependencies": {
    "@aws-sdk/client-s3": "^3.0.0"
  }
}

Example plugin code:

'use strict';

const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');

class ExamplePlugin {
  constructor(serverless) {
    this.provider = serverless.getProvider('aws');
  }

  async upload() {
    const s3 = new S3Client(await this.provider.getAwsSdkV3Config({ service: 'S3' }));

    await s3.send(
      new PutObjectCommand({
        Bucket: 'example-bucket',
        Key: 'example-key',
        Body: 'example-body',
      })
    );
  }
}

module.exports = ExamplePlugin;

Plugins should not rely on Serverless' transitive AWS SDK dependencies.

Credentials

getAwsSdkV3Config() exposes credentials as an async AWS SDK v3 credential provider, not as a static snapshot.

That is required for:

  • AWS SSO
  • MFA
  • assume-role profiles
  • expiring STS credentials
  • credential refresh during long deploys
  • stage-specific credentials
  • Serverless profile precedence

Credential source order is:

  • CLI --aws-profile
  • explicit profile passed to getAwsSdkV3Config()
  • stage-specific AWS_${STAGE}_PROFILE
  • stage-specific AWS_${STAGE}_ACCESS_KEY_ID and AWS_${STAGE}_SECRET_ACCESS_KEY
  • AWS_PROFILE
  • standard AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
  • provider.profile
  • AWS_DEFAULT_PROFILE || "default"
  • the AWS SDK v3 default provider chain as a fallback only when the selected default profile is absent from the shared credentials/config files

If the selected default profile exists but cannot resolve credentials, the original credential error is rethrown rather than falling through to ambient credentials.

The helper supports:

  • AWS_SHARED_CREDENTIALS_FILE
  • AWS_CONFIG_FILE
  • AWS SSO profiles
  • MFA profiles
  • assume-role profiles
  • temporary credential refresh

Region And Transport

Region resolves from explicit options.region, otherwise provider.getRegion().

The config helper carries existing Serverless transport behavior into AWS SDK v3 config for:

  • proxy env vars
  • custom CA env vars/files
  • AWS_CLIENT_TIMEOUT / aws_client_timeout

The returned config uses NodeHttpHandler when custom transport configuration is needed.

Core Internals

This change does not migrate core internals yet.

For now:

  • existing core AWS calls continue using the AWS SDK v2 request path
  • provider.request() remains available as legacy/internal behavior
  • provider.sdk remains AWS SDK v2
  • core direct AWS SDK v3 migration is a later project

Future core migration should use direct AWS SDK v3 clients and commands rather than recreating a generic request abstraction.

Legacy Compatibility Package

A future optional package can restore old plugin APIs for users who need abandoned or unported plugins.

Possible package name:

@oss-serverless/aws-legacy-compat

That package can patch:

provider.request(...);
provider.sdk;

It should be backed by AWS SDK v2 and clearly documented as legacy. It should not reintroduce v3 command/client maps.

@GrahamCampbell GrahamCampbell requested a review from Copilot April 28, 2026 12:07
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes the AWS SDK v3 “v2-style request shim” (command/client maps + SLS_AWS_SDK_V3 mode switch) and establishes a new plugin-facing foundation API for using AWS SDK v3 directly via provider.getAwsSdkV3Config(), while keeping core/internal AWS calls on the AWS SDK v2 request path.

Changes:

  • Remove the SDK v3 shim infrastructure (feature flag routing, command/client maps, v3 error adaptation) and simplify tests/CI accordingly.
  • Introduce provider.getAwsSdkV3Config() plus supporting helpers for SDK v3 client config and credential-provider resolution/caching.
  • Update plugin documentation to recommend direct AWS SDK v3 client usage and clarify the legacy status of provider.request() / provider.sdk.

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
lib/plugins/aws/provider.js Removes v3 shim routing; adds getAwsSdkV3Config() and v3 credential provider caching.
lib/aws/config.js Builds AWS SDK v3 client config (region, retries/maxAttempts, proxy/CA/timeout via NodeHttpHandler).
lib/aws/credentials.js New v3 credential-provider resolution logic (profiles/env/stage + default fallback behavior) and cache-key helper.
lib/aws/error-utils.js Removes shim-only v3→v2 error transformation utilities.
lib/aws/commands.js Removes shim command map used to translate v2-style calls to v3 commands.
lib/aws/client-factory.js Removes shim client factory and client map used by the v3 translation layer.
package.json Drops unused AWS SDK v3 client deps and adds @smithy/node-http-handler.
test/unit/lib/plugins/aws/provider.test.js Adds unit coverage for getAwsSdkV3Config() behavior and credential-provider reuse.
test/unit/lib/aws/config.test.js Adds unit coverage for v3 config building (maxAttempts, region fallback, transport options).
test/unit/lib/aws/credentials.test.js Adds unit coverage for default-profile fallback semantics and shared-file detection.
test/utils/*.js (api-gateway, websocket, sqs, sns, s3, misc, kinesis, iot, event-bridge, dynamodb, cognito, cloudformation) Removes dual v2/v3 test-client branches; standardizes on v2-based request helpers.
.github/workflows/validate.yml Removes v2/v3 mode matrix; runs packaging/unit tests once.
docs/guides/plugins/*.md Updates wording and adds guidance for plugin-owned AWS SDK v3 clients + getAwsSdkV3Config() usage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/guides/plugins/creating-plugins.md
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 28 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/guides/plugins/creating-plugins.md
Comment thread lib/aws/config.js
@GrahamCampbell GrahamCampbell merged commit c348877 into main Apr 28, 2026
4 checks passed
@GrahamCampbell GrahamCampbell deleted the sdk-v3-fixes branch April 28, 2026 15:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants