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,
DefaultSyncBackendandDefaultFutureBackend: both based on Java’s HTTP clienton JS,
DefaultFutureBackend, based on Fetchon 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.
JVM backends
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
Futurewithout Akka, use theDefaultFutureBackend/HttpClientFutureBackendfinally, 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:
Class |
Effect type |
Supported stream type |
Supports websockets |
Fully non-blocking |
|---|---|---|---|---|
|
None ( |
|
yes (regular & streaming¹) |
no |
|
None ( |
|
yes (regular & streaming¹) |
no |
|
|
|
yes (regular) |
no |
|
|
|
yes (regular) |
no |
|
|
|
yes (regular & streaming) |
yes |
|
|
|
yes (regular & streaming) |
yes |
|
|
|
yes (regular & streaming) |
yes |
|
None ( |
|
no |
no |
|
|
|
no |
no |
|
|
|
yes (regular & streaming) |
yes |
|
|
|
yes (regular & streaming) |
yes |
|
|
n/a |
no |
yes |
|
|
n/a |
no |
yes |
|
|
|
no |
yes |
|
|
|
no |
yes |
|
|
n/a |
no |
yes |
|
|
|
no |
yes |
|
None ( |
|
yes (regular & streaming¹) |
no |
|
|
|
yes (regular) |
no |
|
|
|
yes (regular & streaming) |
no |
|
|
|
no |
no |
|
|
n/a |
no |
no |
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.
¹ The synchronous backends support streaming & streaming web sockets through Ox Flows, which is available on Java 21+. See
section on synchronous backends for more details.
Backend wrappers
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 inscala.util.TryEitherBackend, which represents exceptions as the left side of anEitherOpenTelemetryTracingBackend, 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.
ResolveRelativeUrisBackendto resolve relative URIs given a base URI, or an arbitrary effectful functionListenerBackendto listen for backend lifecycle events. See the dedicated section.FollowRedirectsBackend, which handles redirects. All implementation backends are created wrapped with this one.CachingBackend, which caches responses. See the dedicated section.
Scala.JS backends
In addition, there are also backends for Scala.JS:
Class |
Effect type |
Supported stream type |
Supports websockets |
|---|---|---|---|
|
|
n/a |
yes (regular) |
|
|
n/a |
yes (regular) |
|
|
|
yes (regular & streaming) |
|
|
|
yes (regular & streaming) |
|
|
n/a |
yes (regular) |
Scala Native backends
And a backend for scala-native:
Class |
Effect type |
Supported stream type |
Supports websockets |
|---|---|---|---|
|
None ( |
n/a |
no |
|
None ( |
n/a |
no |
Backend types
Depending on the capabilities that a backend supports, the exact backend type differs:
SyncBackendare backends which are synchronous, blocking, and don’t support streaming.Backend[F]are backends which don’t support streaming or web sockets, and useFto represent side effects (e.g. obtaining a response for a request)StreamBackend[F, S]are backends which support streaming, useFto represent side effects, andSto represent streams of bytes.WebSocketBackend[F]are backends which support web sockets, useFto represent side effectsWebSocketStreamBackend[F, S]are backends which support web sockets and streaming, useFto represent side effects, andSto 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 invokesend(backend)on a request description, do you get aResponse[_]directly, or is it wrapped in aFutureor aTask?P, the capabilities supported by the backend, in addition toEffect[F]. IfAny, no additional capabilities are provided. Might includeStreams(the ability to send and receive streaming bodies) andWebSockets(the ability to handle websocket requests).