Preview the November 2026 AWS SDK for Java retry defaults on your own traffic
If you run a Java app that talks to AWS, there's a change coming on November 1, 2026 that will quietly alter how your services behave under partial failure - and unless you take deliberate action, you will not find out until your dashboards do. AWS is changing the default retry behavior in every one of its SDKs (Java, Python, JS, Go, PHP, plus the CLI) as part of a cross-SDK announcement. The values that change are small on paper and significant in production: What changes on Nov 1, 2026 Max attempts (most services) - from 4 to 3 Max attempts (DynamoDB) - from 9 to 4 โ the big one Base delay for transient errors - from 100 ms to 50 ms Base delay for throttling - from 500 ms to 1000 ms New retryable exceptions - LimitExceededException and STS IdpCommunicationErrorException The most consequential row is the second one. DynamoDB has always had a per-service override that lets the SDK retry a call up to nine times before giving up. In November it will retry four times. If your write path relies on that longer tail to survive brief throttling bursts - many do, quietly - a real number of writes that succeed today will fail on Nov 1st. You can opt in early on AWS SDK for Java 2.44+ by setting AWS_NEW_RETRIES_2026=true. But that's a binary switch, and the only way to know if it hurts is to flip it and watch. That's not a plan. The gap The only question that matters is "what would the new defaults do to my traffic?" The AWS announcement can't answer that; it doesn't know how often your DynamoDB PutItem gets throttled at 3 AM, or which of your SQS consumers has a p95 that walks right up to the timeout. Your logs can't answer it either. The SDK's retry loop is largely invisible from the outside - you see either a successful result or a final failure, not the attempts in between. What I built I published a small library called retrylens (Maven Central, GitHub) that does one thing: it attaches a single ExecutionInterceptor to any AWS SDK v2 client, records every attempt into a bounded ring buffer, and then lets you simulate what the November 2026 defaults would have done to that same traffic. The simulator is a pure function over the recorded outcomes. It never re-issues a request, never talks to AWS, and never needs credentials. It's arithmetic on data you already have - which is what makes it safe to run against a real production app. The whole API in one screen import io.github.bibekmhj.retrylens.RetryLens; import io.github.bibekmhj.retrylens.RetryMode; import io.github.bibekmhj.retrylens.RetryReport; RetryLens lens = RetryLens.create(); DynamoDbClient ddb = DynamoDbClient.builder() .overrideConfiguration(o -> o.addExecutionInterceptor(lens.interceptor())) .build(); // โฆ exercise the client on real traffic for a while โฆ RetryReport now = lens.report(); RetryReport in2026 = now.previewFor(RetryMode.STANDARD_2026); System.out.println(now.toText()); System.out.println(in2026.toText()); System.out.println(now.diff(in2026).totalFailuresDelta() + " extra failures under 2026 defaults"); That's the entire integration. There's no framework, no proxy, no wrapper - the SDK's own ExecutionInterceptor SPI is doing all the work. What comes out the other side A representative snapshot from a synthetic DynamoDB + S3 + SQS workload: retrylens report - observed (your current retry mode) 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 S3.GetObject 812 912 100 0 0 8ms 41ms Sqs.ReceiveMessage 201 253 52 83 3 21ms 2.10s top errors: RequestThrottled=83 retrylens report - projected under STANDARD_2026 calls=1428 attempts=1614 retries=186 throttled=118 failures=27 ฮ attempts: -223 (mostly DynamoDB PutItem: 9-attempt cap โ 4) ฮ failures: +21 (DynamoDB PutItem exhausts retries sooner on sustained throttling) The two numbers on the last line are the ones you can actually take to a design review. 21 extra failures per 1,428 calls is a specific claim you can act on: raise DynamoDB write capacity, or set a per-operation retry override, or accept the drop as within budget. Without a number, you're guessing. What retrylens deliberately does not do Honesty about the sharp edges: It does not model the standard-mode retry quota. In practice the SDK's standard mode uses a token bucket that can suppress retries under sustained failure; retrylens's numbers are therefore an upper bound on how much retrying the new mode would do. Real production will retry no more than what the simulator projects, sometimes less. It does not model live jitter. Backoff wall-clock is reported as the expected value of full-jitter, not a specific outcome. It does not re-issue requests. The simulator is arithmetic on recorded outcomes. If your traffic mix changes tomorrow, run it again on the new traffic. Install io.github.bibekmhj retrylens 0.1.0 Zero required runtime dependencies. AWS SDK is declared provided, so you keep whichever version you already use (2.20+ recommended, retry values calibrated for 2.44+). What to do this week Whether or not you use this specific library, do one of these: - Run your app under AWS_NEW_RETRIES_2026=true in a staging environment for a week and diff your CloudWatch failure metrics against the previous week. - Or, run retrylens against a canary of production traffic for 30 minutes and read the diff. - Or, set AWS_RETRY_MODE=legacy explicitly in your production environment right now, so that when Nov 1st arrives you have already opted out and can plan the migration on your own timeline. The one option you don't have is finding out on Nov 1st. If you try retrylens and it either helps or breaks in an interesting way, I'd love to hear about it in the GitHub issues. The library is Apache 2.0, ~600 lines of Java, and reviewable in one PR. Top comments (0)
Comments
No comments yet. Start the discussion.