The New Default Retry Behavior in AWS SDKs - Which Versions Changed and How Much of the Old Behavior You Can Keep

First Published:
Last Updated:

AWS SDKs and tools introduced a new retry behavior through an opt-in feature on May 20, 2026. An AWS Developer Tools Blog post published on November 10, 2026, states that this behavior is now the default, and the opt-in feature has been removed. However, the specific SDK versions that have adopted this default behavior vary. The table in the same post lists the Kotlin row as "To be announced."

This article details what changes and what remains unchanged, outlining the behavior for each SDK version and referencing relevant documentation. It covers the default mode, base delays, retry quotas, specific considerations for DynamoDB, and long polling. It will explain the behavior when no settings are configured, when the mode is explicitly set, when the maximum number of attempts is specified, and when the legacy option is used. Finally, it will outline the extent to which the previous behavior can be preserved, including for SDKs and tools that do not support the legacy option. This article is not an introduction to retry design principles and does not cover pricing.

In conclusion:

  • The changes are not limited to the default mode; the behavior of both the standard and adaptive modes has changed. The base delay is now 50 ms for transient errors and 1,000 ms for throttling errors. A retry after a transient error uses 14 tokens from the retry quota.
  • The version where the new behavior became the default varies by SDK. For Python, it is botocore 1.44.0. For Java 2.x, it is 2.58.0, which was released on November 11, 2026. Kotlin had not made the new behavior the default on the date of review. The tracking issue for Kotlin states that it will become the default in the next minor version.
  • From the version where the new behavior became the default, setting AWS_NEW_RETRIES_2026 has no effect. Earlier versions still read it.
  • Some SDKs cannot be completely reverted to their previous behavior. According to the tracking issue for AWS CLI v2, AWS CLI v2 does not accept legacy, and setting legacy causes every command that calls an AWS service to fail. The tracking issues for .NET and AWS Tools for PowerShell state that they discard an entire profile that contains a legacy setting.
  • Some sources still disagree. The Retry behavior page of the AWS SDKs and Tools Reference Guide still states, on the date of review, that opting in is required.

This article reviewed the documentation on November 13, 2026 (Japan Standard Time), and re-examined the November post and the tracking issues on November 14, 2026 (Japan Standard Time). Chapter 8 describes observations made by running botocore against a local stub on a Mac, and does not represent a promise made in the documentation.

Related articles on this site:

Table of Contents

  1. 1. Scope and Terms
  2. 2. What Changed on November 10, 2026
  3. 3. Which Version Changed the Default in Each SDK
  4. 4. New Values
  5. 5. What Happens in Each Configuration
  6. 6. How Much of the Old Behavior You Can Keep
  7. 7. What Is Not Retried
  8. 8. Observations on a Local Mac
  9. 9. Where the Sources Disagree, and Where No Statement Was Found
  10. 10. Failure Modes
  11. 11. Frequently Asked Questions About the New Default Retry Behavior in AWS SDKs
  12. 12. Summary
  13. 13. References

1. Scope and Terms

This chapter defines the scope, audience, materials consulted, and terminology used in this article. The key conclusions are as follows:

  • This article covers only the switch of the default on November 10, 2026. The overall retry mechanism is covered in a separate article on this site (Section 1.2).
  • The mode named standard behaves differently before and after November 10, 2026 (Section 1.4).
  • The "max attempts" parameter has two different methods of counting: the total number of attempts and the number of retries (Section 1.4, Section 5.2).
  • Each row in the tables gives the status as of its date of review, November 13 or November 14, 2026.
  • This article will not state that something is "unavailable" or "impossible" if the documentation does not explicitly state it (Section 1.5, Section 9.2).

1.1 Intended Audience

This article is intended for the following audience:

  • Developers using the AWS SDK who want to understand how error behavior might change when upgrading to a new SDK version.
  • Users who, after November 2026, have noticed that errors are being returned more quickly, or that DynamoDB retries have decreased.
  • Individuals who want to revert to previous default behavior.
  • Those who operate environments where multiple SDKs and the AWS CLI all read the same ~/.aws/config file.

This article assumes that readers are considering the following points, and checks each one against the sources:

  • On November 10, 2026, the default behavior changed across all SDKs.
  • Only the default mode was changed; explicitly using the standard mode will not result in any changes.
  • Setting AWS_NEW_RETRIES_2026 to false will revert to the previous behavior.
  • Setting AWS_RETRY_MODE=legacy will revert to the previous behavior across all SDKs.
  • Because 501 is a 5xx status code, the SDK also retries it.

1.2 Scope and Exclusions

This article covers the following:

  • The opt-in of May 20, 2026, and the switch of the default on November 10, 2026.
  • For the 13 rows of SDKs and tools, the version where the default changed and its status.
  • Changes in behavior and new values for both standard and adaptive configurations.
  • What happens when you upgrade the version in different configuration scenarios.
  • How to maintain previous behavior and its limitations.
  • Handling of errors that will not be retried, and how 501 errors are treated.
  • Discrepancies between documentation.
  • Observations from using botocore with a local stub on a local Mac.

This article does not cover:

  • Pricing.
  • General discussions on retry design, circuit breakers, and stream recovery. This site's LLM Inference Resilience Patterns on AWS covers this.
  • Timelines for the SDK and AWS CLI. This site's AWS History and Timeline regarding AWS SDKs and the AWS CLI covers this.
  • How the calling SDK and the internal queue within Lambda interact during asynchronous Lambda invocations. This site's What Happens to a Failed Asynchronous Lambda Invocation covers this.
  • The overall hierarchy of configuration layers. This site's Endpoint Resolution in the AWS SDKs and CLI covers this. This article only covers retry configurations.
  • Service-side throttling limits.
  • Which SDK is better than another.

AWS SDK for Java 1.x is not the subject of this article. The AWS SDK for Java 1.x Developer Guide states that AWS SDK for Java 1.x reached its end-of-support date on December 31, 2025. The table in the November 10, 2026 blog post only includes rows for Java 2.x.

1.3 Date of Review and Materials Reviewed

This article reviewed the following materials on November 13, 2026 (Japan Standard Time). The body of this article uses the short names in parentheses.

  • AWS Developer Tools Blog: Updated default retry behavior for AWS SDKs and tools (November post).
  • AWS Developer Tools Blog: Announcing updated retry behavior for AWS SDKs and Tools (May post).
  • AWS SDKs and Tools Reference Guide: Retry behavior page (Reference Guide page).
  • 13 tracking issues on GitHub related to various SDKs and tools. These 13 issues are referenced in the November post. While some are found in GitHub Discussions and others in Issues, this article refers to all of them as tracking issues.
  • botocore CHANGELOG and the release dates of botocore versions on PyPI.
  • botocore Config API Reference (botocore Config reference).
  • AWS SDK for Java 1.x Developer Guide: Document History.

This article read the AWS pages both through the AWS Knowledge MCP Server and as HTML retrieved with curl. This article checked its direct quotes against these texts. For the tracking issues, this article read the body and the update comments of November 11, 2026. On November 14, 2026 (Japan Standard Time), this article reviewed the November post and the 13 tracking issues again. The table in the November post and the body of the tracking issues for Kotlin and AWS CLI v2 had been updated. Table rows with a date of review of 2026-11-14 give the values from this second review.

1.4 Terms, and Different Things with the Same Name

This article uses the following terms with the same meaning throughout:

  • retry mode: This setting determines which retry mechanism the SDK will use. The possible values are standard, adaptive, and legacy. The environment variable is AWS_RETRY_MODE, and the config file key is retry_mode.
  • transient error: A temporary error. The Reference Guide page lists examples such as connection resets and I/O failures, as well as HTTP 500, 502, 503, and 504 errors without recognizable error codes (Section 4.1).
  • throttling error: An error indicating that the service rejected the request due to the rate of requests. The SDK identifies it by error codes such as Throttling or ThrottlingException (Section 4.1).
  • base delay: The baseline time used for delay calculations (Section 4.2).
  • retry quota: The token budget within the SDK client. Tokens are consumed with each retry attempt, and when the budget is exhausted, the SDK will return an error without retrying. The Reference Guide page refers to this as a "Retry quota (token bucket)" (Section 4.3).
  • opt-in variable: This is AWS_NEW_RETRIES_2026. Starting May 20, 2026, setting this to true will allow you to test the new behavior.
  • Default in version: The version that the table in the November post and the tracking issues give as the one where the new behavior became the default.
  • Date of review: The date on which this article reviewed the documentation: November 13, 2026, and November 14, 2026, for the rows that this article reviewed again.

The sources this article read contain different things with the same name.

  • standard: The standard mode has different behavior before and after November 10, 2026. The November post indicates that this update changes how standard and adaptive are handled. This article refers to the standard before the update as "previous standard" and the standard after it as "updated standard." The "previous standard" had a base delay that differed by SDK, and a transient error retry used 5 or 10 tokens (Section 2.3, Table 2).
  • default: The "default" settings have three sources. The first is the default within each SDK's code. The second is the "Default" column in the settings table on the Reference Guide page, which gives standard and 3 on the date of review. The third is the "Default in" column in the November post. The beginning of the same Reference Guide page also states that opt-in is required as of the date of review (Section 9.1).
  • legacy: The word is both the retry mode value legacy and a general word for "previous default behavior." In Python and Ruby, the previous default mode was legacy. In .NET and Go, the previous default mode was standard, and it used the values associated with the previous standard. This article uses legacy only when referring to the mode name, and uses "previous default behavior" for the general meaning.
  • max attempts: The "Max attempts" on the Reference Guide page refers to the total number of attempts, including the initial request. The max_attempts setting in botocore's Config refers to the number of retry attempts, excluding the initial request. MaxErrorRetry in the AWS SDK for .NET also counts retries. This article separates the total number of attempts from the number of retries every time (Section 5.2).
  • retry quota: The "retry quota" in this article refers to the token budget within an SDK's client. It is different from MaximumRetryAttempts in Lambda event source mappings and from the quotas in Service Quotas.
  • tracking issue: The November post refers to all thirteen items as "tracking issues." On GitHub, these can be found in both Discussions and Issues.

1.5 Terms for the State of the Sources

This article uses the following six terms to describe the state of the documentation. These terms, including their English spellings, are also used in the tables.

  • Stated: The documentation contains a statement regarding the matter.
  • Stated as not supported: The documentation explicitly states that the matter is not supported or cannot be used.
  • Documentation does not list: While a list or table exists, the specific item is not included. This does not necessarily indicate that the matter is unsupported or unavailable.
  • No statement found: Despite searching using different keywords and categories of documentation (as described in Section 1.3), no relevant statement could be found. This does not necessarily indicate that the matter is absent or impossible.
  • Sources disagree: The statements regarding the same matter in two different documents are contradictory. This article presents both statements, along with their sources, without designating either as incorrect.
  • Inference: This is an inference made by this article, and is not a statement found in any of the documentation. This article says in the same sentence that it is an inference.

All dates referenced in this article are presented with the year. Pages may be rewritten after the date of review.

2. What Changed on November 10, 2026

This chapter shows, in the words of the sources, the switch from opt-in to default and then the change to standard itself.

2.1 From Opt-in to Default

The May post, dated May 20, 2026, implemented the new behavior through an opt-in setting. The May post reads:

These changes will become the default in November 2026.

The November post, dated November 10, 2026, reads:

Starting November 10, 2026, the updated behavior is the default, and we have removed the opt-in. Availability varies by SDK and tool.

The same November post places the following sentence before the table:

Every SDK and tool listed below, except Kotlin, makes the updated behavior the default.

This means the change did not happen all at once on November 10, 2026. According to the November post, SDKs and tools, excluding Kotlin, made the new behavior the default from the versions in the table. Chapter 3 lists these versions.

2.2 Versions That No Longer Read the Variable

The November post states that the versions where the new behavior became the default stopped reading AWS_NEW_RETRIES_2026.

These releases stop reading AWS_NEW_RETRIES_2026, and setting the variable now has no effect. This change applies only to the versions listed in this post and later. Earlier versions still honor AWS_NEW_RETRIES_2026.

This passage reveals two key points:

  • From the version in the table on, setting AWS_NEW_RETRIES_2026 to false will not revert to the previous behavior. The November post also states that after you upgrade, the SDK ignores this variable.
  • In versions prior to the one mentioned in the table, setting AWS_NEW_RETRIES_2026=true allows you to test the new behavior. If the variable is not set, the previous behavior remains in effect.

The Python tracking issue notes that botocore reads this variable only once, during import. Changing the variable later in the application has no effect. The Java 2.x tracking issue states that versions 2.58.0 and later log a warning if the variable has any value other than true.

2.3 The Definitions of Standard and Adaptive Changed

The November post states that the changes are not limited to the default mode.

This update changes how standard and adaptive (a rate-limiting mode built on standard) retry modes handle failed requests. It also makes standard the default for SDKs that had previously defaulted to legacy.

In other words, there are two changes. The first is a change in the behavior of both the standard and adaptive modes. The second is that, in SDKs whose previous default was legacy, the default became standard.

The first change also affects applications that explicitly specified standard mode. For the tokens that a transient error retry used in the previous standard, the May post states:

In the updated standard mode, each transient error retry costs 14 tokens (up from 5 in the previous version of standard mode).

For the base delay, the May post states that each SDK previously used the same base delay regardless of the error type, and that the value ranged from 10 ms to 1,000 ms across SDKs. However, the tracking issues for Java 2.x and JavaScript 3.x give the previous base delay as 100 ms for transient errors and 500 ms for throttling errors. Here the sources disagree (Sources disagree, Section 9.1). Table 2 lists the previous values, by SDK, as described in the tracking issues.

3. Which Version Changed the Default in Each SDK

This chapter lists versions of the SDKs and tools that have been updated with new default behaviors, referencing the table in the November post and the tracking issues.

3.1 Version Table

Table 1 lists the Default in column of the November post's table, alongside the status in the tracking issues. The tracking issue columns are based on the update comments of November 11, 2026 and the Status table in the body. The date of review is November 14, 2026, for the Java 2.x, Kotlin, and AWS CLI rows, and November 13, 2026, for the other rows.

SDK or toolDefault in, November postDefault version, tracking issueFirst opt-in version, tracking issueDate of review
Java 2.x2.58.0software.amazon.awssdk version 2.58.0, November 11, 20262.44.22026-11-14
Pythonbotocore 1.44.0boto3 and botocore version 1.44.0, November 10, 20261.43.32026-11-13
.NETAWSSDK.Core 4.0.103.0AWSSDK.Core version 4.0.103.0, November 10, 20264.0.4.02026-11-13
PowerShellAWS.Tools.Common, AWSPowerShell.NetCore, and AWSPowerShell version 5.0.332AWS.Tools.Common version 5.0.332, November 10, 20265.0.2022026-11-13
JavaScript 3.x3.1166.0 along with @smithy/core version 3.40.0 or later@smithy/core version 3.40.0, November 10, 2026@aws-sdk/client-* version 3.1060.02026-11-13
PHP3.403.3aws-sdk-php version 3.403.3, November 10, 20263.401.12026-11-13
KotlinTo be announced. To test now, opt in with 1.9.0 or later.Next minor version, expected in December 2026 or January 20271.6.73. Full behavior with 1.9.0 or later2026-11-14
Rustaws-config 1.13.2 along with BehaviorVersion::v2026_11_10() or lateraws-config version 1.13.2, November 10, 2026aws-config version 1.8.172026-11-13
Swift1.8.24aws-sdk-swift version 1.8.24, November 10, 20261.7.92026-11-13
Rubyaws-sdk-core 3.267.0aws-sdk-core version 3.267.0, November 10, 20263.248.02026-11-13
Go 2.xv1.48.0v1.48.0 and service modules from November 10, 2026 and laterv1.42.02026-11-13
C++1.11.926aws-sdk-cpp version 1.11.926, November 10, 20261.11.8362026-11-13
AWS CLI2.40.0AWS CLI version 2.40.0, November 10, 20262.34.572026-11-14

Table 1 provides the following clarifications:

  • For the Java 2.x and Kotlin rows, the sources disagreed on November 13, 2026, but no longer disagree on November 14, 2026. Refer to Sections 3.2 and 3.3 for details.
  • The Python version 1.44.0 was released on November 10, 2026, according to PyPI. The last version before it was 1.43.127, published on PyPI on November 9, 2026. Chapter 8 compares these two version lines.
  • The row for AWS CLI refers to versions of AWS CLI v2. The default mode of AWS CLI v2 and how it handles legacy are described in Sections 3.4 and 6.2.

3.2 Java 2.x

The table in the November post lists the Java 2.x row as 2.58.0. When this article read the table on November 13, 2026, that row displayed "To be announced." The Java 2.x tracking issue states the following in the Important box at the top of its body:

Starting in software.amazon.awssdk:* version 2.58.0 (released November 11, 2026), the updated retry behavior is the default and the AWS_NEW_RETRIES_2026 environment variable is removed.

Version 2.58.0 was released on November 11, 2026, the day after the November post was published. On November 14, 2026, both the table in the November post and the tracking issue for Java 2.x give the same version.

The tracking issue for Java 2.x states that 2.58.0 changes the default mode from legacy to standard. Previously, in the Java 2.x legacy mode, there was a retry quota of 500 tokens. Five tokens were used for retrying transient errors, and no tokens were used for retrying throttling errors. The tracking issue for Java 2.x also states that all modules within software.amazon.awssdk should be on the same version. Using older DynamoDB modules with the newer core modules will only apply a partial set of changes.

3.3 Kotlin

For Kotlin, the table in the November post states:

To be announced. To test now, opt in with 1.9.0 or later.

The Kotlin tracking issue states the following in the Update box at the top of its body:

The AWS SDK for Kotlin will make it the default, and remove AWS_NEW_RETRIES_2026, in its next minor version, which follows the next Kotlin language release and is expected in December 2026 or January 2027. Until then, you can opt in. Version 1.8.0, which this post previously named, shipped without the change.

The same tracking issue notes that while opt-in is available from version 1.6.73, the full behavior is only available from version 1.9.0 or later. Prior to version 1.9.0, even with opt-in enabled, transient error retries used 5 tokens instead of 14. When this article read it on November 13, 2026, the tracking issue gave the default version as 1.8.0 (tentatively Q1 2027), which disagreed with the table in the November post. On November 14, 2026, the two sources no longer disagree. In both sources, Kotlin had not made the new behavior the default on the date of review. The Kotlin tracking issue also states that while opt-in is enabled, setting legacy does not stop the new behavior, and the SDK treats legacy the same as standard. For the behavior after the default switches, the tracking issue states that it will update this section at the time of the switch.

3.4 AWS CLI v2

When this article read it on November 13, 2026, the tracking issue for AWS CLI v2 contained discrepancies between the main text and a comment from November 11, 2026. The main text stated that the previous default setting for AWS CLI v2 was legacy and that you could revert with AWS_RETRY_MODE=legacy. However, the comment from November 11, 2026 states:

Correction: The original version of this post said that AWS CLI v2 previously defaulted to legacy retry mode and that you could revert with AWS_RETRY_MODE=legacy. That was wrong. AWS CLI v2 already uses standard mode by default, and it doesn't accept legacy.

The same comment continues:

If AWS_RETRY_MODE=legacy is set, or retry_mode = legacy is set in the profile the AWS CLI uses, every command that calls an AWS service fails.

Upon reviewing it again on November 14, 2026, this article found that the main text had been updated. The main text now states that the retry mode itself does not change and that AWS CLI v2 already uses standard as the default. The Warning box in the main text reads:

AWS CLI v2 doesn't support legacy retry mode. If AWS_RETRY_MODE=legacy is set, or retry_mode = legacy is set in the profile the AWS CLI uses, every command that calls an AWS service fails with Invalid value provided to "mode": "legacy".

The Before table in the main text gives the previous values as a base delay of 1,000 ms for transient errors, 3 total attempts, and 3 total attempts for DynamoDB and DynamoDB Streams. Table 2 uses these values.

The same comment and the main text state that two changes that were not included in the opt-in shipped in version 2.40.0. The first was that the default total attempts for DynamoDB and DynamoDB Streams became 4. Before that, it was 3 even with the opt-in variable set. The second was that an HTTP 429 with an error code that the operation's model does not define is now retried as a throttling error.

3.5 SDKs That Need Other Components When You Upgrade

In several SDKs, upgrading the core version alone does not bring in all of the new behavior. The tracking issues state the following:

  • Go 2.x: In addition to v1.48.0, versions of the service modules on or after November 10, 2026, are required. Older versions of service/dynamodb, service/dynamodbstreams, service/sqs, service/sfn, and service/swf still read AWS_NEW_RETRIES_2026.
  • JavaScript 3.x: The new behavior is enabled by default in @smithy/core version 3.40.0. Versions 3.723.0 and later of @aws-sdk/client-* will incorporate this behavior when reinstalled or when the lockfile is updated.
  • .NET: The change to the default total attempts for DynamoDB requires versions 4.0.17.11 and later of AWSSDK.DynamoDBv2, and versions 4.0.4.27 and later of AWSSDK.DynamoDBStreams. With older versions, clients keep 10 retries even with AWSSDK.Core version 4.0.103.0.
  • Rust: Clients using BehaviorVersion::v2026_11_10() or later will have the default behavior enabled. For DynamoDB, the corresponding versions of aws-sdk-dynamodb and aws-sdk-dynamodbstreams are also required.
  • Java 2.x: Ensure all modules are on the same version (see Section 3.2).

3.6 Previous Defaults

Table 2 lists the previous defaults, as described in the "Before" column for each tracking issue. The Kotlin row gives the current default on the date of review. The AWS CLI v2 row gives the values from the main text reviewed on November 14, 2026 (Section 3.4). The date of review is November 14, 2026, for the AWS CLI v2 row, and November 13, 2026, for the other rows.

SDK or toolPrevious default modePrevious base delay for transient errorsPrevious total attemptsPrevious total attempts, DynamoDBDate of review
Java 2.xlegacy100 ms492026-11-13
Pythonlegacy1,000 ms510. DynamoDB Streams: 52026-11-13
.NETStated as unchanged1,000 ms3112026-11-13
PowerShellStated as unchanged1,000 ms3112026-11-13
JavaScript 3.xstandard100 ms332026-11-13
PHPlegacy100 ms311. DynamoDB Streams: 122026-11-13
KotlinStated as unchanged10 ms332026-11-13
RustStated as unchanged1,000 ms332026-11-13
Swiftlegacy. Behaves the same as standard1,000 ms332026-11-13
Rubylegacy300 ms411. DynamoDB Streams: 42026-11-13
Go 2.xStated as unchanged1,000 ms332026-11-13
C++DefaultRetryStrategy25 ms, no jitter11112026-11-13
AWS CLI v2standard. See Section 3.41,000 ms332026-11-14

Additional notes regarding Table 2 are as follows.

  • "Stated as unchanged" marks a row whose tracking issue states that the retry mode itself does not change. The JavaScript 3.x tracking issue states that standard remains the default.
  • The Python tracking issue states that the previous legacy had no retry quota. The tracking issues for Ruby, PHP, and C++ also state that they previously lacked a retry quota in their default settings.
  • In the previous standard, the tokens for a transient error retry varied by SDK. Python, Go 2.x, and Swift used a value of 5, except for timeout errors, which used a value of 10. .NET and PowerShell used a value of 5, while JavaScript 3.x and Kotlin used a value of 10.
  • The tracking issue for C++ states that from version 1.11.836 to 1.11.919, standard mode was the default even without the opt-in. From version 1.11.920 up to just before version 1.11.926, it reverted to the DefaultRetryStrategy.
  • The tracking issue for Swift states that within this SDK, the legacy and standard behaviors are the same.

4. New Values

This chapter describes the updated standard values, as presented in the text on the Reference Guide page. Figure 1 illustrates the process leading up to a failed call being retried.

How a Failed Call Is Retried After November 10, 2026
How a Failed Call Is Retried After November 10, 2026

4.1 Error Classification

The Reference Guide page categorizes failed requests into three types: transient, throttling, and non-retryable. The error code and the HTTP status code determine this classification.

The Reference Guide page lists the following as transient errors:

  • RequestTimeout, RequestTimeoutException, InternalError, IDPCommunicationError
  • I/O failures, including connection resets, DNS name resolution failures, and socket timeouts.
  • HTTP 500, 502, 503, and 504 errors without a recognizable error code.

The Reference Guide page lists 14 error codes, including Throttling, ThrottlingException, ProvisionedThroughputExceededException, and SlowDown, as throttling errors. The Reference Guide page states that a 5xx with a throttling error code is treated as a throttling error, not a transient error. The SDK first checks the error code and then the HTTP status code.

The Reference Guide page lists the following as non-retryable errors: AccessDeniedException, ValidationException, ResourceNotFoundException, among others. These errors are returned to your code immediately.

4.2 Base Delays and the Formula

The Reference Guide page states that the SDK computes the delay with the following formula:

delay = random(0, 1) × min(20,000 ms, base_delay × 2^retry)

base_delay is 50 ms for transient errors and 1,000 ms for throttling errors. retry starts at 0 for the first retry. The cap on a delay is 20 seconds. random(0, 1) generates a uniform value between 0 and 1, which the Reference Guide page refers to as "full jitter."

In the example provided in the Reference Guide page, the first retry after a 503 error waits between 0 and 50 ms, with an average of approximately 25 ms. After a throttling event, the first retry waits between 0 and 1,000 ms, with an average of approximately 500 ms. With the default total attempts of 3, a delay does not reach the 20-second cap.

4.3 Retry Quota

The Reference Guide page specifies the retry quota values as follows:

  • The quota capacity is 500 tokens.
  • Transient error retries consume 14 tokens.
  • Throttling error retries consume 5 tokens.
  • If a retry is successful, the tokens used for that retry are returned.
  • If a request succeeds without any retries, 1 token is returned.

When the quota reaches 0, the SDK will return an error without attempting any retries. The Reference Guide page states that the retry quota will not delay or prevent the initial request. The quota scope typically applies to a single instance of an SDK client and is not shared across processes or hosts. The Reference Guide page also notes that the specifics of this scope may vary depending on the SDK.

The Reference Guide page states that, with the default total attempts of 3, the budget starts to drain when more than about 22% of requests have sustained transient failures. For throttling errors, this threshold is approximately 32%. As an inference by this article, if all requests consistently fail due to transient errors, the quota will be exhausted after approximately 35 retries (500 divided by 14). Section 8.4 counts this number in botocore.

4.4 DynamoDB and DynamoDB Streams

The Reference Guide page states that the following default settings are applied to DynamoDB clients:

  • The base delay for transient errors is 25 ms, rather than 50 ms.
  • The base delay for throttling errors is 1,000 ms, the same as for other services.
  • The total attempts are 4 instead of 3.

The Reference Guide page also indicates that these default settings apply to both DynamoDB and DynamoDB Streams. However, the Java 2.x tracking issue states that the Java 2.x DynamoDB Streams client uses the general defaults. Here the sources disagree (Sources disagree, Section 9.1).

The tracking issue concerning Java 2.x further states that when developers explicitly configure a retry mode or retry strategy in the DynamoDB client's code, the DynamoDB default settings no longer apply. In that case, the total attempts are 3, and the base delay starts at 50 ms.

The previous total attempts for DynamoDB varied by SDK. As shown in Table 2, Java 2.x had 9, Python had 10, while .NET, PowerShell, PHP, Ruby, and C++ all had 11. The DynamoDB Streams client for PHP had 12.

4.5 Long Polling

The Reference Guide page lists the following four operations as long-polling operations:

  • SQS.ReceiveMessage
  • SFN.GetActivityTask
  • SWF.PollForActivityTask
  • SWF.PollForDecisionTask

In these operations, even when the retry quota is depleted and the retry is blocked, the SDK will pause before returning an error. The Reference Guide page explains that long-polling operations are typically called repeatedly without any delay in between. Without this pause, when the quota is depleted, the polling loop immediately sends the next request, which can increase CPU usage and network traffic on the client.

4.6 HTTP 429 and x-amz-retry-after

Several tracking issues state that an HTTP 429 whose error code the operation does not model is now retried as a throttling error. The tracking issues for Python, PHP, .NET, PowerShell, Go 2.x, Swift, Rust, C++, and AWS CLI v2 state this. The tracking issues for PHP, .NET, PowerShell, Go 2.x, Swift, Rust, C++, and AWS CLI v2 indicate that this change was not included in the opt-in feature. The Python tracking issue also mentions this point as an additional change for those who had previously configured the opt-in feature.

The Reference Guide page describes the handling of the x-amz-retry-after header as follows: Some services include this header in their error responses. The value is a delay in milliseconds. The SDK uses the header value, with the computed delay as the lower bound and the computed delay plus 5,000 ms as the upper bound. The SDK does not apply jitter to the value in this header.

5. What Happens in Each Configuration

This chapter shows, for each configuration, what happens when you upgrade the SDK to the Default in version or later.

5.1 Six Scenarios

The "Does this impact me?" section of the November post outlines six scenarios. Table 3 details these scenarios. The left column presents the questions from the November post verbatim, while the right column is this article's summary. The date of review for all rows is November 13, 2026.

Question in the November postWhat happens when you upgradeDate of review
No explicit retry configuration at all?All changes are applied. In SDKs that previously used legacy as the default, the default becomes standard.2026-11-13
Explicitly set retry mode to standard or adaptive?The new backoff timing, retry quota costs, and DynamoDB defaults apply. While the mode selection remains unchanged, the behavior of the mode will change.2026-11-13
Explicitly set max_attempts or backoff settings?The configured values remain unchanged. Values you did not set, such as retry quota costs, take the new defaults.2026-11-13
Explicitly set retry mode to legacy?The specific changes vary depending on the SDK. Some SDKs do not accept the legacy mode (see Section 6.2).2026-11-13
Already set AWS_NEW_RETRIES_2026=true?Most behavior remains the same. Minor changes specific to individual SDKs that were not included in the opt-in will be applied.2026-11-13
Set AWS_NEW_RETRIES_2026=false?The SDK will ignore this variable and use the new behavior.2026-11-13

Additional notes regarding Table 3 are as follows.

  • For the third row, the Java 2.x tracking issue states that Java 2.x in legacy mode ignores max_attempts in the config file. In legacy mode, DynamoDB clients ignored all three: the environment variable, the system property, and the config file.
  • For the third row, the Ruby tracking issue states that under the previous legacy default, neither max_attempts nor AWS_MAX_ATTEMPTS were applied. The new default now applies these settings.
  • For the fourth row, the C++ tracking issue states that legacy mode ignores both AWS_MAX_ATTEMPTS and max_attempts.
  • For the fifth row, the changes that were not part of the opt-in vary by SDK. Many tracking issues name the retry of an HTTP 429 whose error code is not modeled (see Section 4.6).

5.2 Two Ways to Count Max Attempts

The "Max attempts" value on the Reference Guide page refers to the total number of attempts, including the initial request. The Reference Guide page states:

A max attempts value of 3 means the SDK makes one initial request and up to two retries.

Both the environment variable AWS_MAX_ATTEMPTS and the max_attempts setting in the config file define this total number of attempts.

In botocore's Config, retries has two keys: total_max_attempts and max_attempts. The botocore Config reference describes total_max_attempts as the total number of attempts, including the initial request, while max_attempts refers to the number of retry attempts, excluding the initial request. The botocore Config reference recommends total_max_attempts because it corresponds to both AWS_MAX_ATTEMPTS and the max_attempts setting in the config file.

Therefore, in Python, the following two configurations have the same meaning:

from botocore.config import Config

# Both settings allow one initial request and up to four retries.
config_a = Config(retries={"total_max_attempts": 5})
config_b = Config(retries={"max_attempts": 4})

The AWS SDK for .NET's MaxErrorRetry also counts retry attempts. The .NET tracking issue states that the total number of attempts is this value plus one. If a Python user who previously used a total of 5 attempts wants to revert to that value, setting max_attempts in Config to 5 will result in a total of 6 attempts.

6. How Much of the Old Behavior You Can Keep

This chapter shows how much of the previous behavior you can keep after an upgrade. Figure 2 shows which values keep their old value for each setting.

Which Setting Keeps Which Old Value
Which Setting Keeps Which Old Value

6.1 The Variable Does Not Restore It

The November post states:

A complete revert is not available in every SDK. After you upgrade, unsetting AWS_NEW_RETRIES_2026 or setting it to false doesn't restore the previous behavior.

The November post gives two ways to keep the previous behavior. The first is to set legacy. The second is to set previous values one by one.

6.2 SDKs That Accept Legacy and SDKs That Do Not

The first way in the November post is to set AWS_RETRY_MODE=legacy, or to use retry_mode = legacy in the config file, or to configure legacy mode within the code. The November post notes that how much of the previous behavior legacy restores varies by SDK.

Table 4 lists how each SDK handles legacy mode, referencing the "Legacy Mode" section of the Reference Guide page and the relevant tracking issues. The date of review is November 14, 2026, for the Kotlin and AWS CLI v2 rows, and November 13, 2026, for the other rows.

SDK or toolLegacy on the Reference Guide pageHow the tracking issue describes legacyDate of review
Java 2.xAvailable inReverts to the previous default. When configured to legacy through environment variables, system properties, or config files, DynamoDB's 9 attempts and 25 ms also come back. Configuring legacy in code on a DynamoDB client applies the general legacy values.2026-11-13
PythonAvailable inReverts to the previous default. The backoff timing and retry quota costs of a previously set standard or adaptive mode do not come back.2026-11-13
.NETNot available inDoes not support legacy mode. Configuring a profile in the config file with legacy will discard the entire profile, including credentials and Region. AWS_RETRY_MODE=legacy is ignored, and standard mode is used instead.2026-11-13
PowerShellDocumentation does not listDoes not support legacy mode. Writing legacy in the shared config file makes it discard that profile, and cmdlets fail with a credentials or Region error.2026-11-13
JavaScript 3.xNot available inDoes not support legacy mode. A full revert is not available. Describes how to stay on earlier versions temporarily.2026-11-13
PHPAvailable inReverts to the previous default. However, in legacy mode, the total attempts for DynamoDB Streams are 11 instead of 12.2026-11-13
KotlinNot available inWhile opted in, treats legacy the same as standard. Individual values can be overridden in code.2026-11-14
RustNot available inDoes not support legacy mode. Setting legacy will cause aws_config::defaults(...).load() to panic. Setting it to BehaviorVersion::v2026_01_12() restores the previous values, except that an HTTP 429 with an unmodeled error code is still retried.2026-11-13
SwiftNot available inLegacy and standard behave the same, so legacy does not restore the previous behavior. Describes passing retryStrategyOptions created with useNewRetries2026: false.2026-11-13
RubyAvailable inReverts to the previous default.2026-11-13
Go 2.xNot available inDoes not have a legacy retry mode. Setting legacy will cause the configuration loading to fail with unknown RetryMode, legacy.2026-11-13
C++Available inReverts to the previous DefaultRetryStrategy. In legacy mode, AWS_MAX_ATTEMPTS and max_attempts are ignored.2026-11-13
AWS CLI v2Available inThe main text of the tracking issue and a comment from November 11, 2026, state that it does not accept legacy and that all commands calling AWS services will fail. Sources disagree.2026-11-14

Table 4 provides the following clarifications:

  • The Reference Guide page does not list PowerShell in either the "Available in" or "Not available in" sections (Documentation does not list).
  • There is a discrepancy between the Reference Guide page and the tracking issue regarding AWS CLI v2 (Sources disagree, Section 9.1). The May post also included the AWS CLI among the SDKs that support legacy.
  • The Ruby tracking issue states that even when defaults_mode is set to legacy, it will not select the legacy retry mode; instead, it requires setting retry_mode directly.

6.3 The Risk of a Shared Config File

The November post gives the following warning about a legacy setting:

Important: Some SDKs and tools don't accept legacy. Depending on the SDK or tool, a legacy setting causes an error when the configuration loads, or causes the entire config profile to be ignored, including credentials and Region.

The same warning states that if multiple SDKs or tools share environment variables or config files, the retry mode should be configured either within the code or within a profile used exclusively by that application.

Referring to Table 4, if ~/.aws/config contains [default] with retry_mode = legacy, Python applications will revert to the previous default behavior. According to the tracking issue, AWS CLI v2 commands reading the same profile will fail. .NET applications will lose their credentials and Region settings within that profile. Go 2.x applications will fail to load their configuration.

6.4 Overriding Individual Values

The second way in the November post is to set previous values one by one. The November post gives the following example:

export AWS_MAX_ATTEMPTS=5

The November post notes that which values you can override, and how, varies by SDK. The tracking issues state the following:

  • Python: The retry mode and max attempts values can be overridden. Backoff timing and retry quota costs cannot be configured.
  • JavaScript 3.x: The max attempts value and the base delay for non-throttling errors can be overridden.
  • Go 2.x: Max attempts, the base delay, and the split of delays by error type can be overridden. Retry quota costs can be overridden only in part.
  • Kotlin: The max attempts, base delay, scale factor, retry quota costs, and the long-polling backoff can be overridden. The base delay for throttling errors does not change with the opt-in and can be changed with throttlingBaseDelay.

The AWS_MAX_ATTEMPTS setting and the max_attempts value in the config file apply a single value to all clients. The Python tracking issue indicates that if you want to revert only the DynamoDB client to a previous value of 10, you should set the total_max_attempts value specifically for the DynamoDB client.

6.5 What Legacy Does Not Restore

Even in SDKs that accept legacy, some things do not come back. The Python tracking issue states:

Setting the retry mode to legacy restores the previous default only. If you explicitly set standard or adaptive mode before, you can't restore that mode's previous backoff timing (1 s base delay) or retry quota costs (5 tokens, or 10 for connection and read timeouts).

In other words, an application that previously set standard explicitly does not get the previous standard back even if it sets legacy. Legacy represents a previous default mode, not a previous standard. Similarly, the tracking issue for Java 2.x states that the 5-token cost of a previously set standard or adaptive mode cannot be restored.

The following also do not come back:

  • Rust: Even with BehaviorVersion::v2026_01_12(), an HTTP 429 with an unmodeled error code is still retried as a throttling error.
  • PHP: Even with legacy, the total attempts for DynamoDB Streams are 11, not the previous 12.
  • Swift: Legacy does not restore the previous behavior. Even with useNewRetries2026: false, the long-polling backoff, the retry of an unmodeled HTTP 429, and the handling of x-amz-retry-after stay on the new behavior.

7. What Is Not Retried

This chapter covers errors that are not retried and how HTTP 501 is handled.

7.1 HTTP 501 Is Not in the Transient Error List

The transient error list on the Reference Guide page lists HTTP 500, 502, 503, and 504 without a recognized error code. HTTP 501 is not included in this list. Similarly, 501 is not found in the list of throttling errors.

This article, referencing material from Section 1.3, found no statement on whether HTTP 501 is retried or not. The sources searched were the Reference Guide page, the November post, the May post, 13 tracking issues, and the botocore CHANGELOG.

As an inference by this article, an SDK that follows the classification on the Reference Guide page is not expected to retry a 501 without an error code. This is an inference and not a statement in any source. Section 8.5 presents observations from botocore. This article does not discuss how other SDKs handle HTTP 501.

The Python tracking issue states the following difference from legacy mode:

Compared with legacy mode, standard mode doesn't retry S3 BadDigest errors or HTTP 509 responses other than BandwidthLimitExceeded.

7.2 A 501 from a Local Emulator

Local emulators may return a 501 error for operations they do not implement. This site's What AWS Emulator Promises covers the 501 that AWS Emulator returns for operations it does not implement. Whether the SDK retries that 501 should be read within the inference in Section 7.1 and the observation in Section 8.5.

8. Observations on a Local Mac

This chapter details the results of running botocore on a local Mac, using a local HTTP stub, as of November 13, 2026 (Japan Standard Time). All of it is observation, not a promise in the sources. Because it is a single observation, this article does not claim that the results are always the same. Delays vary with jitter, so they are given as distributions and counts.

8.1 Setup

The setup is as follows:

  • The stub is an HTTP server written using only Python's standard library, and it only listens on 127.0.0.1. It returns responses such as 503, 501, throttling errors, 429 with an error code that no operation models, and connection resets, mimicking responses from STS, DynamoDB, DynamoDB Streams, and SQS. The stub also records the time when a request is received. Delays are measured as the interval between requests received by the stub.
  • The runs compared two versions of botocore across five combinations of version and environment variables. A used version 1.43.127 with no environment variables. B used version 1.43.127 with the environment variable AWS_NEW_RETRIES_2026 set to true. C used version 1.44.2 with no environment variables. D used version 1.44.2 with the environment variable AWS_NEW_RETRIES_2026 set to false. E used version 1.44.2 with the environment variable AWS_RETRY_MODE set to legacy. For A and C, the runs also covered the case where code sets standard explicitly.
  • Credentials used were dummy keys from examples in AWS documentation. The runs did not read ~/.aws/config and did not use any AWS account. Any request to an address other than 127.0.0.1 was stopped before it was sent.
  • The distribution of delays comes from 200 calls whose stub response failed once and then succeeded. Since successful retries return tokens, this measurement method does not decrement the retry quota.
  • For AWS CLI v2, the version installed on the Mac ran commands with legacy set against the stub. The installed version was 2.39.3, earlier than the Default in version 2.40.0.
  • Python was version 3.14.10, and botocore was installed with its version pinned by uv.
  • The measured intervals include a few milliseconds for the stub to process each request. Therefore, a measured delay can exceed the upper bound of the formula by a few milliseconds.

8.2 Default Mode and Number of Attempts

Table 5 lists the number of requests that reached the stub for one call. The stub kept returning 503, a connection reset, or a throttling error. The retry mode column gives the value that botocore resolved from the configuration. The observation date was November 13, 2026.

Configurationbotocore and SettingsRetry ModeSTS 503DynamoDB 503DynamoDB Streams 503STS Connection ResetSTS Throttling
A1.43.127, no variableslegacy510555
A, explicitly set to standard1.43.127, standard set in codestandard33333
B1.43.127, AWS_NEW_RETRIES_2026=truestandard34433
C1.44.2, no variablesstandard34433
C, explicitly set to standard1.44.2, standard set in codestandard34433
D1.44.2, AWS_NEW_RETRIES_2026=falsestandard34433
E1.44.2, AWS_RETRY_MODE=legacylegacy510555

Based on Table 5, the following observations were made.

  • The difference between A and C matches the Python row of Table 2 and the After column of the Python tracking issue.
  • D was the same as C. In 1.44.2, setting AWS_NEW_RETRIES_2026=false made no difference.
  • B was also the same as C. In 1.43.127 too, setting AWS_NEW_RETRIES_2026=true gave the new numbers of attempts.
  • With standard set explicitly, both DynamoDB and DynamoDB Streams were 3 in version 1.43.127 and 4 in version 1.44.2. The Python tracking issue states that with standard set explicitly, these two increase from 3 to 4.
  • E was the same as A. In 1.44.2, setting AWS_RETRY_MODE=legacy brought back the previous default numbers of attempts.

The two ways of counting in Section 5.2 were also checked against a stub that kept returning 503. Across all five configurations, setting max_attempts in Config to 2 sent 3 requests, setting total_max_attempts to 2 sent 2 requests, and setting AWS_MAX_ATTEMPTS=2 sent 2 requests.

8.3 Distribution of the First Delay

Table 6 lists the intervals between the initial request and the first retry. Each row represents the distribution over 200 calls, and the units are milliseconds. The stub returned a success after one failure.

ConfigurationAverage STS 503STS 503 (p10 to p90 and maximum)Average STS ThrottlingSTS Throttling (p10 to p90 and maximum)Average DynamoDB 503DynamoDB 503 (minimum to maximum)
A489.4109.7 to 896.4, 983.4543.8105.0 to 904.8, 1,006.255.651.9 to 65.1
A, explicitly set to standard466.388.9 to 885.1, 1,005.3517.8122.4 to 894.8, 1,000.0Not measuredNot measured
B27.66.4 to 50.0, 65.2499.897.3 to 911.8, 999.816.20.9 to 32.3
C29.99.1 to 49.5, 57.2490.3105.6 to 909.0, 1,001.916.81.5 to 32.7
C, explicitly set to standard28.47.6 to 50.0, 56.6487.190.8 to 883.6, 1,000.7Not measuredNot measured
D31.410.8 to 51.2, 57.9505.3106.2 to 902.6, 1,003.816.51.9 to 38.9
E491.776.2 to 911.0, 1,001.7518.477.4 to 924.1, 1,006.956.151.5 to 58.3

Based on Table 6, the following observations were made.

  • In configurations C and D, the first delay following a 503 averaged approximately 30 ms, while after throttling, it averaged around 500 ms. This is close to the averages in the examples on the Reference Guide page in Section 4.2 (approximately 25 ms and approximately 500 ms).
  • With the previous standard, that is, A with standard set explicitly, the first delay following a 503 also averaged 466.3 ms. The range of delays did not differ between a 503 and throttling.
  • In configurations A and E, the DynamoDB 503 delays fell within a narrow range of 51.5 ms to 65.1 ms across all 200 calls. As an inference by this article, this observation means that the first delay of the previous legacy for DynamoDB has no jitter.
  • For DynamoDB in configurations C and D, the average delay after a 503 was in the 16 ms range, with a maximum of 38.9 ms. This range corresponds to the base delay of 25 ms plus the processing time of the stub.

The runs also checked the x-amz-retry-after header. The stub added this header with a value of 2000 to the 503 responses. In 10 calls, the first delays for B, C, and D ranged from 2,002.7 ms to 2,008.3 ms. For A and E, the delays ranged from 61.1 ms to 944.5 ms, which did not match the value in the header.

8.4 Retry Quota and Long Polling

To count the retry quota, a single client called STS 60 times while the stub kept returning 503.

  • In configurations B, C, and D, calls 1 through 17 each sent 3 requests, call 18 sent 2, and from call 19 on each call sent only 1. A total of 35 retries were sent. This matches the approximately 35 retries in Section 4.3, 500 divided by 14.
  • In configuration A with standard set explicitly, calls 1 through 50 each sent 3 requests, and from call 51 on each call sent 1. A total of 100 retries were sent. This matches 500 divided by the 5 tokens of the previous standard.
  • Because the legacy delays are long, configurations A and E made only 6 calls. All 6 calls sent 5 requests each, and the retries did not stop. These 6 calls do not show that legacy retries never stop.

Long polling was checked in configurations B, C, and D. With clients for SQS ReceiveMessage and STS GetCallerIdentity, the runs called each until three calls in a row sent only one request, which depleted the retry quota. Both clients reached that point on the 21st call. The durations of the next 30 calls were as follows:

  • SQS ReceiveMessage: Average 28.9 ms to 31.4 ms, minimum 3.5 ms, maximum 54.2 ms.
  • STS GetCallerIdentity: Average 0.7 ms to 1.0 ms, maximum 1.6 ms.

This article reads this difference as consistent with the statement in Section 4.5 that long-polling operations wait before returning an error.

8.5 501 and an Unmodeled 429

When the stub kept returning a 501 with no body, STS and DynamoDB sent only one request in all five configurations and in both cases with standard set explicitly. botocore returned the error with the error code 501 and a retry count of 0. This observation matches the inference in Section 7.1. However, the observation covers only botocore versions 1.43.127 and 1.44.2. It shows nothing about other SDKs or about a 501 from an actual AWS service.

When the stub kept returning a 429 with the error code DemoUnmodeledError, which no operation models, the numbers of requests were as follows:

  • C and D: 3 times
  • B: 1 time
  • A with standard set explicitly: 1 time
  • A and E: 5 times

The difference between B and C matches the comment of November 11, 2026, on the Python tracking issue. This comment states that, for those who had set the opt-in, version 1.44.0 adds the retry of an unmodeled 429. That legacy, in A and E, retried the 429 is an observation that this article has not checked against the statements in the sources it read.

8.6 AWS CLI v2 and Legacy

The AWS CLI v2 on the Mac was 2.39.3. The runs sent aws sts get-caller-identity to the stub and compared the results in the following four cases:

  • Without any retry settings: Successful. One request reached the stub.
  • AWS_RETRY_MODE=legacy: Failed with exit code 255. No requests reached the stub.
  • With retry_mode = legacy in the profile in the config file: Also failed with exit code 255. No requests reached the stub.
  • aws --version with AWS_RETRY_MODE=legacy: Successful. This command does not call any AWS services.

In the two cases where legacy was set, AWS CLI v2 produced the following error:

aws: [ERROR]: Invalid value provided to "mode": "legacy" must be one of: "standard" or "adaptive"

This observation matches the comment of November 11, 2026, on the AWS CLI v2 tracking issue. The version observed, 2.39.3, is earlier than the Default in version 2.40.0. As an inference by this article, AWS CLI v2 may not have accepted legacy since before the switch of the default in 2.40.0. The comment's "AWS CLI v2 already uses standard mode by default" also matches this inference. This article did not check other versions of AWS CLI v2.

8.7 What This Setup Does Not Show

These observations do not show:

  • The actual responses from AWS services. The stub responses only mimic the format of those responses.
  • The behavior of SDKs other than botocore. The descriptions for Java, Kotlin, .NET, and others were based solely on documentation.
  • Retry quota behavior between multiple processes or hosts. The retry quota is managed on a per-client instance basis.
  • The client-side rate limiter of adaptive mode.

9. Where the Sources Disagree, and Where No Statement Was Found

This chapter summarizes discrepancies found in the source materials and instances where information was not found.

9.1 Where the Sources Disagree

This article found six points where the sources disagree. This article does not decide which source is wrong. The two points that this article listed on November 13, 2026, the default version of Java 2.x and the versions of Kotlin, no longer disagree on November 14, 2026, because the table in the November post and the Kotlin tracking issue were updated (Sections 3.2 and 3.3).

The first is AWS CLI v2 and legacy. The Reference Guide page includes the CLI in the list where legacy is available. The May post included the AWS CLI both among the SDKs whose previous default was legacy and among the SDKs that support legacy. The AWS CLI v2 tracking issue, in its main text and in a comment dated November 11, 2026, states that AWS CLI v2 already used standard by default and does not accept legacy (Sections 3.4, 6.2).

The second is the list of SDKs whose previous default was legacy. The May post lists Java, Python, Ruby, PHP, C++, and AWS CLI. The November post lists Python, Java, Ruby, PHP, and Swift. The tracking issues state that Java 2.x transitioned from legacy to standard, and that C++ transitioned from DefaultRetryStrategy to standard.

The third is whether opting in is required. The November post states that, starting on November 10, 2026, the new behavior is the default. The top of the Reference Guide page still states the following on the date of review:

The behavior described on this page requires opting in until it becomes the default behavior. Set AWS_NEW_RETRIES_2026=true in your environment.

The settings table on the same Reference Guide page specifies a default mode of standard and a total number of attempts of 3. The Support table lists five entries for Swift, Ruby, Go, C++, and AWS CLI v2, each stating "See tracking issue." As an inference by this article, the top of the Reference Guide page may still carry the sentence from before the default switched.

The fourth is the previous maximum of total attempts for DynamoDB. The May post states:

Previous defaults varied by SDK (up to 10 max attempts in some SDKs).

The November post states:

Previous defaults varied by SDK (as many as 12 max attempts in some SDKs).

The tracking issues list DynamoDB Streams for PHP as 12, DynamoDB for .NET, PowerShell, PHP, Ruby, and C++ as 11, and DynamoDB for Python as 10 (Section 4.4, Table 2).

The fifth is DynamoDB Streams for Java 2.x. The Reference Guide page states that DynamoDB's default settings also apply to DynamoDB Streams. The tracking issue for Java 2.x states that the Java 2.x DynamoDB Streams clients use the general defaults (Section 4.4).

The sixth is whether the previous standard and legacy base delays were differentiated by error type. The May post states that previously, each SDK used the same base delay regardless of the error type. The tracking issues for Java 2.x and JavaScript 3.x state that the previous base delay was 100 ms for transient errors and 500 ms for throttling errors (Section 2.3).

This article does not call the following two a disagreement:

  • Changes to legacy: The May post stated that nothing changes for an explicit legacy setting. The November post states that what changes with legacy varies by SDK. The two describe the state before and after the default switched.
  • Legacy for Swift: The Reference Guide page states that legacy cannot be used with Swift. The tracking issue for Swift states that legacy and standard have the same behavior, and that legacy does not restore the previous behavior. The two agree that legacy in Swift does not bring the previous behavior back.

9.2 What the Documentation Does Not List, and Where No Statement Was Found

For the following three items, this article found no statement in the sources on the date of review, or confirmed that a list in the sources does not include them. None of them shows that the matter does not exist or cannot be done.

  • Retrying HTTP 501: No mention of HTTP 501 was found in the documentation referenced in Section 1.3 (No statement found, Section 7.1).
  • PowerShell legacy: The Reference Guide page's Available in and Not available in lists do not include PowerShell (Documentation does not list). The PowerShell tracking issue states that it does not support legacy.
  • Update schedule for the Reference Guide page: This article did not find any statement indicating when the page is scheduled to be updated (No statement found).

10. Failure Modes

This chapter lists failures that can occur after you upgrade, as symptom, cause, and source.

  • Symptoms: After the update, calls that previously succeeded are now returning errors. Cause: The total number of attempts has been reduced. For Python, it went from 5 to 3. For Java 2.x, it went from 4 to 3. For DynamoDB, SDKs that previously used 9 to 12 attempts now use 4. Reference: November post, Table 2.
  • Symptoms: During extended outages, errors are now returning faster than before. Cause: SDKs that previously lacked a retry quota now have one implemented. Reference: November post, Python tracking issue (Section 4.3).
  • Symptoms: Despite explicitly specifying the standard setting, the behavior and error patterns have changed after the update. Cause: The behavior of the updated standard setting itself has changed. Reference: November post (Section 2.3).
  • Symptoms: Even with AWS_NEW_RETRIES_2026=false set, the application is exhibiting the new behavior. Cause: From the Default in version on, the SDK no longer reads this variable. Reference: November post (Section 2.2).
  • Symptoms: Every AWS CLI v2 command that calls an AWS service fails. Cause: Either AWS_RETRY_MODE=legacy is set, or the profile includes retry_mode = legacy. Reference: AWS CLI v2 tracking issue (Section 3.4).
  • Symptoms: .NET applications are failing with errors indicating that credentials or the Region cannot be found. Cause: The shared config file's profile includes retry_mode = legacy. .NET discards the entire profile. Reference: .NET tracking issue, November post (Section 6.3).
  • Symptoms: Go 2.x applications are failing with unknown RetryMode, legacy while loading the configuration. Cause: The application is configured to use legacy mode. Reference: Go 2.x tracking issue (Section 6.2).
  • Symptoms: Rust applications are panicking at startup. Cause: The application is configured to use legacy mode. Reference: Rust tracking issue (Section 6.2).
  • Symptoms: After reverting to legacy mode, the application does not get back the backoff timing of the standard mode it had set before. Cause: Legacy mode uses the previous default behavior, which was not the previous standard. Reference: the Python and Java 2.x tracking issues (Section 6.5).
  • Symptoms: When attempting to set the total number of attempts to 5 in Python, the application is sending 6 attempts. Cause: In Config, max_attempts refers to the number of retry attempts. Reference: botocore Config reference (Section 5.2).
  • Symptoms: After upgrading Go 2.x to v1.48.0, DynamoDB is still using the previous default settings. Cause: The service module is outdated. Reference: Go 2.x tracking issue (Section 3.5).
  • Symptoms: Calls to endpoints returning a 501 error are failing after only one attempt. Cause: 501 is not listed as a transient error. Reference: Reference Guide page. That it is not retried is an inference by this article (Section 7.1).

11. Frequently Asked Questions About the New Default Retry Behavior in AWS SDKs

Q1. Did the default setting change in all SDKs on November 10, 2026?

No. The November post states that, with the exception of Kotlin, SDKs and tools made the new behavior the default from the versions in the table. Java 2.x changed to the new default with version 2.58.0 on November 11, 2026, and Kotlin had not made it the default on the date of review. In every SDK, the default does not change until you upgrade to its Default in version (Chapter 3).

Q2. If I set standard explicitly, does nothing change?

Something does change. The November post states that this update changes how standard and adaptive behave. Even with standard set explicitly, the new base delays, retry quota costs, and DynamoDB defaults apply (see Sections 2.3 and 5.1).

Q3. Will setting AWS_NEW_RETRIES_2026 to false revert to the previous behavior?

From the Default in version on, it does not. The November post states that these versions do not read this variable. In versions before the Default in version, the previous behavior stays as long as you do not set the variable (see Section 2.2).

Q4. Does setting AWS_RETRY_MODE=legacy revert every SDK to its previous behavior?

No. Some SDKs and tools do not accept this setting. According to the tracking issue, every AWS CLI v2 command that calls an AWS service fails. .NET and PowerShell discard the entire profile that contains the legacy setting. Go 2.x will fail to load the configuration, and Rust will panic. Even in SDKs that can revert to legacy mode, the values of a previously set standard are not restored (see Sections 6.2 and 6.5).

Q5. How many attempts does the new default make?

The default total number of attempts, as specified in the Reference Guide page, is 3, consisting of the initial request and up to two retries. For DynamoDB and DynamoDB Streams clients, this number is 4. However, the Java 2.x tracking issue states that Java 2.x's DynamoDB Streams uses the general default (Section 4.4).

Q6. How long does the SDK wait before the first retry?

According to the formula in the Reference Guide page, after transient errors such as 503, the delay is between 0 and 50 ms, with an average of about 25 ms. After throttling errors, the delay is between 0 and 1,000 ms, with an average of about 500 ms. The base delay for transient errors in DynamoDB is 25 ms (see Sections 4.2 and 4.4).

Q7. What happens when the retry quota is depleted?

The SDK returns the error without a retry. The retry quota does not stop the initial request. For the four long-polling operations, it waits before returning the error. If a retry succeeds, the tokens it used are returned (see Sections 4.3 and 4.5).

Q8. Will HTTP 501 errors be retried?

This article found no statement about 501 in the sources. The list of transient errors in the Reference Guide page includes 500, 502, 503, and 504, but not 501. As an inference by this article, an SDK that follows this classification is not expected to retry a 501 without an error code (see Sections 7.1 and 8.5).

Q9. How do I set Python back to the previous 5 attempts?

Set the total number of attempts to 5. To do this, set AWS_MAX_ATTEMPTS=5, set max_attempts = 5 in the config file, or set total_max_attempts to 5 in Config. Note that the max_attempts setting within Config refers to the number of retry attempts, so it should be set to 4 (see Section 5.2).

Q10. When multiple SDKs and the AWS CLI all read the same ~/.aws/config file, where should the legacy setting go?

Do not put it in a shared profile. The November post says to configure the retry mode either within the application's code or within a profile used exclusively by that application. Placing legacy settings in the shared [default] profile can lead to failures with AWS CLI v2, .NET, and Go 2.x (see Section 6.3).

12. Summary

Read the switch on November 10, 2026 through the following five points:

  • Version: The default changes from each SDK's Default in version. For Python, it is botocore 1.44.0; for Java 2.x, it is 2.58.0. Kotlin had not made it the default on the date of review. Versions where it became the default do not read AWS_NEW_RETRIES_2026.
  • Behavior: The change is not limited to the default mode. The updated standard uses a base delay of 50 ms for transient errors and 1,000 ms for throttling errors, and uses 14 tokens for transient retries. For DynamoDB, it uses 25 ms and 4 attempts.
  • Configuration: Even with standard set explicitly, the new values apply. If you set max attempts explicitly, only that value stays. Check whether max attempts refers to the total number of attempts or the number of retry attempts.
  • Rollback: Some SDKs cannot be rolled back completely. According to the tracking issues, AWS CLI v2, .NET, PowerShell, Go 2.x, Rust, Kotlin, Swift, and JavaScript 3.x cannot use or do not accept legacy. Using legacy settings in a shared config file could cause failures in other SDKs or tools.
  • State of the sources: The sources disagree on six points, including the use of legacy settings for AWS CLI v2 and opt-in notes. Tables 1 through 4 reflect the status as of November 13, 2026, and rows with a date of review of 2026-11-14 reflect the status as of November 14, 2026.

13. References



References:
Tech Blog with curated related content

Written by Hidekazu Konishi