Reactive Streams 1.0.4 standardized non-blocking backpressure, but the bigger shift is API shape. See where reactive patterns beat REST. Read now.
Why REST Still Wins Most of the Time
REST is a request/response contract: the client asks, the server answers once, and both sides can forget the connection. That model is easy to cache, easy to secure with standard gateways, and easy to reason about when failures are discrete HTTP status codes. For CRUD resources, configuration reads, and anything where the consumer wants a snapshot rather than a live feed, REST remains the default because the shape matches the problem.
Reactive APIs become interesting when that snapshot model breaks down. Long-running work, fan-out to many downstream services, continuous telemetry, and producer/consumer rate mismatches all force either polling, oversized payloads, or timeouts that hide real load. Those are design smells, not reasons to abandon REST everywhere—only signals that the interaction is a stream, not a single transfer.
What Reactive Streams Actually Standardized
Reactive Streams 1.0.4 did not invent streaming; it standardized how non-blocking backpressure travels between a publisher and a subscriber. The subscriber signals demand; the publisher must not overwhelm; cancellation is first-class. That contract matters more than any single library: without shared rules for demand, “async” pipelines still drop data, buffer unboundedly, or block threads under load.
The practical takeaway is protocol-level honesty. An API that claims to be reactive but cannot slow a fast producer or cancel mid-stream is just firehose messaging with nicer syntax. Backpressure turns throughput into a negotiated property of the connection rather than a hope that the consumer keeps up.
Where Reactive Shape Beats REST
Reactive patterns pull ahead when the product of the API is continuous change or progressive delivery rather than a finished document. Streaming search results as they become available, pushing entity updates as they commit, coordinating multi-step pipelines where intermediate states are useful, and bridging services with very different processing rates all fit stream semantics better than repeated GET/POST round trips.
- Progressive results: return partial answers as soon as they exist instead of waiting for the slowest dependency.
- Live state: subscribers stay connected and receive only deltas, avoiding full re-fetch churn.
- Flow control: slow consumers throttle producers without ad-hoc queues or silent drops.
- Composition: map, filter, and merge operators compose services as dataflow graphs, not nested request chains.
REST can approximate some of these with pagination, webhooks, or long polling, but each workaround reintroduces coupling the stream model already encodes: subscription lifetime, demand, and ordered delivery of change.
Design Guidance When You Cross the Line
Treat reactive surface area as deliberate, not fashionable. Keep command and query endpoints RESTful where a single response is enough. Expose streams for feeds, watches, and long-running jobs that emit milestones. Define what “done,” “error,” and “cancel” mean on the wire, and make idempotency rules clear for anything that may reconnect. Prefer bounded buffers and explicit demand over infinite in-memory queues; backpressure only works if every hop honors it.
Test under imbalance: fast producer and slow subscriber, subscriber disconnect mid-stream, and bursty demand. If operators still block or allocate without limit, the API is async in name only. The shift beyond REST is not abandoning resources—it is choosing an interaction model whose shape matches continuous work, continuous change, and honest flow control.