Resilience covers areas such as retries, circuit breaking and rate limiting.

sttp client doesn’t have the above built-in, as these concepts are usually best handled on a higher level. Sending a request (that is, invoking myRequest.send() using an implicit backend that is in scope), can be viewed as a:

  • () => Response[T] function for synchronous backends
  • () => Future[Response[T]] for Future-based asynchronous backends
  • IO[Response[T]]/Task[Response[T]] process description

All of these are lazily evaluated, and can be repeated. Such a representation allows to integrate the send() side-effect with a stack-dependent resilience tool. There’s a number of libraries that implement the above mentioned resilience functionalities, hence there’s no sense for sttp client to reimplement any of those. That’s simply not the scope of this library.

Still, the input for a particular resilience model might involve both the result (either an exception, or a response) and the original description of the request being sent. E.g. retries can depend on the request method; circuit-breaking can depend on the host, to which the request is sent; same for rate limiting.


Here’s an incomplete list of libraries which can be used to manage retries in various Scala stacks:

sttp client contains a default implementation of a predicate, which allows deciding if a request is retriable: if the body can be sent multiple times, and if the HTTP method is idempotent. This predicate is available as RetryWhen.Default and has type (Request[_, _], Either[Throwable, Response[_]]) => Boolean.

See also the retrying using ZIO example, as well as an example of a very simple retrying backend wrapper.

Note that some backends also have built-in retry mechanisms, e.g. akka-http or OkHttp (see the builder’s retryOnConnectionFailure method).

Circuit breaking

Rate limiting

Java libraries