[Spring Boot 3] Default Aspect Order places Retry outside CircuitBreaker, causing inflated failure counts

Author: GarimaBokdiaCreated Dec 10, 2025Updated Aug 1, 2026
Labelsbug

Description In the current Spring Boot 3 auto-configuration, the default aspectOrder values cause @Retry to wrap @CircuitBreaker.

This results in a logical error where a single operation with multiple retries is recorded as multiple failures by the CircuitBreaker, rather than a single failed unit of work.

Analysis I investigated the default property values in the autoconfigure modules:

  1. RetryProperties.java: retryAspectOrder defaults to Ordered.LOWEST_PRECEDENCE - 4.
  2. CircuitBreakerProperties.java: circuitBreakerAspectOrder defaults to Ordered.LOWEST_PRECEDENCE - 3.

Since Spring's Ordered interface prioritizes lower values as "Outer/First":

  • -4 < -3, so Retry runs first (Outer).
  • CircuitBreaker runs second (Inner).

Reproduction Steps

  1. Create a Service method annotated with both: @Retry(maxAttempts=3) @CircuitBreaker(name="test")
  2. Throw a RuntimeException from the method.
  3. Check Actuator metrics: resilience4j.circuitbreaker.calls (kind="failed").
  4. Observed: Value is 3.0 (One failure recorded per retry attempt).
  5. Expected: Value should be 1.0 (The CircuitBreaker should wrap the entire retryable operation).

Proposed Solution The default circuitBreakerAspectOrder in CircuitBreakerProperties.java should be set to a lower value (higher priority) than RetryProperties to ensure it wraps the Retry aspect by default.

Temporary Workaround For users currently facing this issue, you can enforce the correct order manually in application.properties:

properties
# Force Circuit Breaker to be Outer (runs first)
resilience4j.circuitbreaker.circuitBreakerAspectOrder=1
# Force Retry to be Inner (runs second)
resilience4j.retry.retryAspectOrder=2

**Contribution**
 I am happy to submit a Pull Request to adjust these default values if this alignment fits the roadmap.

Source: resilience4j/resilience4j