Techniques to Implement Retry Mechanisms for Failing API Calls in Microservices
In today's complex, interconnected microservices architecture, network failures, resource constraints, and external system unavailability can interrupt seamless data flow, causing APIs to fail. API failures in microservices can hinder application...

I am Tuanh.net. As of 2024, I have accumulated 8 years of experience in backend programming. I am delighted to connect and share my knowledge with everyone.
1. What Is a Retry Mechanism?
2. Types of Retry Strategies
2.1 Simple Retry
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class SimpleRetry {
private static final int MAX_ATTEMPTS = 3;
private static final int DELAY = 2; // seconds
public static void main(String[] args) {
SimpleRetry simpleRetry = new SimpleRetry();
try {
simpleRetry.callApiWithRetry().get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
public CompletableFuture<Void> callApiWithRetry() {
return attemptApiCall(1);
}
private CompletableFuture<Void> attemptApiCall(int attempt) {
return CompletableFuture.runAsync(() -> {
try {
if (attempt <= MAX_ATTEMPTS) {
System.out.println("Attempt " + attempt);
simulateApiCall();
}
} catch (Exception e) {
if (attempt < MAX_ATTEMPTS) {
try {
System.out.println("Retrying after " + DELAY + " seconds...");
TimeUnit.SECONDS.sleep(DELAY);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
attemptApiCall(attempt + 1).join();
} else {
System.err.println("API call failed after " + attempt + " attempts.");
}
}
});
}
private void simulateApiCall() throws Exception {
// Simulate a failure
throw new Exception("Simulated API failure");
}
}
2.2 Exponential Backoff
import java.util.concurrent.TimeUnit;
public class ExponentialBackoffRetry {
private static final int MAX_ATTEMPTS = 3;
private static final int INITIAL_DELAY = 1; // seconds
public static void main(String[] args) {
ExponentialBackoffRetry exponentialBackoffRetry = new ExponentialBackoffRetry();
exponentialBackoffRetry.callApiWithExponentialBackoff();
}
public void callApiWithExponentialBackoff() {
for (int attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
try {
System.out.println("Attempt " + attempt);
simulateApiCall();
return;
} catch (Exception e) {
int delay = INITIAL_DELAY * (int) Math.pow(2, attempt - 1);
System.out.println("Retrying in " + delay + " seconds...");
try {
TimeUnit.SECONDS.sleep(delay);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
return;
}
}
}
System.err.println("API call failed after all attempts.");
}
private void simulateApiCall() throws Exception {
throw new Exception("Simulated API failure");
}
}
3. Considerations for Retry Mechanisms in Microservices
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.retry.Retry;
import io.github.resilience4j.retry.RetryConfig;
import io.vavr.control.Try;
import org.springframework.web.client.RestTemplate;
import java.time.Duration;
public class CircuitBreakerWithRetry {
private final RestTemplate restTemplate = new RestTemplate();
private final CircuitBreaker circuitBreaker;
private final Retry retry;
public CircuitBreakerWithRetry() {
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofMillis(1000))
.build();
RetryConfig retryConfig = RetryConfig.custom()
.maxAttempts(3)
.waitDuration(Duration.ofMillis(500))
.build();
this.circuitBreaker = CircuitBreaker.of("backendService", circuitBreakerConfig);
this.retry = Retry.of("backendService", retryConfig);
}
public void callServiceWithRetryAndCircuitBreaker() {
Try.ofSupplier(Retry.decorateSupplier(retry,
CircuitBreaker.decorateSupplier(circuitBreaker, this::callBackendService)))
.onFailure(System.out::println)
.get();
}
private String callBackendService() {
return restTemplate.getForObject("https://example.com/api", String.class);
}
public static void main(String[] args) {
new CircuitBreakerWithRetry().callServiceWithRetryAndCircuitBreaker();
}
}
4. Best Practices for Retry Mechanisms
5. Conclusion
Read more at : Techniques to Implement Retry Mechanisms for Failing API Calls in Microservices





