Resilience
Retries and concurrency limits moved into the core framework in Spring 7 — no extra project, no Resilience4j needed for the common cases.
Enable it
@Retryable
| Attribute | Default | Meaning |
|---|---|---|
maxRetries | 3 | attempts after the first one |
delay | 1000 | milliseconds before retrying |
jitter | 0 | random addition to the delay |
multiplier | 1 | backoff factor |
maxDelay | – | cap for the growing delay |
includes / excludes | all / none | which exceptions to retry |
Reactive return types are retried too:
Warning
Only retry idempotent operations. A retried POST /payments can charge twice — send an
idempotency key, or do not retry.
Programmatic retries
When the annotation does not fit — a lambda, a loop body, a non-bean call:
@ConcurrencyLimit
Caps how many threads may be inside a method at once — useful in front of a fragile dependency or a bounded pool.
Callers beyond the limit wait — this is backpressure, not rejection.
Timeouts first
Retries multiply load. Before adding one, make sure the call can fail fast:
A 30 s timeout with 4 retries means a client waiting two minutes for an error.
When you need more
Circuit breakers, bulkheads and rate limiters still live in Resilience4j
(spring-cloud-starter-circuitbreaker-resilience4j). Reach for it when a failing dependency
must be cut off entirely, not just retried.
★ Exercises
- Enable resilient methods and add
@Retryableto a flaky call. - Log every attempt and confirm the exponential backoff in the timestamps.
- Restrict retries to one exception type with
includes. - Put
@ConcurrencyLimit(2)on a slow method and fire 10 parallel requests. - Name two operations in your app that must never be retried.