Speakeasy Logo
Skip to Content

Product Updates

Java async support: Native non-blocking SDKs with reactive streaming

Vishal Gowda

Vishal Gowda

September 3, 2025 - 5 min read

Product Updates

Java SDKs, now async‑native: CompletableFuture + Reactive Streams

Java’s ecosystem has steadily shifted toward asynchronous, event‑driven programming. Reactive architectures are increasingly adopted by major platforms1, while CompletableFuture is ubiquitous in modern APIs. For key reactive concepts, see the Reactive Manifesto glossary . SDKs should match this async‑first reality—without forcing teams to abandon familiar synchronous code.

What’s new

  • Async native: CompletableFuture<T> returned by standard methods.
  • Streaming built‑in: Reactive Streams Publisher<T> for pagination, SSE, JSONL, and file I/O.
  • Dual SDK: Synchronous by default; opt in with .async() per call‑site or service.
  • Blob: A light, framework‑agnostic byte‑stream abstraction for efficient uploads/downloads.

Why async

Traditional blocking SDKs dedicate one thread per in‑flight request. That results in idle threads, wasted memory, and hard‑to‑tune pools. Especially under high concurrency and variable network latency. Async I/O scales with a small, fixed number of threads without sacrificing composition2 or backpressure 3.

When async provides the most value

Scenario
Compositional orchestration
Description
Workflows with multiple dependent or parallel API calls (microservices orchestration, data enrichment)
Async Benefit
Futures/streams model sequencing, fan‑out, retries, and timeouts declaratively instead of blocking threads
Latency tolerance
Description
Remote services with unpredictable or spiky response times
Async Benefit
Async frees threads during waits, so slow calls don't exhaust the pool or block unrelated work
Concurrency scaling
Description
Thousands of requests in parallel (web servers, batch processors)
Async Benefit
Decouples request count from thread count — small event pools service massive concurrency without blowing up memory
Event‑driven pipelines
Description
Real‑time filtering, transformation, and routing (SSE, JSONL streams, pagination)
Async Benefit
Lean on mature reactive ecosystems—Project Reactor, RxJava, Akka Streams—with proven operators for complex event processing
Resource efficiency
Description
Cloud or edge environments with strict memory/cost budgets
Async Benefit
Far fewer thread stacks are required — often 80–90% lower memory under load, enabling smaller, cheaper deployments

Here’s how this works in practice. We expose both sync and async interfaces from one SDK:

Implementation deep‑dive

Our HTTP stack uses Java 11’s HttpClient async APIs and NIO.2  primitives (ByteBuffer, AsynchronousFileChannel, AsynchronousSocketChannel) for end‑to‑end non‑blocking I/O.

Our SDKs go to lengths to ensure there is as little as possible thread blocking work. For standard JSON responses, we collect and decode bytes asynchronously using thenApply/thenCompose. For streams, we hook into Flow.Publisher<List<ByteBuffer>>.

Async iterables via Reactive Streams

For async iterables (pagination, streaming responses), we represent them as Reactive Streams  [Publisher<T>](https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.4/README.md#1-publisher-code ). Traditional Java collections or custom iterators aren’t feasible for async scenarios—they can’t express non‑blocking backpressure  or handle variable consumption rates gracefully. Using Publisher<T> is an increasingly common idiom in modern Java applications, providing seamless interoperability with mature reactive ecosystems like Project Reactor , RxJava , Akka Streams , Vert.x , and Quarkus Mutiny . We keep dependencies light by implementing JDK‑native operators (map, mapAsync, concat, wrap, flatten) through custom publishers, subscribers, and subscriptions.

Protocol‑aware streaming

  • SSE & JSONL: Custom publishers bridge raw byte streams to protocol parsers, yielding typed events on backpressure‑aware Publisher<T>
  • Pagination: A generic, non‑blocking pagination publisher drives page fetches using pluggable ProgressTrackerStrategy to parse cursors and termination conditions

Retries, timeouts, and hooks

  • Async retries use ScheduledExecutorService for non‑blocking exponential backoff with jitter
  • Timeouts/cancellation4 are surfaced with CompletableFuture#orTimeout, completeExceptionally, and cancellation propagation to HTTP requests
  • Hook transformations leverage CompletableFuture for zero‑blocking customization points

Efficient payloads with Blob

Blob is our core abstraction for working with streams of ByteBuffer:

Multipart uploads concatenate publishers—each part (form field or file) is its own stream. Downloads expose Blob so you can stream to disk without buffering whole payloads.

Reactive streaming patterns

Reactor

RxJava

Akka Streams

On Virtual Threads

Virtual threads  make synchronous code scale far better by reducing the cost of blocking. They’re a great fit for simple request/response flows and can be used with the synchronous SDK today. Our async SDK still adds value where you need backpressure, streaming, cancellation, and composition across multiple concurrent I/O operations—patterns that CompletableFuture/Publisher express naturally.

For API Producers: the unified paradigm advantage

  • Broader reach: Works for Spring MVC (sync) and WebFlux/Quarkus (async)
  • Migration flexibility: Adopt async gradually without replacing integrations
  • Lower maintenance: One codebase; two clean interfaces
  • Consistent DX: Same auth, errors, and config everywhere

Getting started

Enable the following flag in your .speakeasy/gen.yaml:

Then run speakeasy run to regenerate your SDK.

For existing SDKs, see our migration guide  for step-by-step instructions on enabling async support for your SDKs.

Looking ahead

This release lays the groundwork for the full spectrum of modern Java patterns—from cloud‑native microservices to real‑time streaming systems. Ready to unlock the benefits of non‑blocking I/O? Regenerate your Java SDK  and try it today.


Footnotes

  1. Netflix API with RxJava  | The Rise of Reactive Programming in Java  | Java Reactive Programming: An In-Depth Analysis  | Reactive Programming is Not a Trend  | Java Reactive Programming 

  2. Composition — The ability to chain and combine async operations declaratively, like future.thenCompose() or stream operators, without manual thread coordination.

  3. Spring WebFlux Overview  — Why reactive/non‑blocking scales with a small, fixed number of threads.

  4. Cancellation — The ability to interrupt or stop async operations gracefully, propagating cancellation signals through composed operations to free resources and avoid unnecessary work.

Last updated on

Organize your
dev universe,

faster and easier.

Try Speakeasy Now