Configuring OpenFeign Timeouts and Compression in Spring Cloud

When dealing with synchronous calls in microservice architectures, adjusting the timeout duration for operations is often necessary. OpenFeign, a popular declarative web service client, provides mechanisms to configure these timeouts.

This guide demonstrates how to set up connection and read timeouts for OpenFeign clients within a Spring Cloud environment. We will cover configuration via properties files and Java configuration, illustrate the differences between connection and read timeouts, and discuss the precedence between these configuration methods. Additionally, we'll touch upon related aspects like request/response compression and asynchronous calls.

Environment Setup

The examples are based on the following environment:

  • Spring Cloud Version: 2021.0.0
  • Spring Boot Starter Parent Version: 2.6.2
  • OpenFeign Version: 3.1.0

Configuring Timeouts

OpenFeign offers at least two primary methods for configuring timeouts:

  1. Via external configuration files (application.properties or application.yml).
  2. Via Java configuration classes.

1. Target Service Endpoint

Consider a sample service endpoint that intentionally introduces a delay:


@RequestMapping(value = "/list")
@ResponseBody
public Object list() throws InterruptedException { // Simulate a long-running operation
    Thread.sleep(25000); // 25-second delay
    Map<String, Object> customerData = new HashMap<>();
    customerData.put("name", "John Doe");
    customerData.put("sex", "Male");
    customerData.put("age", "30");
    customerData.put("address", "123 Main St");
    return customerData;
}

2. Timeout Configuration via Properties

Timeouts can be defined in your application.yml file. The default configuration applies to all Feign clients unless overridden for a specific client.


feign:
  client:
    config:
      default:
        connectTimeout: 30000 # 30 seconds connection timeout
        readTimeout: 30000    # 30 seconds read timeout

  • connectTimeout: The maximum time in milliseconds to establish a connection to the remote service.
  • readTimeout: The maximum time in milliseconds to wait for a response after the connection has been established.

Note: To configure timeouts for a specific Feign client, replace default with the actual service name (e.g., customerService).

3. Timeout Configuration via Java

Alternatively, timeouts can be set programmatically using Java configuration.

Configuration Class:


import feign.codec.ErrorDecoder;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignClientConfig {

    @Bean
    public Integer connectTimeOut() {
        return 30000; // 30 seconds connection timeout
    }

    @Bean
    public Integer readTimeOut() {
        return 30000; // 30 seconds read timeout
    }

    @Bean
    public ErrorDecoder feignErrorDecoder() {
        // Custom error decoder implementation
        return new CustomErrorDecoder();
    }

    @Bean
    public RequestInterceptor customRequestInterceptor() {
        return (RequestTemplate template) -> {
            String authToken = retrieveAuthToken(); // Method to get auth token
            template.header("Authorization", authToken);
        };
    }

    // Placeholder for actual token retrieval logic
    private String retrieveAuthToken() {
        // Example: return "Bearer " + SecurityContextHolder.getContext().getToken();
        return "dummy-token";
    }
}

Feign Client Interface:


@FeignClient(name = "customerService", configuration = FeignClientConfig.class)
@Component
public interface CustomerServiceClient {
    @RequestMapping(value = "/customer/list", method = RequestMethod.GET)
    Object getCustomerList();
}

Note: When both properties and Java configuration are present for the same timeout settings, the properties file configuration takes precedence, and the corresponding Java bean configuration is ignored.

4. Test Controller

A controller to invoke the Feign client:


@RestController
public class TestController {

    @Autowired
    private CustomerServiceClient customerServiceClient;

    @GetMapping(value = "/test-timeout")
    @ResponseBody
    public ResponseEntity<?> testTimeout() {
        long startTime = System.currentTimeMillis();
        try {
            Object result = customerServiceClient.getCustomerList();
            Map<String, Object> responseData = new HashMap<>();
            responseData.put("customerData", result);
            return ResponseEntity.ok(new ApiResponse(true, "Success", responseData));
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            String errorMessage = String.format("Request failed: %s, Duration: %d ms", e.getMessage(), (endTime - startTime));
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ApiResponse(false, errorMessage, null));
        }
    }

    // Dummy ApiResponse class for demonstration
    public static class ApiResponse {
        boolean success;
        String message;
        Object data;

        public ApiResponse(boolean success, String message, Object data) {
            this.success = success;
            this.message = message;
            this.data = data;
        }
        // Getters and setters...
    }
}

Testing and Observations

  • If only property configuration is set (e.g., 30s timeout), the call will succeed after 25 seconds, returning the data.
  • If only Java configuration is set (e.g., 30s timeout), the result is the same as property configuration.
  • If both are configured, and the property timeout is set to 5 seconds while Java config is 30 seconds, the property configuration (5s) will win. The client will report an error after approximately 5 seconds.

Example error response when properties win with a 5-second timeout:


{
    "success": false,
    "message": "Request failed: Read timed out executing GET http://customerService/customer/list, Duration: 5178 ms",
    "data": null
}

Related Concerns

Request and Response Compression

For performance optimization or to mitigate timeouts on large paylaods, enabling request and response compression can be beneficial. Configure this in your properties file:


feign:
  compression:
    request:
      enabled: true
      min-request-size: 2048 # Minimum size in bytes to trigger compression
    response:
      enabled: true

Asynchronous Calls

If waiting for a synchronous response is not feasible, consider implementing asynchronous calls. This can be achieved using libraries like AsyncFeign or by leveraging Spring's reactive programming models.

Example using AsyncFeign:


// Configure Async Feign client bean
@Bean
public CustomerServiceClient asyncCustomerServiceClient(SpringEncoder encoder, SpringDecoder decoder) {
    return AsyncFeign.asyncBuilder()
            .encoder(encoder)
            .decoder(decoder)
            .target(CustomerServiceClient.class, "http://your-service-url");
}

// Example test method for asynchronous calls
@GetMapping("test-async")
public String testAsyncClient() throws ExecutionException, InterruptedException {
    List<CompletableFuture<Object>> futures = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
        // Assuming CustomerServiceClient has an async method 'getCustomerListAsync()'
        // futures.add(asyncCustomerServiceClient.getCustomerListAsync());
    }

    // Process results from futures
    // for (CompletableFuture<Object> future : futures) {
    //     Object result = future.get();
    //     log.info("Async Result: " + result);
    // }
    return "Async calls initiated";
}

Refer to relevant documentation for detailed asynchronous implementation patterns.

Concluding Remarks

OpenFeign provides robust features for managing inter-service communication. While its declarative nature simplifies client implementation, be mindful of configuration precedence and explore options like compression and asynchronous calls to optimize performance and reliability.

Tags: Spring Cloud openfeign Timeout Configuration Connection Timeout Read Timeout

Posted on Wed, 20 May 2026 03:30:38 +0000 by denoteone