Supported backends

sttp supports a number of synchronous and asynchronous backends. It’s the backends that take care of managing connections, sending requests and receiving responses: sttp defines only the API to describe the requests to be sent and handle the response data. Backends do all the heavy-lifting. Typically, a single backend instance is created for the lifetime of the application.

Choosing the right backend depends on a number of factors: whether you are using sttp to explore some data, or is it a production system; are you using a synchronous, blocking architecture, or an asynchronous one; do you work mostly with Scala’s Future, or maybe you use some form of a Task abstraction; finally, if you want to stream requests/responses, or not.

Default backends

As a starting point, the default backends are good choice. Depending on the platform, the following are available:

  • on the JVM, DefaultSyncBackend and DefaultFutureBackend: both based on Java’s HTTP client

  • on JS, DefaultFutureBackend, based on Fetch

  • on Native, DefaultSyncBackend, based on curl

These default backends provide limited customisation options, hence for any more advanced use-cases, simply substitute them with a specific implementation. E.g. the HttpClientSyncBackend backend, which is the underlying implementation of DefaultSyncBackend, offers customisation options not available in the default one.

Backends overview

Which one to choose?

  • for simple exploratory requests, use the synchronous DefaultSyncBackend / HttpClientSyncBackend.

  • if you have Akka in your stack, use the Akka backend

  • if you have Pekko in your stack, use the Pekko backend

  • if you are using Future without Akka, use the DefaultFutureBackend / HttpClientFutureBackend

  • finally, if you are using a functional effect wrapper, use one of the “functional” backends, for ZIO, Monix, Scalaz, cats-effect or fs2.

Below is a summary of all the JVM backends; see the sections on individual backend implementations for more information:

The backends work with Scala 2.12, 2.13 and 3.

Backends supporting cats-effect are available in versions for cats-effect 2.x (dependency artifacts have the -ce2 suffix) and 3.x.

All backends that support asynchronous/non-blocking streams, also support server-sent events.

There are also backends which wrap other backends to provide additional functionality. These include:

  • TryBackend, which safely wraps any exceptions thrown by a synchronous backend in scala.util.Try

  • EitherBackend, which represents exceptions as the left side of an Either

  • OpenTelemetryTracingBackend, for OpenTelemetry-compatible distributed tracing. See the dedicated section.

  • OpenTelemetryMetricsBackend, for OpenTelemetry-compatible metrics. See the dedicated section.

  • PrometheusBackend, for gathering Prometheus-format metrics. See the dedicated section.

  • extendable logging backends (with an slf4j implementation) backends. See the dedicated section.

  • ResolveRelativeUrisBackend to resolve relative URIs given a base URI, or an arbitrary effectful function

  • ListenerBackend to listen for backend lifecycle events. See the dedicated section.

  • FollowRedirectsBackend, which handles redirects. All implementation backends are created wrapped with this one.

In addition, there are also backends for Scala.JS:

Class

Effect type

Supported stream type

Supports websockets

DefaultFutureBackend

scala.concurrent.Future

n/a

yes (regular)

FetchBackend

scala.concurrent.Future

n/a

yes (regular)

FetchMonixBackend

monix.eval.Task

monix.reactive.Observable[ByteBuffer]

yes (regular & streaming)

FetchZioBackend

zio.Task

zio.stream.Stream[Throwable, Byte]

yes (regular & streaming)

FetchCatsBackend

F[_]: cats.effect.Concurrent

n/a

yes (regular)

And a backend for scala-native:

Class

Effect type

Supported stream type

Supports websockets

DefaultSyncBackend

None (Identity)

n/a

no

CurlBackend

None (Identity)

n/a

no

Backend types

Depending on the capabilities that a backend supports, the exact backend type differs:

  • SyncBackend are backends which are synchronous, blocking, and don’t support streaming.

  • Backend[F] are backends which don’t support streaming or web sockets, and use F to represent side effects (e.g. obtaining a response for a request)

  • StreamBackend[F, S] are backends which support streaming, use F to represent side effects, and S to represent streams of bytes.

  • WebSocketBackend[F] are backends which support web sockets, use F to represent side effects

  • WebSocketStreamBackend[F, S] are backends which support web sockets and streaming, use F to represent side effects, and S to represent streams of bytes.

Each backend type extends GenericBackend has two type parameters:

  • F[_], the type constructor used to represent side effects. That is, when you invoke send(backend) on a request description, do you get a Response[_] directly, or is it wrapped in a Future or a Task?

  • P, the capabilities supported by the backend, in addition to Effect[F]. If Any, no additional capabilities are provided. Might include Streams (the ability to send and receive streaming bodies) and WebSockets (the ability to handle websocket requests).