๐ด The Error You're Seeing
Confirm this matches your console output. If it does, you're in the right place.
2026-03-01 17:25:12.000 ERROR 8842 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.web.client.HttpClientErrorException$TooManyRequests: 429 Too Many Requests: "{\"error\": \"Rate limit exceeded\"}"] with root cause
org.springframework.web.client.HttpClientErrorException$TooManyRequests: 429 Too Many Requestsโก Quick Fix Works 80% of the time
Implement a retry mechanism with exponential backoff using Resilience4j or Spring Retry.
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 2000, multiplier = 2))
public String callExternalApi() { ... }๐ง Why this Happens
Tap to expand the deep technical explanation
You sent too many HTTP requests to an external API in a short time frame. The external server responded with a 429 status code to protect itself from being overloaded, asking your application to slow down.
The HITEC City Parking Spot Analogy:
Imagine a bartender serving drinks. If you slam the bar and order 50 shots in 10 seconds, the bartender (API) will put up a hand and say 'Slow down, I'll serve you in a minute' (429).
๐ How to Reproduce Confirm this is your error
Make RestTemplate call an API that rate-limits your requests with 429 Too Many Requests, without a retry mechanism. RestTemplate throws HttpClientErrorException TooManyRequests.
๐ ๏ธ Solutions (3 Ways to Fix)
Implement Exponential Backoff
๐ Use this when calling third-party APIs that have rate limits.
Instead of retrying immediately, wait 1 second, then 2 seconds, then 4 seconds. This gives the external server time to reset your limit.
@Retryable(value = HttpClientErrorException.TooManyRequests.class,
maxAttempts = 3,
backoff = @Backoff(delay = 1000, multiplier = 2))
public String callApi() {
return restTemplate.getForObject("https://api.example.com/data", String.class);
}Read the Retry-After header
๐ Use this if the external API tells you exactly how long to wait.
Many APIs return a 'Retry-After' header in the 429 response, specifying how many seconds to wait before trying again.
try {
return restTemplate.getForObject(url, String.class);
} catch (HttpClientErrorException.TooManyRequests e) {
String retryAfter = e.getResponseHeaders().getFirst("Retry-After");
Thread.sleep(Long.parseLong(retryAfter) * 1000);
// Retry logic...
}Throttle your own requests
๐ Use this if you are processing a large batch of data.
Add a delay between your requests to stay under the rate limit, rather than relying on retries.
for (Item item : items) {
callApi(item);
Thread.sleep(500); // Wait 500ms between calls
}๐ Version Notes
RestTemplate throws HttpClientErrorException.
RestTemplate or WebClient throws HttpClientErrorException.
๐ก๏ธ How to Prevent This Next Time
Always implement rate limiting and retry logic when integrating with third-party APIs. Use Resilience4j RateLimiter to cap your outbound request rate.