advanced~2h

WebClient: The Reactive HTTP Client

OpenFeign is declarative and simple; WebClient is lower-level and non-blocking. This module is when the second one is actually the right tool.

Learning objectives

  • Beginner: Make a simple GET request with WebClient and extract the response body.
  • Intermediate: Explain the difference between a blocking call and a non-blocking, reactive one.
  • Advanced: Choose between OpenFeign and WebClient for a given service-to-service integration, based on concurrency requirements.
WebClient client = WebClient.builder() .baseUrl("http://inventory-service") .build(); Mono<StockLevel> stock = client.get() .uri("/api/stock/{sku}", "SKU-123") .retrieve() .bodyToMono(StockLevel.class);

Notice the return type: Mono<StockLevel>, not StockLevel directly. This is the core difference from OpenFeign's synchronous interface — WebClient returns a reactive publisher representing a value that WILL arrive, not one that's already there.

💻 Code example

WebClient client = WebClient.builder() .baseUrl("http://inventory-service") .build(); Mono<StockLevel> stock = client.get() .uri("/api/stock/{sku}", "SKU-123") .retrieve() .bodyToMono(StockLevel.class);

A blocking HTTP call (like a plain Feign call) ties up the calling THREAD for the entire duration of the network round-trip — that thread can do nothing else until a response arrives. A non-blocking call frees the thread immediately, registering a callback to run once the response actually arrives, so the same thread can serve other work in the meantime.

Blocking (Feign/RestTemplate)Non-blocking (WebClient)
Thread during the callHeld, idle, waitingReleased immediately
Threads needed for high concurrencyOne per in-flight callA small fixed pool regardless of concurrency
Code readabilitySimple, sequentialRequires reactive-chain thinking (Mono/Flux)

◆ Under the hood

For a typical service making a handful of downstream calls per request, blocking Feign clients are simpler to read and perfectly adequate — the thread-per-call cost is invisible at low-to-moderate concurrency. WebClient's non-blocking model earns its complexity specifically at HIGH concurrency (thousands of simultaneous in-flight calls), where a thread-per-call model would need thousands of threads just to stay idle waiting on network I/O, while WebClient serves the same load with a handful.

✓ Quick recap

  • WebClient returns Mono/Flux (a publisher for a future value), not the value directly — this is the reactive programming model.
  • Blocking calls hold a thread idle for the whole round-trip; non-blocking calls release the thread immediately and resume via callback.
  • Choose WebClient when concurrency is genuinely high enough that thread-per-call would be a real bottleneck — otherwise, OpenFeign's simplicity usually wins.

Want a visual for this concept?

Generate a diagram tailored to “WebClient: The Reactive HTTP Client” — the AI picks whichever visual (flowchart, comparison, sequence, etc.) best fits.

Sign in to generate a visual →

Practice quiz

Next Step

Continue to Spring Cloud Gateway← Back to all Spring Cloud chapters