Preview the November 2026 AWS SDK for Java retry-behavior changes in your own app — before AWS flips the default in production.
In November 2026, AWS is changing the default retry behavior across every AWS SDK — Java, Python, JS, Go, PHP, and the CLI (announcement). If you do nothing, your services will start behaving differently in production:
| Setting | Legacy default | 2026 default |
|---|---|---|
| Max attempts | 4 | 3 |
| Base delay | 100 ms | 50 ms |
| Throttling delay | 500 ms | 1000 ms |
| DynamoDB attempts | 9 | 4 |
| Retryable errors | — | + LimitExceededException, IdpCommunicationErrorException |
Most teams can't answer the only question that matters: "what would this mean for my app?" They can't opt in blindly and they can't wait until November to find out.
It attaches a single ExecutionInterceptor to any AWS SDK v2 client, records every attempt in a bounded ring buffer, and answers three questions your logs can't:
- What is my SDK actually doing right now? — per-operation attempts, retries, throttles, failures, p50/p95 wall-clock.
- What would the November 2026 defaults do to that traffic? — a pure-function simulator replays each recorded call under the new rules and reports the diff.
- How does my code react when the SDK decides to stop retrying? — a deterministic
FailureInjectorthrows service exceptions the SDK's own retry loop treats as real.
No re-issuing of requests. No AWS calls. No credentials required to try it.
Before — you push to prod on Nov 1st and hope:
DynamoDbClient ddb = DynamoDbClient.create();
// … your app …After — one line, and you know:
RetryLens lens = RetryLens.create();
DynamoDbClient ddb = DynamoDbClient.builder()
.overrideConfiguration(o -> o.addExecutionInterceptor(lens.interceptor()))
.build();
// … exercise your app on real traffic for a while …
RetryReport now = lens.report();
RetryReport in2026 = now.previewFor(RetryMode.STANDARD_2026);
System.out.println(now.diff(in2026).totalFailuresDelta() + " extra failures under 2026 defaults");
System.out.println(in2026.toText());Sample output:
retrylens report — generated 2026-08-22T18:04:11.923Z
calls=1428 attempts=1837 retries=409 throttled=118 failures=6
operation calls attempts retries throttled failures p50 p95
----------------------------------------------------------------------------------------------------------------
DynamoDb.PutItem 310 498 188 12 2 31ms 410ms
top errors: ProvisionedThroughputExceededException=12, InternalServerError=3
S3.GetObject 812 912 100 0 0 8ms 41ms
Sqs.ReceiveMessage 201 253 52 83 3 21ms 2.10s
top errors: RequestThrottled=83
Maven:
<dependency>
<groupId>io.github.bibekmhj</groupId>
<artifactId>retrylens</artifactId>
<version>0.1.0</version>
</dependency>Gradle:
implementation("io.github.bibekmhj:retrylens:0.1.0")retrylens has zero required runtime dependencies — the AWS SDK is declared provided, so you keep whichever version you already use (2.20+ recommended, and the simulator is calibrated for the values in SDK 2.44's AWS_NEW_RETRIES_2026 announcement).
import io.github.bibekmhj.retrylens.RetryLens;
import io.github.bibekmhj.retrylens.RetryMode;
import software.amazon.awssdk.services.s3.S3Client;
RetryLens lens = RetryLens.create();
S3Client s3 = S3Client.builder()
.overrideConfiguration(o -> o.addExecutionInterceptor(lens.interceptor()))
.build();
// … app runs …
System.out.println(lens.report().toText());
System.out.println(lens.report().previewFor(RetryMode.STANDARD_2026).toText());- 2026 preview simulator — pure function, replays observed traces under the new defaults. No live retries, no AWS calls.
- Per-operation report — attempts, retries, throttles, failures, p50/p95, top error codes.
- Ring-buffered trace store — bounded memory footprint, configurable capacity.
- Failure injector — deterministic
ExecutionInterceptorthat throws realAwsServiceExceptions frombeforeTransmission. Lets you test how your app reacts to throttling or transient errors without provoking AWS. - Micrometer bridge (optional) — turn every trace into
retrylens.apicall/retrylens.attempts/retrylens.retries/retrylens.throttled/retrylens.failuresmeters. Fills the gap of aws-sdk-java-v2#4611. - JSON output — hand
report.toJson()to dashboards or CI assertions with no extra dependency.
RetryReport.previewFor(RetryMode.STANDARD_2026) returns a new immutable report that answers, per call:
given the same per-attempt outcomes we recorded, would the November 2026 defaults have retried this? For how long? Would it have finally succeeded, or would the smaller attempt budget have exhausted the retries?
The simulator applies AWS's documented rules — smaller attempt caps, revised backoff timing, added retryable exceptions, DynamoDB's 9-→-4 attempt drop — and never re-issues a request. Safe to run against production traffic. See docs/2026-RETRY-CHANGES.md.
| Component | Supported |
|---|---|
| Java | 17, 21, 22, 23 |
| AWS SDK for Java v2 | 2.20 and newer (retry values calibrated for 2.44+) |
| Spring Boot | 3.x (bring your own configuration; example provided) |
| Micrometer | 1.10+ (optional) |
AWS SDK for Java v1 reached end-of-support on Dec 31 2025 and is out of scope.
The FailureInjector interceptor throws real AwsServiceExceptions from beforeTransmission — the SDK's retry engine treats them exactly like service errors:
FailureInjector injector = FailureInjector.builder()
.rule(FailureInjector.rule()
.whenService("DynamoDb").whenOperation("PutItem")
.times(2)
.throwThrottling("ProvisionedThroughputExceededException"))
.build();
DynamoDbClient ddb = DynamoDbClient.builder()
.overrideConfiguration(o -> o
.addExecutionInterceptor(lens.interceptor())
.addExecutionInterceptor(injector.interceptor()))
.build();Combine with RetryLens to see exactly what the SDK — and, via the simulator, what the 2026 defaults — would do.
See docs/ARCHITECTURE.md.
The core is one interceptor and one immutable record type. Everything else is a pure function of a list of recorded traces. That is why the preview mode is safe to run against production traffic and why the same code path produces the report, the JSON output, and the Micrometer meters.
- Spring Boot starter with autoconfiguration.
- Additional simulator modes (adaptive retry rate-limiting).
- CLI diagnostic:
java -jar retrylens.jar --scanagainst a running JMX endpoint or heap dump. - Real OpenTelemetry
ObservationAPI integration when AWS ships the SPI.
Because "test in prod on November 1st" is not a plan, and because reading AWS's changelogs is not the same as knowing what your services will do. retrylens is a very small piece of code that turns a nervous multi-quarter migration into a diff you can read in your terminal today.
If AWS SDK v2 later adopts a first-class 2026 preview mode of its own, this library will happily deprecate itself. Until then, the goal is: one dependency, one interceptor, one report, one question answered.
Apache 2.0. See LICENSE.
Bug reports, ideas, and PRs welcome. See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
- AWS announcement — Announcing updated retry behavior for AWS SDKs and Tools
- AWS SDK for Java v2 tracking issue —
aws-sdk-java-v2#6987 - AWS SDKs and Tools reference — Retry behavior
- Micrometer Observation gap —
aws-sdk-java-v2#4611