http4s: a minimal Scala HTTP interface built on cats and fs2
A minimal, idiomatic Scala interface for HTTP
At a glance
- What is it?
- http4s is a Typelevel library that gives Scala programs one HTTP abstraction for both client and server. It suits teams already inside the cats-effect and fs2 ecosystem, and fits poorly anyone who wants a framework with batteries included.
- Who is it for?
- Adopt http4s if your service is already written against cats-effect and fs2, and you want HTTP routes expressed as a value you can compose and test rather than a framework that owns your main method. Do not adopt it if you need a full application framework with dependency injection, templating or a management console, or if your team is not comfortable with typeclasses and effect types.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly Scala, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Who http4s is for, and the problem it removes
http4s describes itself as "a minimal, idiomatic Scala interface for HTTP services" and places itself alongside Ruby's Rack, Python's WSGI, Haskell's WAI and Java's Servlets. That comparison is the clearest statement of what it is: an interface layer, not an application framework. The problem it addresses is that in Scala, HTTP servers and HTTP clients were historically separate stacks with separate types, separate configuration models and separate testing stories. A service would define routes with one library and call downstream services with another, and the two never shared a request or response representation.
The audience follows from that. If you are writing Scala against cats-effect and fs2, http4s gives you one HttpRoutes value for the server side and one Client value for the outbound side, both built on the same core types. If you are not already in that ecosystem, the library asks you to learn it first, because its whole surface is expressed in terms of cats typeclasses and fs2 streams. The repository topics list cats, fs2, http, http-client, http-server, scala and typelevel, which is an accurate summary of the dependency direction.
How http4s models a request: routes as partial functions
The README's opening example is the whole architecture in miniature. A route set is built with HttpRoutes.of, and each entry is a pattern match on a request:
val http = HttpRoutes.of {
case GET -> Root / "hello" =>
Ok("Hello, better world.")
}The left side of the case destructures the method and the path segments, so routing is ordinary Scala pattern matching rather than a separate DSL. The right side returns an effect that produces a Response. Ok is a smart constructor that builds a 200 with the given body.
That design has consequences worth naming. Because routes are a value, you can combine two HttpRoutes with the combinators cats provides, mount them under a path prefix, or wrap them in middleware, and the result is still an HttpRoutes. Because the body is produced inside an effect, streaming is the default rather than an add-on: fs2 underpins the entity body, so a response can be a stream that is never fully materialised. The cost is that nothing is hidden. There is no annotation processor scanning your classes and no convention that maps a directory to a route; you write the match, and if you get the path wrong you find out at runtime.
Installing http4s and serving a first route
http4s is published to Maven Central under the org.http4s group, and the README points readers to http4s.org for the full guide. The README shows only the route snippet, so this section stays with what the repository actually states: the modules exist as directories named core, dsl, server, client, ember-client, ember-server and the blaze backend referenced in the Requirements section, and the README asks you to enable partial unification in build.sbt if you are on an older Scala compiler. Scala 2.13 and later have it on by default, so this line is only needed for older compilers:
scalacOptions ++= Seq("-Ypartial-unification")For the blaze backend specifically, the README's Requirements section states that it needs a modern, supported JVM and relies on server APIs unavailable before JDK8u252. Any JDK newer than JDK8u252, including 9 and above, is supported. Check your JDK before you start debugging a startup failure.
The repository also carries an examples/ directory with subdirectories including examples/ember, examples/docker and examples/src. Those are the closest thing to runnable reference material in the tree, and they are a better starting point than assembling a server from scratch. The README does not print a dependency block, so take the artifact names from the module directories and the version from the releases list, and confirm the exact coordinates on http4s.org before you pin anything.
Where http4s stops being the right tool
The minimalism is the limitation. http4s gives you an interface, so everything above the interface is your responsibility: configuration loading, JSON codecs, authentication, metrics, graceful shutdown, connection pool tuning. The repository does ship optional integration modules, including a circe module and a jawn module visible in the top-level tree, and a client-testkit module, but these are integrations rather than a framework. If your team expects a project generator that produces a working service with health checks wired up, http4s will feel like it is missing half the product.
A second boundary is the learning curve. The library is idiomatic Scala in the Typelevel sense, which means typeclass-driven and effect-polymorphic. Developers coming from an imperative HTTP framework will spend their first days reading compiler errors about missing instances rather than writing endpoints. That is a real cost, and it is not offset by the library hiding anything, because it does not try to.
A third point of caution is versioning. The releases list shows both a 0.23.x line and a 1.0.0 milestone line, with v1.0.0-M48 and v0.23.37 published on the same day. The default branch is series/0.23. If you adopt the 1.0.0 milestone, you are adopting a pre-1.0 line, and the README's own instructions are written against the 0.23 series. Pick deliberately and read the http4s.org documentation for the series you choose.
http4s next to tapir, sttp and ZIO HTTP
The alternatives people search for are tapir, sttp and ZIO HTTP, and they differ from http4s in where they put the abstraction.
tapir inverts the relationship: you describe endpoints as values independently of the HTTP library, then interpret those descriptions into http4s, or into another server or client backend. If you need to publish an OpenAPI document or share endpoint definitions between server and client, that extra layer is the point. With http4s alone, the route and its documentation are separate artifacts you keep in sync yourself.
sttp approaches the client side with a request-building API that is not tied to cats-effect, and it can target multiple backends. If your main concern is calling HTTP APIs from a codebase that is not already effect-oriented, sttp asks less of you than http4s's Client does.
ZIO HTTP is built on ZIO rather than cats-effect and fs2. The choice between them is largely the choice of effect system, and it is not a choice you make per library: adopting ZIO HTTP means adopting ZIO's runtime, environment and error model across the service. If your code is already cats-effect, http4s is the shorter path; if it is already ZIO, ZIO HTTP is.
Maintenance, licensing and upgrade cost
The repository is not archived, and the last push was on 2026-09-24, so development is ongoing. The most recent releases are v1.0.0-M48 and v0.23.37, both published on 2026-09-08, with v0.23.36 before them on 2026-07-07. The presence of a maintained 0.23 line alongside a 1.0.0 milestone line means two upgrade questions, not one: whether to move from 0.23.x to 1.0.0 when it lands, and how far behind 0.23.x you are willing to sit.
The repository carries a .scala-steward.conf file, and Scala Steward is the standard tool for opening dependency-update pull requests in Scala projects. That file indicates automated dependency updates are part of the project's workflow, which reduces the chance that a transitive dependency goes stale. It says nothing about whether your own upgrade will be painless.
Licensing is Apache-2.0, stated in the README and present as a LICENSE file at the repository root, with a NOTICE file alongside it. Apache-2.0 permits commercial use and modification and includes a patent grant. The README reproduces the licence text and notes that the software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. If you redistribute http4s, read the NOTICE file. This is a description of the licence, not legal advice; your own counsel should review anything you ship.
Editorial conclusion
Adopt http4s if your service is already written against cats-effect and fs2, and you want HTTP routes expressed as a value you can compose and test rather than a framework that owns your main method. Do not adopt it if you need a full application framework with dependency injection, templating or a management console, or if your team is not comfortable with typeclasses and effect types. Before committing, read the http4s.org documentation for the version you intend to pin, check which backend modules you need (ember-server, ember-client, blaze), and confirm the JDK requirement for blaze from the README's Requirements section.
Frequently asked questions
How does http4s compare to ZIO HTTP?
The difference is the effect system. http4s is built on cats-effect and fs2, while ZIO HTTP is built on ZIO, so choosing between them usually means choosing the runtime, environment and error model for the whole service.
How does http4s compare to sttp?
sttp approaches the client side with a request-building API that is not tied to cats-effect and can target multiple backends. http4s exposes its Client inside the cats-effect and fs2 model, so it asks more of a codebase that is not already effect-oriented.
How does tapir compare to http4s?
tapir lets you describe endpoints as values and then interpret them into a server or client, which supports publishing an OpenAPI document from the same definition. With http4s alone you write the routes directly, so the route and any documentation are separate artifacts you keep in sync.
How does ZIO compare to http4s?
They sit on different effect systems: ZIO HTTP is built on ZIO, while http4s is built on cats-effect and fs2. Adopting one means adopting that runtime, environment and error model across the service rather than only for the HTTP layer.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/http4s-http4s)