CtrlK
CommunityDocumentationLog inGet started
Tessl Logo

tessl/maven-org-springframework-ai--spring-ai-autoconfigure-retry

Spring Boot auto-configuration for AI retry capabilities with exponential backoff and intelligent HTTP error handling

Overview
Eval results
Files

configuration-guide.mddocs/guides/

Configuration Guide

Comprehensive guide to configuring Spring AI Retry Auto Configuration for different use cases and environments.

Configuration Overview

All properties use the prefix spring.ai.retry and can be set in:

  • application.properties
  • application.yml
  • Environment variables
  • System properties

Core Properties

Max Attempts

Controls the total number of retry attempts (including the initial call).

spring.ai.retry.max-attempts=10

Values:

  • Default: 10
  • Range: 0 to 100 (recommended)
  • 0 = no retries (fail immediately)
  • 1 = one attempt only
  • 10 = up to 10 total attempts

Client Error Retry

Controls whether to retry 4xx client errors.

spring.ai.retry.on-client-errors=false

Values:

  • Default: false (don't retry 4xx)
  • true = retry 4xx errors
  • false = fail immediately on 4xx

When to use true:

  • Some APIs use 4xx for temporary conditions
  • 408 Request Timeout might resolve
  • 429 Too Many Requests (though better in onHttpCodes)

HTTP Code Lists

On HTTP Codes (Always Retry)

Highest precedence - these codes always trigger retry:

spring.ai.retry.on-http-codes=429,503

Common values:

  • 429 - Rate limit exceeded
  • 503 - Service unavailable
  • 502 - Bad gateway
  • 504 - Gateway timeout

Exclude HTTP Codes (Never Retry)

These codes never trigger retry:

spring.ai.retry.exclude-on-http-codes=401,403,400

Common values:

  • 401 - Unauthorized (invalid credentials)
  • 403 - Forbidden (insufficient permissions)
  • 400 - Bad request (invalid format)
  • 404 - Not found

Backoff Configuration

Initial Interval

Time to wait before first retry:

spring.ai.retry.backoff.initial-interval=2s

Formats:

  • Milliseconds: 2000ms
  • Seconds: 2s
  • Minutes: 2m
  • ISO-8601: PT2S

Recommended ranges:

  • Development: 100ms - 500ms
  • Internal services: 500ms - 2s
  • External APIs: 2s - 5s
  • Rate-limited APIs: 5s - 10s

Multiplier

Exponential growth factor for each retry:

spring.ai.retry.backoff.multiplier=5

Values:

  • 1 = fixed backoff (no growth)
  • 2 = moderate exponential growth
  • 3-5 = aggressive growth (default: 5)
  • >5 = very aggressive growth

Backoff progression examples:

With initial=2s:

  • multiplier=1: 2s, 2s, 2s, 2s, ...
  • multiplier=2: 2s, 4s, 8s, 16s, ...
  • multiplier=3: 2s, 6s, 18s, 54s, ...
  • multiplier=5: 2s, 10s, 50s, 250s, ...

Max Interval

Maximum wait time (cap on exponential growth):

spring.ai.retry.backoff.max-interval=3m

Formats: Same as initial-interval

Recommended ranges:

  • Development: 500ms - 5s
  • Testing: 5s - 30s
  • Production: 1m - 5m

Configuration Examples

Development Environment

Fast failure for rapid iteration:

# application-dev.properties
spring.ai.retry.max-attempts=2
spring.ai.retry.backoff.initial-interval=100ms
spring.ai.retry.backoff.multiplier=2
spring.ai.retry.backoff.max-interval=500ms

Result:

  • 2 total attempts
  • Backoff: 100ms, 200ms
  • Total max time: ~300ms

Testing Environment

Quick retries for tests:

# application-test.properties
spring.ai.retry.max-attempts=3
spring.ai.retry.backoff.initial-interval=50ms
spring.ai.retry.backoff.multiplier=1
spring.ai.retry.backoff.max-interval=50ms

Result:

  • 3 total attempts
  • Fixed 50ms backoff
  • Total time: ~100ms

Production Environment

Robust retry for high reliability:

# application-prod.properties
spring.ai.retry.max-attempts=10
spring.ai.retry.on-http-codes=429,503
spring.ai.retry.exclude-on-http-codes=401,403,400
spring.ai.retry.backoff.initial-interval=2s
spring.ai.retry.backoff.multiplier=5
spring.ai.retry.backoff.max-interval=3m

Result:

  • 10 total attempts
  • Exponential backoff with long max
  • Total max time: ~22 minutes

Rate-Limited API

Respect rate limits with longer backoff:

spring.ai.retry.max-attempts=10
spring.ai.retry.on-http-codes=429,503
spring.ai.retry.backoff.initial-interval=5s
spring.ai.retry.backoff.multiplier=2
spring.ai.retry.backoff.max-interval=60s

Result:

  • Explicitly retries 429 (rate limit)
  • Longer initial wait (5s)
  • Max interval matches typical rate limit window (60s)

Internal Microservices

Quick retries for internal services:

spring.ai.retry.max-attempts=5
spring.ai.retry.backoff.initial-interval=500ms
spring.ai.retry.backoff.multiplier=3
spring.ai.retry.backoff.max-interval=10s

Result:

  • Moderate attempts (5)
  • Short initial wait
  • Lower max interval

Critical Operations

Maximum resilience for critical operations:

spring.ai.retry.max-attempts=15
spring.ai.retry.backoff.initial-interval=3s
spring.ai.retry.backoff.multiplier=3
spring.ai.retry.backoff.max-interval=5m

Result:

  • Many attempts (15)
  • Long max interval (5m)
  • Total max time: ~45 minutes

YAML Configuration

Complete YAML example:

spring:
  ai:
    retry:
      # Core settings
      max-attempts: 10
      on-client-errors: false
      
      # HTTP code lists
      on-http-codes:
        - 429  # Rate limit
        - 503  # Service unavailable
        - 502  # Bad gateway
        - 504  # Gateway timeout
      
      exclude-on-http-codes:
        - 401  # Unauthorized
        - 403  # Forbidden
        - 400  # Bad request
        - 404  # Not found
        - 422  # Unprocessable entity
      
      # Backoff settings
      backoff:
        initial-interval: 2s
        multiplier: 5
        max-interval: 3m

Property Precedence

HTTP error classification follows this precedence (highest to lowest):

  1. onHttpCodes → Always retry
  2. excludeOnHttpCodes → Never retry
  3. onClientErrors setting → Retry 4xx if true
  4. Default → Retry 5xx, fail on 4xx

Example

Configuration:

spring.ai.retry.on-client-errors=false
spring.ai.retry.on-http-codes=429
spring.ai.retry.exclude-on-http-codes=400,503

Results:

  • 429: Retry (in onHttpCodes, precedence #1)
  • 400: No retry (in excludeOnHttpCodes, precedence #2)
  • 503: No retry (in excludeOnHttpCodes, precedence #2)
  • 401: No retry (4xx + onClientErrors=false, precedence #3)
  • 500: Retry (default behavior, precedence #4)

Profile-Specific Configuration

Using Spring Profiles

# application.yml
spring:
  ai:
    retry:
      max-attempts: 10  # Default for all profiles

---
# application-dev.yml
spring:
  config:
    activate:
      on-profile: dev
  ai:
    retry:
      max-attempts: 2
      backoff:
        initial-interval: 100ms

---
# application-prod.yml
spring:
  config:
    activate:
      on-profile: prod
  ai:
    retry:
      max-attempts: 15
      backoff:
        initial-interval: 5s
        max-interval: 5m

Programmatic Configuration

import org.springframework.ai.retry.autoconfigure.SpringAiRetryProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import java.time.Duration;
import java.util.Arrays;

@Configuration
public class RetryConfig {
    
    @Bean
    @Profile("dev")
    public SpringAiRetryProperties devRetryProperties() {
        SpringAiRetryProperties props = new SpringAiRetryProperties();
        props.setMaxAttempts(2);
        props.getBackoff().setInitialInterval(Duration.ofMillis(100));
        return props;
    }
    
    @Bean
    @Profile("prod")
    public SpringAiRetryProperties prodRetryProperties() {
        SpringAiRetryProperties props = new SpringAiRetryProperties();
        props.setMaxAttempts(10);
        props.setOnHttpCodes(Arrays.asList(429, 503));
        props.getBackoff().setInitialInterval(Duration.ofSeconds(2));
        return props;
    }
}

Custom Bean Override

Override RetryTemplate

import org.springframework.retry.support.RetryTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CustomRetryConfig {
    
    /**
     * Custom RetryTemplate overrides auto-configured bean
     */
    @Bean
    public RetryTemplate retryTemplate() {
        return RetryTemplate.builder()
            .maxAttempts(5)
            .fixedBackoff(1000)
            .build();
    }
}

Override ResponseErrorHandler

import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.ai.retry.TransientAiException;
import org.springframework.ai.retry.NonTransientAiException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;

@Configuration
public class CustomErrorHandlerConfig {
    
    @Bean
    public ResponseErrorHandler responseErrorHandler() {
        return new ResponseErrorHandler() {
            @Override
            public boolean hasError(ClientHttpResponse response) throws IOException {
                return response.getStatusCode().isError();
            }
            
            @Override
            public void handleError(ClientHttpResponse response) throws IOException {
                int status = response.getStatusCode().value();
                String message = "HTTP " + status;
                
                if (status >= 500) {
                    throw new TransientAiException(message);
                } else {
                    throw new NonTransientAiException(message);
                }
            }
        };
    }
}

Backoff Calculation

Formula

wait_time = min(initial_interval × multiplier^(retry_count - 1), max_interval)

Examples

Default (initial=2s, multiplier=5, max=3m):

Attempt 1: 2s   (2 × 5^0)
Attempt 2: 10s  (2 × 5^1)
Attempt 3: 50s  (2 × 5^2)
Attempt 4+: 180s (capped)
Total: ~22 minutes

Conservative (initial=500ms, multiplier=2, max=5s):

Attempt 1: 500ms
Attempt 2: 1s
Attempt 3: 2s
Attempt 4: 4s
Attempt 5+: 5s (capped)
Total: ~33s for 10 attempts

Fixed (initial=2s, multiplier=1):

All attempts: 2s each
Total: 18s for 10 attempts

Best Practices

1. Match Timeout Budget

Ensure total retry time fits within timeout:

# If system timeout is 30s:
spring.ai.retry.max-attempts=5
spring.ai.retry.backoff.max-interval=5s
# Total: ~15-20s worst case

2. Configure HTTP Codes Explicitly

Always specify important codes:

# Always retry rate limits
spring.ai.retry.on-http-codes=429,503

# Never retry auth errors
spring.ai.retry.exclude-on-http-codes=401,403

3. Adjust for API Type

External APIs:

spring.ai.retry.backoff.initial-interval=5s
spring.ai.retry.backoff.max-interval=60s

Internal services:

spring.ai.retry.backoff.initial-interval=500ms
spring.ai.retry.backoff.max-interval=10s

4. Use Fixed Backoff for Predictability

spring.ai.retry.backoff.multiplier=1
spring.ai.retry.backoff.initial-interval=2s
spring.ai.retry.backoff.max-interval=2s

5. Environment-Specific Settings

Development:

spring.ai.retry.max-attempts=2
spring.ai.retry.backoff.max-interval=500ms

Production:

spring.ai.retry.max-attempts=10
spring.ai.retry.backoff.max-interval=3m

Troubleshooting

Issue: Retries Take Too Long

Problem: Application hangs with long retry delays

Solution: Reduce max-interval and max-attempts

spring.ai.retry.max-attempts=5
spring.ai.retry.backoff.max-interval=10s

Issue: Too Many Failed Retries

Problem: Wasting resources on non-transient errors

Solution: Add codes to exclude list

spring.ai.retry.exclude-on-http-codes=401,403,400,404,422

Issue: Missing Rate Limit Recovery

Problem: Not recovering from rate limits

Solution: Add 429 to retry list

spring.ai.retry.on-http-codes=429
spring.ai.retry.backoff.initial-interval=5s
spring.ai.retry.backoff.max-interval=60s

Configuration Reference

See Configuration Properties Reference for complete details on all properties, types, and validation rules.

Next Steps

tessl i tessl/maven-org-springframework-ai--spring-ai-autoconfigure-retry@1.1.1

docs

index.md

tile.json