eclipse-vertx/vert.x · warning
429 Too Many Requests (RFC6585)
Error message
429 Too Many Requests (RFC6585)
What it means
SC_TOO_MANY_REQUESTS is an HttpResponseExpectation constant for HTTP 429 (RFC6585). It means the client has sent too many requests in a given time window and the server is rate limiting (often with a Retry-After header). Vert.x exposes it for asserting or reacting to throttling in HttpClient expectations.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/http/HttpResponseExpectation.java:275
/** * 425 Unordered Collection (WebDAV, RFC3648) */ HttpResponseExpectation SC_UNORDERED_COLLECTION = status(425); /** * 426 Upgrade Required (RFC2817) */ HttpResponseExpectation SC_UPGRADE_REQUIRED = status(426); /** * 428 Precondition Required (RFC6585) */ HttpResponseExpectation SC_PRECONDITION_REQUIRED = status(428); /** * 429 Too Many Requests (RFC6585) */ HttpResponseExpectation SC_TOO_MANY_REQUESTS = status(429); /** * 431 Request Header Fields Too Large (RFC6585) */ HttpResponseExpectation SC_REQUEST_HEADER_FIELDS_TOO_LARGE = status(431); /** * Any 5XX server error */ HttpResponseExpectation SC_SERVER_ERRORS = status(500, 600); /** * 500 Internal Server Error */ HttpResponseExpectation SC_INTERNAL_SERVER_ERROR = status(500); /** * 501 Not Implemented
View on GitHub (pinned to fb308bd8c3)
Solutions
- Honor the Retry-After header and retry the request after the indicated delay with exponential backoff and jitter.
- Reduce request concurrency (batch, debounce, or circuit-breaker) to stay under the limit.
- Cache responses or use conditional requests to cut request volume.
- Raise the quota with the provider or use a dedicated API key if the shared one is exhausted.
Example fix
// before Future.all(IntStream.range(0, 1000).mapToObj(i -> send(i)).collect(toList())); // after // retry with backoff on 429 sendWithRetry(req, attempt -> attempt < 5, delayMs -> delayMs * 2, resp -> resp.statusCode() == 429);
Defensive patterns
Strategy: retry
Validate before calling
if (inFlightRequests >= rateLimitBudget) {
throw new IllegalStateException("would exceed rate limit budget");
} Type guard
boolean is429(HttpClientResponse resp) { return resp.statusCode() == 429; } Try / catch
send().onFailure(err -> {
if (isCauseStatus(err, 429)) {
long delay = parseRetryAfter(err) orBackoff(attempt);
scheduleRetry(delay);
}
}); Prevention
- Implement exponential backoff with jitter on 429
- Honor Retry-After headers
- Cap concurrent requests to endpoints with known quotas
- Cache responses and use conditional requests to reduce volume
When it happens
Trigger: Exceeding a server/API rate limit: bursty parallel requests, missing backoff on retries, load tests hitting production, or many concurrent clients sharing one API key/IP. Seen when expecting success but receiving 429, or explicitly with .expecting(SC_TOO_MANY_REQUESTS).
Common situations: Runaway retry loops without exponential backoff; integration tests hammering an endpoint; shared egress IP exhausting a quota; third-party API quota changes.
Understand the failure class
- HTTP status errors: handling 4xx and 5xx responses — how to handle 4xx and 5xx responses properly.
Related errors
- Unit must not be null
- 421 Misdirected Request
- 422 Unprocessable Entity (WebDAV, RFC4918)
- 423 Locked (WebDAV, RFC4918)
- 424 Failed Dependency (WebDAV, RFC4918)
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/6d26738f64efa3ed.
Report an issue: GitHub.