Blocking vs Non‑Blocking in Spring: RestTemplate vs WebClient Explained

This article compares Spring's traditional RestTemplate blocking client with the newer reactive WebClient non‑blocking client, explaining their underlying mechanisms, performance differences under concurrency, and provides complete code examples for both approaches, helping developers choose the appropriate tool for efficient HTTP calls.

Programmer DD
Programmer DD
Programmer DD
Blocking vs Non‑Blocking in Spring: RestTemplate vs WebClient Explained

1. Introduction

In this tutorial we compare Spring's two web client implementations — RestTemplate and the new reactive alternative WebClient.

2. Blocking vs Non‑Blocking Clients

Web applications often need to call other services via HTTP, so a web client tool is required.

2.1 RestTemplate – Blocking Client

For a long time Spring provided RestTemplate as a web client abstraction. Under the hood RestTemplate uses a thread‑per‑request model based on the Java Servlet API.

This means the thread remains blocked until a response is received, consuming memory and CPU cycles. With many concurrent requests, threads accumulate, exhausting the thread pool, increasing memory usage, and causing performance degradation due to frequent context switches.

2.2 WebClient – Non‑Blocking Client

WebClient leverages Spring Reactive Framework's asynchronous non‑blocking solution.

Where RestTemplate creates a new thread for each HTTP request, WebClient creates lightweight tasks that are queued by the reactive framework and executed only when a response is ready.

The reactive framework uses an event‑driven architecture and the Reactive Streams API to compose asynchronous logic, allowing fewer threads and system resources to handle more work.

WebClient is part of Spring WebFlux, offering a fluent functional API and returning reactive types such as Mono and Flux.

3. Comparative Example

To demonstrate the difference we implement two REST endpoints that call a slow service returning a list of tweets. The slow service endpoint is defined as:

@GetMapping("/slow-service-tweets")
private List<Tweet> getAllTweets() {
    Thread.sleep(2000L); // delay
    return Arrays.asList(
        new Tweet("RestTemplate rules", "@user1"),
        new Tweet("WebClient is better", "@user2"),
        new Tweet("OK, both are useful", "@user1"));
}

3.1 Using RestTemplate to call the slow service

Implementation of a blocking endpoint:

@GetMapping("/tweets-blocking")
public List<Tweet> getTweetsBlocking() {
    log.info("Starting BLOCKING Controller!");
    final String uri = getSlowServiceUri();
    RestTemplate restTemplate = new RestTemplate();
    ResponseEntity<List<Tweet>> response = restTemplate.exchange(
        uri, HttpMethod.GET, null,
        new ParameterizedTypeReference<List<Tweet>>() {});
    List<Tweet> result = response.getBody();
    result.forEach(tweet -> log.info(tweet.toString()));
    log.info("Exiting BLOCKING Controller!");
    return result;
}

When this endpoint is called, the thread blocks until the slow service responds, then logs the tweets.

Starting BLOCKING Controller!
Tweet(text=RestTemplate rules, username=@user1)
Tweet(text=WebClient is better, username=@user2)
Tweet(text=OK, both are useful, username=@user1)
Exiting BLOCKING Controller!

3.2 Using WebClient to call the slow service

Implementation of a non‑blocking endpoint:

@GetMapping(value = "/tweets-non-blocking", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Tweet> getTweetsNonBlocking() {
    log.info("Starting NON-BLOCKING Controller!");
    Flux<Tweet> tweetFlux = WebClient.create()
        .get()
        .uri(getSlowServiceUri())
        .retrieve()
        .bodyToFlux(Tweet.class);
    tweetFlux.subscribe(tweet -> log.info(tweet.toString()));
    log.info("Exiting NON-BLOCKING Controller!");
    return tweetFlux;
}

The method returns a Flux immediately; the client subscribes to the stream and receives tweets as they become available.

Starting NON-BLOCKING Controller!
Exiting NON-BLOCKING Controller!
Tweet(text=RestTemplate rules, username=@user1)
Tweet(text=WebClient is better, username=@user2)
Tweet(text=OK, both are useful, username=@user1)

4. Conclusion

RestTemplate uses the Java Servlet API and is synchronous and blocking. WebClient is asynchronous and does not block the executing thread while waiting for a response. Although RestTemplate remains usable, non‑blocking approaches generally consume far fewer system resources, making WebClient a better choice in many scenarios.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaspringHTTPreactiveresttemplatewebclient
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.