JUN0.DEV
JUN0.DEV

Choosing Between WebClient and RestTemplate

Published on
  • avatarJunyoung Yang
GitHubkakao-tech-campus-3rd-step3/Team12_BEUniSchedule backend repository

In the final Kakao Tech Campus project, UniSchedule had to call an external timetable API. The feature itself was simply calling an external HTTP API and processing the response, but the call was part of the service flow. So I could not treat the HTTP client choice as a small detail.

At first, I could implement it quickly with the familiar RestTemplate. Honestly, if the goal was only to ship the feature fast, RestTemplate felt the easiest. But when I thought about maintaining the project, I also had to consider Spring's support direction and settings such as timeout, retry, and connection configuration.

This post is a record of how I chose between RestTemplate and WebClient.

Initial Options

There are several ways to call an external HTTP API in Spring, but at the time I mainly compared these two.

  • RestTemplate
  • WebClient

RestTemplate is simple to use and has many examples. It also feels natural in a synchronous Spring MVC service. On the other hand, WebClient belongs to the WebFlux family of APIs, so at first it can feel like the whole project needs to become reactive.

But my decision was not based on "WebClient is non-blocking, so it is better." The project was based on Spring MVC, and I had no plan to change the whole structure to WebFlux just because of one external API call.

Problem

With RestTemplate, I could build the feature quickly. Still, there were a few things that bothered me when thinking about using it continuously in a new project.

  • It is not the client where new features are actively added.
  • Timeout, connection pool, and retry rules still need to be set based on the project.
  • If asynchronous calls or streaming are needed later, the choice may have to change again.

I could not see external API calls as just code that fetches data. If the external API has a problem or responds slowly, it can affect the response time of our own service. So I cared more about how failures could be handled than about the call style itself.

Approach

In the end, I chose to use WebClient as the external API client.

There were three main reasons.

  • It fit better with Spring's recent HTTP client direction.
  • Timeout, error handling, filters, and headers were easier to configure separately.
  • It left room for asynchronous handling or streaming later.

There was one thing I had to be careful about. Using WebClient does not automatically make a Spring MVC application non-blocking. If block() is used at the call site, that request flow is still blocking.

So this choice was not based on "performance will always improve." It was closer to a choice based on Spring's direction and whether the client would be easier to configure and maintain.

Implementation

For external API calls, failure cases mattered more than the success case. So I checked the following points together.

  • Set connection timeout and response timeout.
  • Convert external API failures into internal exceptions.
  • Keep a mapping boundary because the external API response schema can change.
  • Prevent one failed external call from becoming a failure of the entire service.

From this point of view, using WebClient as a one-line call tool would not mean much. The client bean configuration, common error handling, and response mapping also had to be organized together for the choice to make sense.

Trade-offs

Choosing WebClient also had a cost.

  • The spring-webflux dependency is added.
  • If team members are not used to reactive APIs, there is a learning cost.
  • If block() is overused in an MVC flow, most of the non-blocking benefit disappears.

So in code review, I did not focus only on the fact that WebClient was used. I also checked how much of the flow should remain synchronous and how timeout and error handling would be enforced.

Takeaway

After this work, I try not to choose an external API client only because it is familiar.

The points I checked were:

  • First check whether the project is based on Spring MVC or WebFlux.
  • Timeout, retry, and error mapping can matter more than the client choice itself.
  • Even if WebClient is used, the whole flow does not automatically become non-blocking.
  • It is better to leave the reason for the choice in code or in an ADR-like note.

This choice was not about using a newer technology just for the sake of it. It was about making external API calls easier to handle inside the project.