Skip to content

DynamoDbResolveEndpointInterceptor re-evaluates endpoint rules engine on every request even when endpointOverride is static #6847

@batrived

Description

@batrived

Summary

When DynamoDbClientBuilder.endpointOverride(uri) is configured, the resolved endpoint is static for the lifetime of the client. However, DynamoDbResolveEndpointInterceptor.modifyRequest() still calls DefaultDynamoDbEndpointProvider.resolveEndpoint() on every single request, which re-evaluates the full endpoint rules engine and re-parses the URI from scratch each time.

Evidence

Using async-profiler on a JanusGraph server with a DynamoDB-heavy read workload (Query-dominated, ~thousands of DynamoDB calls/sec, SDK version 2.42.28):

  • DynamoDbResolveEndpointInterceptor.modifyRequest: 1.97% cumulative CPU of total JVM CPU
  • java/net/URI$Parser.scan: 0.36% flat CPU — URI re-parsed on every request
  • DefaultDynamoDbEndpointProvider.resolveEndpoint() runs the full rules engine even when the endpoint was statically configured

This is a subset of the broader AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext overhead (6.44% total).

Workaround

Bypassing endpointOverride in favor of a custom endpointProvider lambda that returns a pre-built static Endpoint eliminates this per-request cost entirely:

URI resolvedEndpoint = URI.create("https://dynamodb.us-east-1.amazonaws.com");
Endpoint staticEndpoint = Endpoint.builder().url(resolvedEndpoint).build();

DynamoDbClient.builder()
    .endpointProvider(params -> CompletableFuture.completedFuture(staticEndpoint))
    // ... rest of config
    .build();

This saves ~0.5% CPU on our workload. The workaround is not obvious and shouldn't be required — endpointOverride is a documented, common configuration pattern.

Proposed fix

When endpointOverride is set at client construction time, the DynamoDbResolveEndpointInterceptor (or the underlying DefaultDynamoDbEndpointProvider) should cache the resolved Endpoint after the first evaluation and return the cached result on subsequent requests. Since the endpoint override URI is immutable after construction, this is safe.

Alternatively, the interceptor could detect at construction time that endpointOverride is present and substitute a no-op/cached implementation.

Relationship to PR #6820

PR #6820 ("Move endpoint resolution from interceptors to pipeline stage") addresses this architecturally. This issue is filed to track the specific user-visible problem — static endpointOverride causing per-request endpoint rules evaluation — in case the PR takes time to land or a targeted fix is preferred.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions