Fact-checked by Grok 2 weeks ago

Reactive Streams

Reactive Streams is an initiative that defines a standard specification for asynchronous stream processing with non-blocking backpressure, enabling the efficient exchange of streaming data across asynchronous boundaries such as threads or processes. The specification outlines a minimal set of interfaces—Publisher, Subscriber, Subscription, and Processor—that facilitate the production, consumption, and mediation of potentially unbounded sequences of elements while ensuring resource safety through subscriber-controlled demand signaling. Originating from a collaboration among engineers at companies including Kaazing, Lightbend, Netflix, Pivotal, Red Hat, and Twitter, Reactive Streams was developed to unify disparate reactive libraries and address challenges in handling live data streams in concurrent and distributed environments. It aligns with the principles of the Reactive Manifesto, emphasizing responsive, resilient, elastic, and message-driven systems by incorporating backpressure mechanisms to prevent overwhelming slow consumers with data from fast producers. The specification for the Java Virtual Machine (JVM) reached version 1.0.4 in May 2022, licensed under MIT-0, and is implemented in the Java standard library as the java.util.concurrent.Flow interfaces since Java 9, promoting interoperability among libraries such as Project Reactor, RxJava, and Akka Streams.

History

Origins

Reactive Streams originated as a collaborative initiative in late 2013, spearheaded by engineers from Pivotal, , (now X), Lightbend, Kaazing, and , aimed at resolving interoperability challenges among emerging libraries such as RxJava, Akka Streams, and Scalaz Stream. These libraries, while innovative in handling asynchronous data flows, suffered from incompatible and protocols, hindering seamless integration across different frameworks and ecosystems. The first informal discussions took place in late 2013, with the project formally launching in early 2014 under the domain reactive-streams.org, marking the establishment of a dedicated special interest group to drive the effort. These included an initial Skype call in October 2013 with Viktor Klang, Roland Kuhn, Ben Christensen, and others, followed by meetings such as one at Twitter later that year. Key early contributors included Viktor Klang from Lightbend, Ben Christensen from Netflix, Stéphane Maldini from Pivotal, and Roland Kuhn from Lightbend, alongside contributors from the other participating companies, who coordinated through shared prototypes and mailing lists to align on core concepts. The early objective was to define a minimal, implementation-agnostic specification for asynchronous that incorporated non-blocking backpressure mechanisms, ensuring controlled resource usage without prescribing specific libraries or runtimes. This approach drew brief inspiration from the Reactive Manifesto, which emphasized , , elasticity, and message-driven architectures as foundational principles for modern software systems.

Development and Milestones

The Reactive Streams specification reached its initial stable release, version 1.0.0, on April 28, 2015, following extensive community feedback, prototyping, discussions, and iterations among contributors from founding companies including , Pivotal, and Lightbend. This milestone included the core API interfaces, a textual specification, the (TCK) for verifying implementations, and example code, all released into the under Zero. Subsequent minor versions addressed clarifications and improvements without breaking compatibility. Version 1.0.1, released on August 9, 2017, added a glossary, intent explanations for rules, and enhanced TCK coverage and documentation. Version 1.0.2 followed on December 18, 2017, introducing adapters for compatibility with Java's java.util.concurrent.Flow and a dedicated TCK for it, alongside clarifications to Subscriber rules and TCK enhancements for better error reporting. Version 1.0.3, issued on August 23, 2019, fixed edge cases in the TCK such as synchronous completion issues and null pointer exceptions, while refining specification terminology for thread safety. Key project milestones included early proposals for integration into Java SE around late 2014, coinciding with initial Reactive Streams development efforts. TCK development began in 2015 alongside specification refinement, enabling interoperability testing across implementations. By 2016, the specification was accepted into JSR 166 for inclusion in Java 9's concurrency utilities as the java.util.concurrent.Flow API. The project is governed through the open-source repository at under reactive-streams/reactive-streams-jvm, fostering community contributions via issues and pull requests. Version 1.0.4, released on May 26, 2022, marked the latest stable update with TCK refinements for Subscriber rule verification, specification clarifications on method call serialization, and a shift to No Attribution, confirming the specification's maturity with no major changes since. As of 2025, Reactive Streams remains stable, with ongoing maintenance through the repository but no new versions announced, reflecting its established role as a foundational standard for asynchronous on the JVM.

Principles and Goals

Core Objectives

Reactive Streams aims to establish a minimal standard for asynchronous that incorporates non-blocking backpressure, enabling systems to handle data flows without risking overload from faster producers outpacing consumers. This standard addresses the core challenge of unbounded memory usage in asynchronous environments by enforcing bounded buffering, where resource consumption is controlled to prevent arbitrary data accumulation. By promoting non-blocking operations, it facilitates the parallel utilization of resources across threads, processes, or hosts, ensuring in high-throughput scenarios. A primary objective is to ensure among diverse reactive libraries and implementations through a defined for exchange across asynchronous boundaries. This governs the exchange of elements between Publishers and Subscribers, where Publishers provide sequenced only in response to signals from Subscribers, supporting a reactive pull-based that avoids unbounded queues. Subscribers explicitly control buffer bounds by requesting a specific number of elements, thereby maintaining resource efficiency and preventing system exhaustion in dynamic processing graphs. The specification also tackles key challenges in , such as and error handling, by designing interfaces that allow seamless combination of streams while mandating clear error propagation. For instance, errors must be signaled via dedicated methods, enabling Subscribers to handle failures without disrupting the overall flow, and supporting recovery options in intermediate processors. These goals align with broader principles from the Reactive Manifesto, emphasizing and in asynchronous systems.

Relation to Reactive Manifesto

The Reactive Manifesto, published in September 2014, outlines the principles for building reactive systems that are responsive, resilient, elastic, and message-driven, aiming to create flexible, loosely coupled, and scalable architectures capable of handling modern demands like high load and failure recovery. Reactive Streams operationalizes these manifesto principles specifically for asynchronous stream processing, providing a minimal specification to enable interoperability in handling data streams with non-blocking backpressure. It aligns closely with the 's emphasis on message-driven systems by mandating asynchronous, non-blocking between components, where backpressure signals—such as demand requests from subscribers—ensure controlled flow and prevent overload, thereby supporting elasticity under varying loads. This approach contrasts with traditional blocking models, as the notes that synchronous backpressure would undermine the benefits of asynchrony, a concern directly addressed in Reactive Streams' protocols to maintain even during . While the Reactive Manifesto provides a high-level philosophical foundation for reactive architectures, Reactive Streams serves as a concrete implementation standard that supports these ideals—particularly through its focus on bounded queues and flow control—without requiring adoption of a full reactive system design. Historically, the manifesto, with its initial version released on August 22, 2013, predated the formal Reactive Streams specification (version 1.0 in 2015) but directly inspired its goals, emerging from collaborative efforts among engineers at organizations like , Pivotal, and Lightbend starting in late 2013 to standardize stream handling in line with reactive principles.

Specification

Key Interfaces

The Reactive Streams specification defines four core interfaces—Publisher, Subscriber, Subscription, and Processor—that form the foundational protocol for asynchronous, non-blocking with backpressure support. These interfaces are intentionally minimal and functional in design, promoting composability by focusing solely on the contractual obligations between producers and consumers without prescribing implementation details. The Publisher interface represents the provider of stream elements, enabling the production of a potentially unbounded sequence of data items to one or more subscribers. It exposes a single method, void subscribe(Subscriber<? super T> s), which a consumer invokes to establish a connection and begin receiving elements according to its demand. Publishers must ensure that emissions occur only in response to subscriber requests to prevent overwhelming slow consumers. The Subscriber interface defines the consumer endpoint for receiving and processing stream elements, along with control signals for managing the flow. It declares four methods: void onSubscribe(Subscription s), invoked once to establish the subscription; void onNext(T t), called sequentially for each element; void onError(Throwable t), signaling an irrecoverable error that terminates the ; and void onComplete(), indicating successful completion with no further elements. Subscribers are responsible for requesting data via the provided Subscription to enforce backpressure. The Subscription interface encapsulates the one-to-one relationship between a specific Publisher and Subscriber, controlling the lifecycle and flow of data. It includes two key methods: void request(long n), where the Subscriber specifies the number of elements it is willing to receive (with n > 0 or a special value for unbounded demand), and void cancel(), which unsubscribes and prevents further emissions. This mechanism allows Subscribers to throttle incoming data, implementing backpressure at the protocol level. The interface combines the roles of Publisher and Subscriber by extending both, facilitating intermediate stream transformations such as , filtering, or aggregating elements while preserving the reactive contract. Processors receive input via Subscriber methods and produce output through Publisher semantics, enabling chained compositions without breaking the asynchronous, -driven flow.

Backpressure Mechanism

The backpressure mechanism in Reactive Streams provides a non-blocking approach to flow control in asynchronous , enabling consumers to regulate the rate at which producers emit data. This is achieved through the Subscriber signaling to the Publisher via the Subscription interface's request(long n) , where n specifies the number of elements the Subscriber is willing to receive. By design, this pull-based model contrasts with traditional push-based streams, where producers dictate the pace, potentially overwhelming slower consumers; instead, the Subscriber drives the flow, ensuring that data emission pauses until explicit is signaled. Dynamic adjustment of demand is a core feature, allowing Subscribers to issue multiple request(n) calls that accumulate outstanding demand. For slow consumers, a Subscriber might invoke request(1) to process elements one at a time, minimizing buffering needs, while faster scenarios could use larger n values or even Long.MAX_VALUE to signal effectively unbounded demand—though the specification cautions against the latter to prevent resource exhaustion in practice, as implementations typically employ bounded queues to mediate between threads. This flexibility supports scenarios where producers generate data rapidly, such as in high-throughput event streams, by enforcing that Publishers only deliver elements up to the cumulative requested amount, thereby avoiding overload and unbounded memory growth. In cases of mismatched rates, such as a fast producer paired with a slow consumer, backpressure prevents system failure by halting emission until further requests arrive, using bounded intermediaries to cap buffering. If a Subscriber requests more elements than its capacity allows, the specification permits implementation-specific handling, potentially leading to errors or dropped signals if rules like non-negative n (per Rule 3.9) are violated, but the protocol emphasizes cooperative flow control to maintain stability. Overall, this mechanism ensures resilient, resource-efficient processing, as articulated in the specification: "back pressure is an integral part of this model in order to allow the queues which mediate between threads to be bounded."

Rules and Protocols

The Reactive Streams specification defines a set of strict rules that govern the interactions between Publishers, Subscribers, Subscriptions, and Processors to ensure reliable asynchronous with backpressure. These rules, totaling over 40 detailed provisions across the components, enforce serial signal delivery, proper demand management, and graceful termination, preventing issues like unbounded buffering or race conditions. Central to the protocol is the serialization of signals, which must occur in a strict sequence: the Publisher signals onSubscribe first upon subscription, followed by zero or more onNext signals delivering elements, and finally either an onError or onComplete to indicate terminal state, with no interleaving or overlapping calls permitted. All signals—onSubscribe, onNext, onError, onComplete, request(n), and cancel—must respect a happens-before relationship, ensuring that each is fully processed before the next begins, regardless of the underlying execution context. This ordering prevents concurrent modifications and maintains the integrity of the stream contract. The specification imposes no assumptions on threading or execution contexts, allowing signals to be delivered synchronously within the same thread or asynchronously across threads without blocking. Implementations must support non-blocking behavior, enabling Subscribers to request elements via backpressure signals while the Publisher respects demand bounds to avoid overwhelming the consumer. For instance, a Publisher must not emit more onNext signals than requested (Rule 1.1), and may emit fewer before terminating (Rule 1.2). Error propagation follows precise protocols: upon detecting a failure, a Publisher must signal onError with a non-null Throwable, marking the stream as terminal and prohibiting any further signals (Rule 1.4). Subscribers must handle onError without invoking methods on the Subscription or Publisher afterward (Rule 2.3), and treat the Subscription as cancelled upon receipt (Rule 2.4). Null parameters in signals trigger a NullPointerException, and all signal methods must return normally unless specified otherwise (Rule 2.13). This ensures errors halt the stream cleanly without cascading failures. Cancellation is managed through the Subscription.cancel() method, which requests the Publisher to cease emitting signals and release resources associated with the Subscriber, though it may not take effect immediately if elements are in flight (Rule 3.12). The method is idempotent, thread-safe, and must return normally (Rules 3.5, 3.15); subsequent calls to cancel() or request(n) after cancellation become no-ops (Rules 3.6, 3.7). Subscribers must invoke cancel() serially to avoid races (Rule 2.7) and cancel any prior Subscription upon receiving a new onSubscribe (Rule 2.5). Publishers, in turn, must eventually stop signaling cancelled Subscriptions (Rule 1.8). For Processors, which act as both Subscribers and Publishers, cancellation propagates unless explicitly recovered, in which case the upstream Subscription is still considered cancelled (Rule 4.2). Key rules for Publishers include signaling onComplete for successful termination ( 1.5), supporting multiple concurrent Subscribers optionally ( 1.11), and calling onSubscribe at most once per Subscriber ( 1.9, cross-referenced with 2.12). Subscribers must signal demand explicitly via request(n) before expecting onNext ( 2.1), prepare for terminal signals without prior requests ( 2.9, 2.10), and ensure method calls are serialized ( 2.11). Subscriptions enforce bounds on recursive signaling to prevent stack overflows ( 3.3) and support unbounded cumulative demand up to Long.MAX_VALUE ( 3.17). These protocols collectively ensure composable, safe across diverse implementations.

Technology Compatibility Kit

The Technology Compatibility Kit (TCK) for Reactive Streams is a standardized test suite designed to verify that implementations conform to the specification's requirements, ensuring reliable interoperability across different libraries and frameworks. Released alongside the initial version 1.0.0 of the Reactive Streams specification in April 2015, the TCK provides automated test suites that evaluate compliance with all 47 rules defined in the specification through black-box testing methodologies. This approach uses reference implementations of the core interfaces—such as Publisher, Subscriber, Subscription, and Processor—to simulate interactions without accessing or exposing the internal details of the implementation under test, thereby promoting vendor-neutral verification. Key components of the TCK include specialized verification classes like PublisherVerification, SubscriberVerification, SubscriptionVerification, and ProcessorVerification, each targeting specific aspects of the Reactive Streams interfaces. These classes generate test scenarios that probe adherence to , including proper signal sequencing, , and error propagation. The suite covers a wide range of edge cases, such as concurrent demand requests, asynchronous error signaling, and subscription cancellation under various timing conditions, to ensure robustness in real-world asynchronous environments. By automating these tests, the TCK facilitates thorough validation that goes beyond basic functionality, helping developers identify subtle violations that could lead to issues. The TCK is openly available on GitHub as part of the Reactive Streams JVM repository and is distributed via Maven Central under the artifact org.reactivestreams:reactive-streams-tck, making it accessible for integration into continuous integration pipelines. Passing the TCK is a prerequisite for official certification of compliance, as demonstrated by prominent implementations such as RxJava, which integrates Reactive Streams support and verifies its Flowable types against the TCK, and Akka Streams, which fully implements the TCK to guarantee 100% compatibility. This certification process underscores the TCK's critical role in fostering a ecosystem where components from different vendors can seamlessly exchange streams without compatibility risks, all while preserving proprietary implementation strategies.

Java Integration

Inclusion in Java SE

The integration of Reactive Streams into Java SE was proposed by , leader of the JSR 166 expert group responsible for java.util.concurrent, through JEP 266 ("More Concurrency Updates") in August 2015. This effort built on ongoing discussions within the concurrency community dating back to 2014, aiming to incorporate the Reactive Streams specification as core library primitives to enable standardized asynchronous across JVM ecosystems. The primary motivation for this inclusion was to offer native support for patterns, including backpressure handling, directly in the Standard Edition, thereby reducing reliance on third-party libraries and promoting among reactive frameworks. By nesting the key interfaces—Publisher, Subscriber, Subscription, and —within the new java.util.concurrent. class, the provided a lightweight, specification-compliant foundation without introducing implementation-specific components like schedulers or operators. JEP 266 was targeted for JDK 9 and successfully delivered with the release of 9 in September 2017, coinciding with the introduction of the modular JDK under JSR 376. This marked the official standardization of Reactive Streams primitives in the core platform, aligning them with the existing concurrency utilities. Post-inclusion, the has undergone no significant modifications, maintaining and stability across subsequent Java SE releases. It is available natively from Java 9 onward and remains a foundational element through Java 25 (released September 2025), with compatibility for Java 8 achieved via third-party libraries implementing the equivalent Reactive Streams interfaces.

The Flow API

The API, introduced in Java 9 as part of the java.util.concurrent package, provides a standard set of interfaces and classes for implementing reactive streams directly within the Java platform. It defines flow-controlled components for asynchronous event streams, enabling non-blocking backpressure in concurrent applications. These components are designed for with any Reactive Streams-compliant implementation, ensuring seamless integration across libraries and frameworks. The core interfaces—Flow.Publisher, Flow.Subscriber, Flow.Subscription, and Flow.Processor—are nested within the Flow class and mirror the Reactive Streams specification semantically. A Publisher produces a stream of items and allows subscribers to attach via its subscribe(Subscriber<? super T> s) method. A Subscriber receives items through callbacks like onNext(T item), onError(Throwable t), and onComplete(), while onSubscribe(Subscription s) establishes the connection. The Subscription interface governs demand signaling with request(long n) to pull a specified number of items (where n is the number of elements to request, up to Long.MAX_VALUE for unbounded demand) and cancel() to terminate the stream. Processor<T, R>, extending both Publisher and Subscriber, serves as an abstract base for creating intermediate operators that transform or filter streams, such as mapping or buffering, by processing input from upstream subscribers and publishing output downstream. SubmissionPublisher<T> offers a concrete reference implementation of Publisher, facilitating the creation of reactive sources by allowing items to be submitted asynchronously to one or more subscribers. It uses an Executor (defaulting to ForkJoinPool.commonPool()) for delivery and supports buffering with a default size of 256 elements per subscriber, expandable based on demand. Methods like submit(T item) block if the buffer is full (respecting backpressure), while offer(T item) may drop items under overflow; both enable reactive sources for tasks such as event publishing or data streaming. The API integrates with Java's broader concurrency utilities, particularly through compatibility with CompletableFuture for asynchronous completion handling, though it emphasizes streaming over single-value futures. For instance, SubmissionPublisher.consume(Consumer<? super T> c) returns a CompletableFuture<Void> that completes normally upon subscriber onComplete() or exceptionally on errors, bridging reactive streams with promise-based async patterns. This design allows developers to build reactive pipelines that leverage executors and futures without blocking threads, prioritizing stream-oriented processing in high-throughput scenarios.

Implementations and Adoption

Major JVM Implementations

RxJava, developed by and now maintained under the project, provides full compliance with the Reactive Streams specification starting from , which was rewritten atop the standard to enable asynchronous with backpressure. The library introduces the class as its primary type for Reactive Streams , supporting operations on potentially unbounded sequences such as database queries or network responses, while distinguishing it from the non-backpressured Observable for lighter use cases like event handling. RxJava has seen widespread adoption in enterprise applications and development, notably powering 's for efficient event sequencing and fault-tolerant data flows. Project Reactor, originally from Pivotal and now part of the Spring ecosystem, serves as a foundational Reactive Streams implementation on the JVM, emphasizing non-blocking I/O and composable operators. It features two core publisher types: Flux for streams emitting zero to many elements, suitable for multi-item processing like real-time feeds, and Mono for zero or one element, ideal for asynchronous single-result operations such as API calls. Reactor powers , enabling reactive web applications in 3.x stacks, where it handles HTTP request/response streams with built-in backpressure to manage high-throughput scenarios. Akka Streams, from Lightbend, implements the Reactive Streams protocol through a graph-based domain-specific language (DSL) that models data flows as directed acyclic graphs, facilitating complex topologies like fan-out/fan-in patterns. It incorporates asynchronous non-blocking backpressure as standardized by Reactive Streams, ensuring producers respect consumer demand signals to prevent overload in distributed systems. Designed for integration with the Akka actor model, it supports scalable stream processing in actor-based architectures, and has passed the Reactive Streams Technology Compatibility Kit (TCK) for full specification conformance. Ratpack, a reactive web framework for the JVM, leverages the Reactive Streams API to handle asynchronous stream processing with non-blocking backpressure, allowing developers to consume and produce data streams via methods like Response.sendStream(Publisher). It provides utility classes for stream creation and manipulation without mandating a full reactive library, but supports seamless integration with RxJava for enhanced operator chains in HTTP applications. Major implementations such as RxJava, Project Reactor, and Akka Streams have achieved TCK certification, ensuring interoperability across JVM ecosystems for microservices and high-performance services.

Ports to Other Platforms

The Reactive Streams specification, initially designed with platform-agnostic goals to enable asynchronous across languages and environments, has seen limited but notable adaptations beyond the (JVM). A port, known as reactive-streams-js, has been in development since 2015 through collaborative efforts by engineers from organizations including Kaazing, Lightbend, , Pivotal, , and . This implementation provides a standard for asynchronous with non-blocking backpressure in environments. As of 2025, the project remains in a pre-release state with no official versions published on , though code references version 1.0.2 in its API definitions; it influences reactive libraries in , such as adapters for RxJS, which handle similar streaming paradigms but often extend beyond strict spec compliance. For network-based adaptations, the reactive-streams-io project proposes protocols to extend Reactive Streams semantics over and HTTP for streaming data exchange. Initiated in , this experimental effort explores defining wire protocols to govern stream data across asynchronous boundaries in networked systems, but it remains nascent with no stable releases or significant advancements by 2025. In other languages, Reactive Streams exerts influence without widespread official ports. In C#, the reactive-streams-dotnet provides an official specification implementation for .NET, supporting asynchronous stream processing with backpressure and available via NuGet, though much of the ecosystem's reactive capabilities derive from the earlier System.Reactive library (Rx.NET), which shares conceptual overlaps but predates and extends beyond the spec. For Scala, implementations beyond Akka Streams include fs2-reactive-streams, which integrates the Reactive Streams API into the fs2 functional streaming library, enabling type-safe, effectful stream processing in Cats Effect ecosystems. In Kotlin, community efforts center on kotlinx-coroutines-reactive, which offers utilities to bridge coroutines and Flows with Reactive Streams interfaces, allowing conversion between Flows (Kotlin's native reactive streams) and spec-compliant publishers and subscribers for interoperability in reactive applications. Adapting Reactive Streams to non-JVM platforms presents challenges, particularly in mapping the specification's interfaces to language-specific asynchronous models; for instance, JavaScript's promise-based async patterns require custom conversions to align with Publisher-Subscriber protocols and backpressure signals. As of 2025, adoption of Reactive Streams outside the JVM remains limited, with most activity confined to experimental ports and integrations rather than broad ecosystem dominance, maintaining a JVM-centric focus amid rising alternatives like virtual threads and native async constructs.

Influences and Future Directions

Impact on Reactive Ecosystems

Reactive Streams has established a standard for asynchronous stream processing with non-blocking back pressure, enabling seamless interoperability across different reactive libraries and reducing in the ecosystem. For instance, it allows direct composition of publishers and subscribers between RxJava and Akka Streams, where an RxJava can be adapted to an Akka Source or vice versa without custom bridging code. This facilitates modular application design, as developers can mix components from multiple implementations while adhering to the same for exchange and flow control. The specification has profoundly influenced major reactive frameworks, providing a common foundation for building non-blocking applications. Spring WebFlux leverages Reactive Streams through its integration with Project Reactor, enabling reactive web applications that handle high concurrency with back pressure-aware streams. Similarly, incorporates Reactive Streams via its dedicated library, allowing Vert.x event loops to pump data into and out of Reactive Streams-compliant components for scalable, asynchronous processing. Quarkus reactive extensions build on the specification using SmallRye implementations, supporting reactive messaging and data access patterns optimized for cloud-native environments. A key extension of this influence is the MicroProfile Reactive Streams Operators specification, introduced by Eclipse MicroProfile in 2019, which defines portable operators for building and manipulating reactive streams across application servers. This specification provides a set of stages like map, filter, and flatMap that operate on Reactive Streams types, ensuring consistency in asynchronous within MicroProfile-compatible runtimes such as Open Liberty and . By standardizing these operators, it promotes interoperability between reactive libraries and Java EE-style containers, allowing developers to compose complex stream graphs portably. In cloud-native contexts, Reactive Streams supports event-driven processing in operators and serverless architectures, where frameworks like and K use it to handle streaming data from sources such as or without blocking resources. This adoption enables efficient scaling of under variable loads, as mechanisms prevent overload during event bursts in containerized deployments. From a 2025 perspective, Reactive Streams serves as a foundational element for reactive patterns in , the successor to Java EE, through the integration of the Flow API in the Jakarta Concurrency specification, as part of Jakarta EE 11. This evolution supports asynchronous, non-blocking enterprise applications, aligning platforms with modern cloud-native demands while maintaining compatibility with the broader reactive ecosystem.

Relation to Virtual Threads

Java's virtual threads, introduced through Project Loom and stabilized in Java 21 in September 2023, represent a lightweight concurrency model designed to support millions of threads without the resource overhead of traditional platform threads, thereby enabling scalable blocking operations in I/O-bound applications. These threads allow developers to write familiar synchronous code that blocks during I/O without exhausting limited thread pools, addressing scalability challenges in high-concurrency scenarios like web servers. Reactive Streams complements virtual threads by providing a standardized for asynchronous with built-in backpressure management, particularly suited for streaming where demand signaling prevents overwhelming producers. threads, in turn, facilitate the execution of blocking tasks within reactive contexts, such as I/O operations in data , enabling a hybrid approach where synchronous-style runs on lightweight threads without compromising non-blocking reactive flows. For instance, in applications, virtual threads can handle blocking database calls within a Reactive Streams-based , combining the of imperative with reactive . As of 2025, ongoing debates in the community center on whether virtual threads diminish the necessity of in certain domains, such as web applications, where traditional MVC configured with virtual threads often outperforms or simplifies compared to Spring WebFlux for CPU-bound or moderate I/O workloads; these discussions intensified in 2024-2025 with claims that virtual threads are rendering reactive approaches obsolete in many I/O-heavy scenarios. However, Reactive Streams remains indispensable for truly non-blocking, event-driven systems involving high-throughput streams, where virtual threads alone cannot enforce protocol-level backpressure to manage unbounded data flows. Migration trends reflect this complementarity, with frameworks like Project Reactor introducing support for virtual threads in version 3.6.0 (released November 2023) through schedulers like BoundedElasticThreadPerTaskScheduler, which automatically leverages virtual threads for blocking operations when running on 21 or later. This allows seamless integration, such as subscribing to file streams on a virtual thread-backed scheduler, reducing the need for full rewrites while preserving reactive guarantees. Oracle's , from version 21c onward, also supports virtual threads alongside Reactive Streams extensions, enabling pipelined database operations in hybrid reactive-virtual thread models. Ultimately, Reactive Streams does not face replacement by virtual threads, as the former offers specification-enforced backpressure and for asynchronous streams that lightweight threads lack, ensuring resilience in distributed, data-intensive environments.

References

  1. [1]
    Reactive Streams
    The main goal of Reactive Streams is to govern the exchange of stream data across an asynchronous boundary—think passing elements on to another thread or thread ...
  2. [2]
    Reactive Streams Specification for the JVM - GitHub
    The purpose of Reactive Streams is to provide a standard for asynchronous stream processing with non-blocking backpressure.
  3. [3]
    The Reactive Manifesto
    ### Key Principles of the Reactive Manifesto
  4. [4]
    Flow (Java SE 9 & JDK 9 )
    ### Summary of Flow Interfaces and Key Features
  5. [5]
  6. [6]
    Reactive Streams 1.0.0 is here
    Reactive Streams 1.0.0 is here! ... The artifacts, documentation and specifications are released under Creative Commons Zero into the Public Domain. Documentation.
  7. [7]
    Reactive Streams 1.0.1 is here!
    Reactive Streams 1.0.1 is here! After more than two years since 1.0.0, we—the Reactive Streams Special Interest Group—are proud to announce the immediate ...
  8. [8]
  9. [9]
    Reactive Streams 1.0.2 is here!
    As usual, 1.0. 2 is binary, and semantically, compatible with the previous 1.0. x releases of Reactive Streams. The artifacts, documentation and specifications ...Missing: history | Show results with:history
  10. [10]
    Reactive Streams 1.0.3 is here!
    We—the Reactive Streams Special Interest Group—are happy to announce the immediate availability of Reactive Streams version 1.0.3 . When we released 1.0.2 , we ...
  11. [11]
    Reactor 2.0.0.M1 released with Reactive Streams integration! - Spring
    Oct 21, 2014 · This update includes a fully-compliant Reactive Streams implementation in the completely re-written Stream and Promise APIs! This is a huge step ...Missing: proposal | Show results with:proposal
  12. [12]
    [PDF] How reactive streams change the JVM Ecosystem - Huihoo
    2014–2015: Reactive Streams Spec & TCK development, and implementations. 1.0 released on April 28th 2015, with 5+ accompanying implementations. 2015.
  13. [13]
    Reactive Streams 1.0.4 is here!
    Reactive Streams 1.0.4 is here! We—the Reactive Streams Special Interest Group—are happy to announce the immediate availability of Reactive Streams version ...
  14. [14]
    None
    ### Full Text of README.md
  15. [15]
  16. [16]
  17. [17]
    Reactive Streams · ReactiveX/RxJava Wiki - GitHub
    Jun 3, 2015 · Reactive Streams has been a collaborative effort to standardize the protocol for asynchronous streams on the JVM.
  18. [18]
    Reactive Streams :: Akka Guide
    The main goal of Reactive Streams is to govern the exchange of stream data across an asynchronous boundary – think passing elements on to another thread or ...
  19. [19]
    JEP 266: More Concurrency Updates - OpenJDK
    Aug 4, 2015 · JEP 266: More Concurrency Updates. Owner, Doug Lea ... Interfaces supporting the Reactive Streams publish-subscribe framework, nested within the ...Missing: inclusion | Show results with:inclusion
  20. [20]
    Flow (Java SE 11 & JDK 11 ) - Oracle Help Center
    These interfaces correspond to the reactive-streams specification. ... For further API reference and developer documentation see the Java SE Documentation ...
  21. [21]
  22. [22]
    SubmissionPublisher (Java SE 11 & JDK 11 )
    ### Summary of SubmissionPublisher
  23. [23]
    What's different in 2.0 · ReactiveX/RxJava Wiki - GitHub
    Oct 9, 2018 · RxJava 2.0 has been completely rewritten from scratch on top of the Reactive-Streams specification. The specification itself has evolved out of RxJava 1.x.
  24. [24]
    Reactive Programming at Netflix
    Jan 16, 2013 · Rx provides developers with a SQL-like query language that can be used to sequence, filter, and transform events. Rx also makes it possible to ...Asynchronous Programming Is... · Get Netflix Technology... · Optimizing The Netflix Api
  25. [25]
    Reactive - Spring
    Project Reactor is a fully non-blocking foundation with back-pressure support included. It's the foundation of the reactive stack in the Spring ecosystem and is ...
  26. [26]
    Basics and working with Flows - Akka Documentation
    Back-pressure explained. Akka Streams implement an asynchronous non-blocking back-pressure protocol standardised by the Reactive Streams specification, which ...
  27. [27]
    Streams - 2.0.0-rc-1 - Ratpack
    Reactive Streams is an initiative to provide a standard for asynchronous stream processing with non-blocking back pressure on the JVM. Ratpack uses the Reactive ...
  28. [28]
    Reactive Streams standardization for JavaScript - GitHub
    ... Reactive Manifesto), therefore care has been taken to mandate fully non-blocking and asynchronous behavior of all aspects of a Reactive Streams implementation.
  29. [29]
    reactive-streams-io - GitHub
    This is a nascent project exploring the definition of Reactive Stream network protocols. Exploration of this along with goals and motivations can be found in #1
  30. [30]
    Goals and Motivation · Issue #1 · reactive-streams/reactive-streams-io
    Feb 26, 2015 · The intent is to enable Reactive Stream semantics for async, stream-oriented IO supporting backpressure and cancelation. On top of protocols ...Missing: JSR 166
  31. [31]
    Reactive Streams for .NET - GitHub
    The purpose of Reactive Streams is to provide a standard for asynchronous stream processing with non-blocking backpressure. The latest release is available ...Reactive Streams . Net# · Goals, Design And Scope · Specification
  32. [32]
  33. [33]
    fs2-reactive-streams - Scaladex
    A reactive streams implementation for fs2. Scala versions: 2.12 2.11 · Project · Artifacts · Versions · Badges. No README found for this project, ...
  34. [34]
    kotlinx-coroutines-reactive
    kotlinx-coroutines-reactive provides utilities for reactive streams, including coroutine builders and integration with Flow, and can convert flows to ...
  35. [35]
  36. [36]
    Reactive Streams Interop - Akka Documentation
    Akka Streams implements the Reactive Streams standard for asynchronous stream processing with non-blocking back pressure.
  37. [37]
    Reactive Streams - RxJava Doc
    The RxJavaReactiveStreams module bridges between the RxJava 1.x types and Reactive Streams types for interop between Reactive Streams implementations and passes ...
  38. [38]
    Reactive programming vs. reactive systems - Akka
    Oct 24, 2023 · Streams—as in Reactive Streams: unbounded flows of data processing, enabling asynchronous, non-blocking, back-pressured transformation pipelines ...
  39. [39]
    Reactive Streams | Eclipse Vert.x
    This library provides an implementation of reactive streams for Vert.x. Vert.x provides its own mechanisms for handling streams of data and pumping them with ...
  40. [40]
    Getting Started With Reactive - Quarkus
    This guide is a brief introduction to some reactive features offered by Quarkus. Quarkus is a reactive framework, and so offers a lot of reactive features.From sequential to... · Bootstrapping the Reactive... · Reactive Panache Entity
  41. [41]
    microprofile/microprofile-reactive-streams-operators - GitHub
    Reactive Streams is an integration SPI - it allows two different libraries that provide asynchronous streaming to be able to stream data to and from each other.
  42. [42]
    MicroProfile Reactive Streams Operators Specification - SmallRye
    Aug 29, 2018 · Specification: MicroProfile Reactive Streams Operators Specification Version: 1.0-SNAPSHOT Status: Draft Release: November 05, 2018 Copyright (c) ...Missing: development | Show results with:development
  43. [43]
    Project - MicroProfile
    **Summary of MicroProfile Reactive Streams Operators:**
  44. [44]
    Building cloud-native reactive Java messaging applications
    Feb 13, 2025 · Building cloud-native reactive Java messaging applications. Use Quarkus, Smallrye, and IBM MQ to build a minimal footprint reactive application.
  45. [45]
    Build reactive apps on Kubernetes using Camel K
    Nov 7, 2022 · In this article, you'll learn how Apache Camel K can make it easier to develop reactive applications on Kubernetes by integrating data sources, Apache Kafka ...
  46. [46]
    New Features in Jakarta EE 11, with Examples - OmniFish
    Jul 30, 2025 · Jakarta EE 11 modernizes enterprise development by transitioning from older patterns ... Integration with Java 9 Flow reactive streams. Some ...
  47. [47]
    Reactive Programming in Java | Payara Services Ltd
    These streams can represent anything, from user inputs to real-time data feeds, and they're processed asynchronously without blocking threads.
  48. [48]
    JEP 444: Virtual Threads - OpenJDK
    Mar 6, 2023 · Every statement in every method is executed inside a thread and, since Java is multithreaded, multiple threads of execution happen at once. The ...
  49. [49]
    Hello, Java 21 - Spring
    Sep 20, 2023 · Java 21 introduces a new sort of thread, a virtual thread. Now, we can create millions of threads for the heap. It's easy. But fundamentally ...Missing: relation | Show results with:relation
  50. [50]
  51. [51]
    What new is coming in reactor-core 3.6.0? - Spring
    Oct 31, 2023 · Reactor 3.6.0 is coming and going to be GA on November 14. This blogpost describes new features that are included in this upcoming release!<|control11|><|separator|>
  52. [52]
    Reactor WebFlux vs Virtual Threads | Baeldung
    Jun 25, 2024 · Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since.