๐Ÿ”ด The Error You're Seeing

Confirm this matches your console output. If it does, you're in the right place.

ERROR LOG2026-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)

Solution 1โœ“ Most common cause

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); }
Solution 2

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... }
Solution 3

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

Spring Boot 2.x

RestTemplate throws HttpClientErrorException.

Spring Boot 3.x

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.

Course Search
Search across all chapters & stages
๐Ÿ“–

Search the course

Type any topic โ€” branching, stash, rebase, hooks โ€” and jump straight to that chapter.

merge branchesgit stashundo commitrebase