Skip to content

feat: add resilience layer for Authlete API calls (rate limit best practices)#87

Draft
meysam wants to merge 1 commit into
masterfrom
feat/authlete-rate-limit-resilience
Draft

feat: add resilience layer for Authlete API calls (rate limit best practices)#87
meysam wants to merge 1 commit into
masterfrom
feat/authlete-rate-limit-resilience

Conversation

@meysam

@meysam meysam commented Jun 11, 2026

Copy link
Copy Markdown

Implements caching, conditional retry with exponential backoff and jitter, and per-endpoint circuit breakers with stale-cache fallback, as described in the Rate Limit Best Practices guide.

All endpoints obtain the AuthleteApi client through a dynamic proxy wrapper; behavior is tunable via resilience.properties and can be disabled entirely with resilience.enabled=false.

…actices)

Implements caching, conditional retry with exponential backoff and jitter, and per-endpoint circuit breakers with stale-cache fallback, as described in the Rate Limit Best Practices guide.

All endpoints obtain the AuthleteApi client through a dynamic proxy wrapper; behavior is tunable via resilience.properties and can be disabled entirely with resilience.enabled=false.
@meysam meysam marked this pull request as draft June 11, 2026 13:49
{
// Common spellings of the rate-limit reset header, matched case-insensitively.
private static final String[] RESET_HEADERS = {
"RateLimit-Reset", "Ratelimit-Reset", "X-RateLimit-Reset", "Retry-After"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The findHeader method is performing a case insensitive comparison so I don't think we need to have two entries with different casing

Suggested change
"RateLimit-Reset", "Ratelimit-Reset", "X-RateLimit-Reset", "Retry-After"
"RateLimit-Reset", "X-RateLimit-Reset", "Retry-After"

Comment on lines +181 to +193
detail.append(req.getToken());
detail.append('|').append(join(req.getScopes()));
detail.append('|').append(req.getSubject());
detail.append('|').append(req.getClientCertificate());
detail.append('|').append(req.getHtm());
detail.append('|').append(req.getHtu());
detail.append('|').append(join(req.getResources()));
detail.append('|').append(req.getUri());
detail.append('|').append(req.getTargetUri());
detail.append('|').append(join(req.getAcrValues()));
detail.append('|').append(req.getMaxAge());
detail.append('|').append(req.isRequestBodyContained());
detail.append('|').append(req.isDpopNonceRequired());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Since we are excluding DPoP and HTTP message signature requests from caching we probably should not use the parameters intended for these requests such as: htu, htm, targetUri, isDpopNonceRequred and isRequestBodyContained

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