Spring Boot Skills
GitHub
Framework 7 Core

Resilience and Retry

Use when adding retries, backoff, or concurrency limits to Spring Boot 4 / Spring Framework 7 code with core Retryable and ConcurrencyLimit support. Covers enablement, backoff, proxy limits, and behavior after retries are exhausted.

View SKILL.md

Spring Framework 7 provides core declarative retry and concurrency limiting. This is not a repackaging of the separate spring-retry project; attribute names and recovery behavior differ.

See the official Framework resilience reference.

Enable resilient methods

@Configuration
@EnableResilientMethods
class ResilienceConfig { }

Use @Retryable for transient failures and @ConcurrencyLimit as a lightweight bulkhead:

@Service
class CatalogClient {
    @Retryable(
        includes = ConnectException.class,
        maxRetries = 4,
        delay = 200,
        multiplier = 2.0,
        maxDelay = 2000,
        jitter = 50)
    CatalogItem find(UUID id) { ... } // idempotent read
}

@ConcurrencyLimit(4)
Report generateReport(UUID id) { ... }

maxRetries counts retries after the first call, so four retries means five total attempts. Backoff attributes are flat on @Retryable; multiplier = 1.0 means fixed delay.

Core resilience has no @Recover. When attempts are exhausted, the last exception reaches the caller. Catch it at the orchestration boundary or use a listener. Because the implementation is proxy-based, self-invocation bypasses advice. Put retry outside a transactional bean when each attempt needs a fresh transaction.

Failure and deadline policy

  • Classify exceptions at the transport boundary; HTTP clients may wrap connect/timeout errors. Retry only failures approved for that operation, not arbitrary Exception.
  • A write timeout means the outcome may be unknown. Retry payment/order commands only with provider-supported idempotency and the same key and payload on every attempt. Reconcile uncertain outcomes; never turn exhaustion into a fabricated successful payment.
  • Budget all attempts, backoff, connection-pool acquisition and downstream work within the caller's deadline. Per-attempt connect/read timeouts are not a total operation deadline. A retry timeout is not a mechanism for killing an already-running blocking call.
  • Preserve interruption/cancellation and stop scheduling attempts when the budget is exhausted. Do not layer independent retries at gateway, HTTP client and service without a shared budget.
  • Treat authentication/authorization errors and validation errors as permanent. Handle 409 according to the API contract. Honor bounded Retry-After for 429/503 only when policy permits; do not keep a request thread asleep beyond the caller's deadline.

The CatalogRetryService is an executable, three-attempt read example, used with the companion HTTP-client adapter. It deliberately does not implement 429 scheduling or a total deadline. Tests cover transient recovery, exhaustion, permanent errors and interruption through the actual Spring proxy. Its delays are illustrative; choose production values from the downstream latency budget.

Verification scope

The repository fixture targets Boot 4.1.0 with Java 17/21 and checks bounded attempts through real Spring proxies; not a complete deadline-aware payment workflow. Check the coverage matrix before treating another minor version or an illustrative snippet as verified.

Gotchas

  • Agent adds spring-retry for basic core retry - use @EnableResilientMethods with Framework 7.
  • Agent imports org.springframework.retry.annotation - core annotations use org.springframework.resilience.annotation.
  • Agent writes maxAttempts - core uses maxRetries, which counts retries rather than total calls.
  • Agent adds @Recover - core resilience has no recovery callback; handle the final exception at the caller.
  • Agent nests @Backoff - use flat delay, multiplier, maxDelay, and jitter attributes.
  • Agent forgets @EnableResilientMethods - annotations are ignored without enablement.
  • Agent retries a self-invoked method - call through a Spring proxy.
  • Agent retries inside a rollback-only transaction - move retry outside the transactional boundary.
FROM THE REPOSITORY

Examples & templates

bad-payment-client.javaexamples
Source on GitHub
@Retryable(maxAttempts = 4, backoff = @Backoff(delay = 200))
PaymentResult charge(ChargeRequest request) { return remote.charge(request); } // Spring Retry API
good-payment-client.javaexamples
Source on GitHub
@Retryable(includes = ConnectException.class, maxRetries = 3, delay = 200, multiplier = 2.0)
PaymentResult charge(ChargeRequest request) { return remote.charge(request); }
CatalogRetryService.javatemplates
Source on GitHub
package com.example.clients;

import java.util.UUID;
import java.util.concurrent.CancellationException;
import org.springframework.context.annotation.Configuration;
import org.springframework.resilience.annotation.EnableResilientMethods;
import org.springframework.resilience.annotation.Retryable;

/** Bounded retry of an idempotent read. Register as a bean and invoke through its proxy. */
public class CatalogRetryService {
    private final CatalogTransport transport;
    public CatalogRetryService(CatalogTransport transport) { this.transport = transport; }

    @Retryable(includes = TransientCatalogException.class, maxRetries = 2,
        delay = 50, multiplier = 2, maxDelay = 100)
    public String find(UUID id) {
        if (Thread.currentThread().isInterrupted()) throw new CancellationException("Interrupted");
        return transport.fetch(id);
    }

    @FunctionalInterface
    public interface CatalogTransport { String fetch(UUID id); }

    public static class TransientCatalogException extends RuntimeException {
        public TransientCatalogException(Throwable cause) { super("Catalog temporarily unavailable", cause); }
    }

    @Configuration(proxyBeanMethods = false)
    @EnableResilientMethods
    public static class RetryConfiguration {}
}

Verification scope

Compiled sources
CatalogRetryService, both trees
Runtime checks
Real proxies: recovery, exhaustion, permanent errors and interruption

Coverage describes checked-in fixtures, not a guarantee for every snippet or project.

Coverage matrix & agent evidence
ADD TO YOUR AGENT

Install Boot 4 skills

claude plugin marketplace add rrezartprebreza/spring-boot-skills
claude plugin install spring-boot-4-skills@spring-boot-skills