Library / SDK
smallrye/smallrye-mutiny avatar
smallrye/smallrye-mutiny

Mutiny: an event-driven reactive library with a discoverable Java API

An Intuitive Event-Driven Reactive Programming Library for Java

936 stars149 forksJavaApache-2.0

At a glance

What is it?
Mutiny is a Java library for asynchronous, non-blocking pipelines built on the Reactive Streams protocol, published by the SmallRye project and sponsored by Red Hat. It sits underneath Quarkus and has bindings for Vert.x, Reactor and RxJava, but it does not require either.
Who is it for?
Mutiny suits a Java team whose code is already asynchronous, especially on Quarkus where the reactive APIs return Mutiny types and there is no separate API to learn. It does not suit a team that has standardised on Reactor or RxJava and has no reason to introduce a second reactive type, or a codebase that is mostly blocking JDBC work where a reactive pipeline adds a type system without removing the blocking call.
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 1 day ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • smallrye/smallrye-mutiny936 ★ · +2
Star history
Repository2026-10-212026-11-07
smallrye/smallrye-mutiny934936

2 Stars in the last 17 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Events at the centre, with a flat learning curve

Mutiny is described as an intuitive event-driven reactive programming library for Java, published on Maven Central as io.smallrye.reactive:mutiny, with javadoc served through javadoc.io and documentation at smallrye.io/smallrye-mutiny. The project is sponsored by Red Hat and lives under the SmallRye umbrella.

The design centre is events rather than streams of items. With Mutiny you observe events, react to them and compose processing pipelines, and the README is explicit that a PhD in functional programming is not required. That framing is aimed at Java developers who have to work with asynchrony but do not want to learn a category theory curriculum to express it.

The second stated goal is API shape. The argument is that a class with hundreds of methods is confusing even with good code completion, so Mutiny aims for an explicit API that points you towards the operator you need rather than hiding it behind a generic abstraction. That is a design opinion rather than a measurable claim, but it explains why the library defines its own operator set instead of mirroring an existing one.

The third goal is non-blocking I/O. The library is positioned as a companion for applications built on non-blocking I/O, where the point is to compose operations, transform data, enforce progress, recover from failures and never block a thread.

It fits a wide range of workloads according to the documentation: reactive microservices, data streaming, event processing, API gateways and network utilities. The stated scope is any Java application exhibiting asynchrony.

Reactive Streams underneath, converters on the edges

Mutiny is based on the Reactive Streams protocol, which is what makes it interoperable with the rest of the reactive Java ecosystem. Any library that speaks Reactive Streams can be integrated with it.

The repository layout shows how wide that integration surface is in practice. Alongside the implementation directory there are separate modules for reactor/ and rxjava3/, each holding the converters that let Mutiny interop with those libraries, plus kotlin/ for the Kotlin support mentioned in the README, math/ for the mathematical operators, context-propagation/ for carrying context across async boundaries, and no-deps/ for a variant built without dependencies.

Two modules exist purely to prove correctness. reactive-streams-operators/ and reactive-streams-operators-jakarta/ cover the operators, and reactive-streams-tck-tests/ holds the Reactive Streams test suite tests. The compliance column in the branch table names the Reactive Streams TCK 1.0.4 as the standard each line is validated against, which is a concrete check rather than a marketing claim.

The jakarta variant is the one to notice. Jakarta EE renamed several packages, and reactive libraries that implement the Reactive Streams TCK against javax versus jakarta naming need separate source sets. The presence of both directories means Mutiny handles that split explicitly rather than asking users to pick a classifier and hope.

For Quarkus users the point is simpler. Mutiny is integrated in Quarkus where every reactive API uses Mutiny, and Eclipse Vert.x clients are made available through Mutiny bindings in a separate repository. The README insists, though, that Mutiny is an independent library that can ultimately be used in any Java application, and that framing matters for anyone who does not want a framework dependency to decide their reactive type.

Four maintenance lines and the Java version each one needs

The branch table in the README is the most useful single piece of information for anyone evaluating the project, because it maps each branch to its version series, its Java baseline and its compliance standard.

The main branch carries 3.x.y in development and requires Java 17 with java.util.concurrent.Flow, the Reactive Streams interfaces that arrived in the JDK itself. The 2.9.x branch holds 2.9.y backports and bug fixes on the same Java 17 baseline. The 2.5.x branch is for rare bug fixes and drops to Java 11, still on java.util.concurrent.Flow. The 1.x branch is marked as sunset with rare bug fixes, and it runs on Java 8 while still using Reactive Streams 1.0.4 directly rather than the JDK Flow interfaces.

That last row is the interesting one. The 1.x line keeps working on Java 8 because before Java 9 there was no java.util.concurrent.Flow, so those builds depend on the standalone Reactive Streams artifact instead. Every branch reports Reactive Streams TCK 1.0.4 compliance, so the difference is which interface package you compile against rather than whether the behaviour is standard.

Release history follows the same split. Version 3.3.1 was published on 2026-10-19, 3.3.0 on 2026-06-22 and 3.2.1 on 2026-05-27, and the last push was on 2026-10-19. The gap between 3.3.0 and 3.3.1 is about four months, so patch releases are not on a monthly cadence, and that gap says more about the release rhythm than any general claim about update frequency.

For a team, the practical question is which branch your Java version allows. If you are on Java 8, the sunset line is your only option, and that should influence the decision more than any feature comparison.

Building the library and running the workshop examples

Mutiny is built with Apache Maven and ships a wrapper, so a clone needs no local Maven installation.

shell
./mvnw install

That is the full build. If you want a quick build without running tests or generating API docs, the wrapper takes a flag:

shell
./mvnw -Dquickly

The repository also carries a justfile that wraps the common Maven invocations, which is a faster way to run them once you have just installed.

shell
./mvnw -Dquickly
./mvnw clean install -T4 -Pparallel-tests
./mvnw verify -Pparallel-tests -T4

Those three lines correspond to the quick-build, install and verify recipes. The deep-clean recipe goes further than Maven's own clean, since it also removes the .cache directories found across the tree.

The prepare-release recipe is worth reading even if you never cut a release, because it shows how the pieces fit. It creates a release branch named release/{{version}}, rewrites the current and previous version values in .github/project.yml using yq, sets the new version through the Maven versions plugin, runs a JBang helper to update the documentation attribute files with the new mutiny-version, compiles the workshop-examples module against that version, makes the example scripts executable, commits the version metadata, and then computes the changelog from the previous version recorded in project.yml.

That last step is the interesting part: the changelog is generated from the recorded previous version rather than from commit messages alone, which means a release depends on project.yml being kept accurate.

JBang workshop examples as the actual learning path

The repository contains a workshop-examples directory with self-contained executable JBang scripts that cover the common concerns of the library. The README points at the documentation and website for learning, and the workshop examples are offered as the hands-on companion.

JBang matters here for a practical reason. The scripts declare their own dependencies inline and execute directly, so a reader can run a single file to see one concept without creating a Maven project, resolving a BOM, or waiting for a full dependency tree to download. For a library whose pitch is that reactive programming should not require a steep ramp, an example you can run in one command is a coherent choice.

The release process keeps those examples in step with the library. The prepare-release recipe compiles the workshop-examples module with the -Pupdate-workshop-examples profile against the version being released, passing workshopVersion, and then chmods the discovered Java files executable so the scripts stay runnable.

The examples directory is also where you can see the scope of what Mutiny expects to handle, which is broader than a library that only does HTTP. There are separate modules for math operators, for context propagation, for Kotlin interop, and for reactor and rxjava3 conversion, plus test-utils and a bom directory for dependency management. The bom module is the practical entry point for a consuming team, since it aligns the Mutiny version with the related modules without you pinning each one by hand.

Where Mutiny is the wrong choice

The first honest limitation is that Mutiny does not remove blocking work. It gives you a type system and an operator set for asynchronous flows, but if the code underneath calls a blocking JDBC driver or a synchronous HTTP client, the pipeline still blocks a thread somewhere. Adopting Mutiny in a mostly blocking codebase adds the vocabulary without removing the problem, and the documentation is honest that the fit is for applications exhibiting asynchrony rather than a general purpose upgrade path.

The second is the type proliferation. A team that already uses Reactor or RxJava across its services gains a third reactive type when it adopts Mutiny, and the converters in the reactor/ and rxjava3/ modules exist precisely to smooth that over, which is evidence that the seams are real. If your organisation has standardised on Reactor, Mutiny's advantage over Reactor is mostly API shape and the Quarkus integration, and that may not outweigh a new type in the boundary of the codebase.

The third is version spread. Four branches with four different Java baselines means a library with real historic weight, which is good for stability and awkward for a team that wants a single modern baseline. The 1.x line is explicitly marked as sunset, so a Java 8 shop is signing up for a line that receives only rare bug fixes.

There is also a documentation gap worth noting. The README is a summary, and it points at the online documentation for the detail, so the API surface itself has to be learned from the website and javadoc rather than from the repository.

Editorial conclusion

Mutiny suits a Java team whose code is already asynchronous, especially on Quarkus where the reactive APIs return Mutiny types and there is no separate API to learn. It does not suit a team that has standardised on Reactor or RxJava and has no reason to introduce a second reactive type, or a codebase that is mostly blocking JDBC work where a reactive pipeline adds a type system without removing the blocking call. Before adopting it, check the branch table in the README against your Java baseline, since the current line needs Java 17 while the 1.x branch still runs on Java 8, and confirm that the Quarkus version you run exposes the reactive APIs you need.

Frequently asked questions

What Java version does Mutiny require?

The current main branch and the 2.9.x branch require Java 17 with java.util.concurrent.Flow, the 2.5.x branch targets Java 11, and the sunset 1.x branch still runs on Java 8 using Reactive Streams 1.0.4 instead of the JDK Flow interfaces.

How do I build Mutiny from source?

The library is built with Apache Maven and ships a wrapper, so ./mvnw install runs a full build. For a quick build without tests or API docs use ./mvnw -Dquickly, and a justfile in the repository wraps the common Maven invocations.

Can Mutiny interoperate with Reactor and RxJava?

Yes. Mutiny is based on the Reactive Streams protocol, and the repository contains reactor/ and rxjava3/ modules with converters for those libraries, plus kotlin/ for Kotlin interop.

Do I need Quarkus to use Mutiny?

No. Mutiny is integrated in Quarkus, where every reactive API uses Mutiny, and Vert.x clients are available through Mutiny bindings in a separate repository. The README describes it as an independent library that can be used in any Java application.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. smallrye/smallrye-mutiny on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/smallrye-smallrye-mutiny.svg)](https://hysenlabs.com/projects/smallrye-smallrye-mutiny)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/smallrye-smallrye-mutiny.svg)](https://hysenlabs.com/projects/smallrye-smallrye-mutiny)

Was this useful?