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

  1. Honor the Retry-After header and retry the request after the indicated delay with exponential backoff and jitter.
  2. Reduce request concurrency (batch, debounce, or circuit-breaker) to stay under the limit.
  3. Cache responses or use conditional requests to cut request volume.
  4. 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

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

Related errors


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/6d26738f64efa3ed. Report an issue: GitHub.