Telemetry
API reliability SQL recipe

Measure API 429 Rate-Limit Recovery

Measure how often rate-limited requests recover on a later attempt without treating every retry as a new request.

Intermediateapi_attempt_eventsReviewed 2026-07-28Tested with Apache DataFusion 45.2.0

Reviewed by the Telemetry product team on . SQL compatibility, event contract, synthetic output, and operational caveats. Editorial ownership

Question answered

Do requests that receive HTTP 429 recover successfully after retrying?

Attempt-level telemetry can make a retry storm look like demand. This pattern first collapses attempts to one request outcome, then measures how many rate-limited requests eventually recovered.

Event contract

Fields the query expects

FieldTypeWhy it exists
timestamp_utcTimestampAttempt completion time in UTC.
route_templateUtf8Stable route template.
request_idUtf8Identifier shared by the original attempt and retries.
attempt_numberInt64One-based attempt sequence.
status_codeInt64HTTP status returned for the attempt.
retry_after_msInt64Applied retry delay in milliseconds.
environmentUtf8Deployment environment.
DataFusion SQL

Copy the query

sql
WITH request_outcomes AS (
  SELECT
    route_template,
    request_id,
    COUNT(*) AS attempts,
    MAX(CASE WHEN status_code = 429 THEN 1 ELSE 0 END) AS was_rate_limited,
    MAX(CASE WHEN status_code BETWEEN 200 AND 299 THEN 1 ELSE 0 END) AS succeeded
  FROM api_attempt_events
  WHERE timestamp_utc >= now() - INTERVAL '24 hours'
    AND environment = 'production'
  GROUP BY route_template, request_id
)
SELECT
  route_template,
  COUNT(*) AS requests,
  SUM(was_rate_limited) AS rate_limited_requests,
  SUM(CASE
    WHEN was_rate_limited = 1 AND succeeded = 1 THEN 1
    ELSE 0
  END) AS recovered_requests,
  100.0 * SUM(CASE
    WHEN was_rate_limited = 1 AND succeeded = 1 THEN 1
    ELSE 0
  END) / NULLIF(SUM(was_rate_limited), 0) AS recovery_rate_pct
FROM request_outcomes
GROUP BY route_template
ORDER BY rate_limited_requests DESC, route_template;

This read-only query is planned and executed against an empty typed table with Apache DataFusion 45.2.0. The deterministic sample output is synthetic and reviewed separately; validate field types, thresholds, and business definitions against your own data. Read the testing methodology.

Query result

Rate-limited request recovery

Search recovers two of three rate-limited requests; export does not recover in the observed window.

route_templaterequestsrate_limited_requestsrecovered_requestsrecovery_rate_pct
/api/search43266.67
/api/export2100

Synthetic example output. Run the query against your own event schema and thresholds before using it for operational decisions.

Rate-limited request recovery: static chart of synthetic recovery_rate_pct values from the Measure API 429 Rate-Limit Recovery example result
Indexable SVG of the deterministic example output. Download it for an article, runbook, or design review with attribution.

Reproduce the example

Download the public fixture

The JSON bundle includes the typed event contract, reproducible input rows, exact SQL, expected output, review notes, and engine version. The CSV contains the displayed result.

How the SQL works

  1. 1The first CTE creates one record per logical request, preventing retries from inflating request volume.
  2. 2A request counts as recovered only when it contains both a 429 attempt and a successful attempt.
  3. 3Keeping rate-limited request count beside the percentage makes low-volume results visible.

Edge cases to decide

  • Use an idempotency or logical request identifier that survives retries.
  • Bound the retry sequence so a request that completes after the reporting window is not permanently labeled failed.
  • Record client cancellations separately from retry exhaustion.

Recommended dashboard

  • Bars: recovery_rate_pct by route
  • Trend: rate_limited_requests and recovered_requests
  • Table: exhausted requests with attempt count and retry delay

Alert guidance

Alert when rate-limited volume is material and recovery stays below the route's reviewed target for several buckets.

Read alert setup

Put the recipe to work

Related instrumentation and guides

Continue the analysis

Run it on real events

Create a table, adapt the fields, and save the result

Start free, send structured events, and use the query result as a chart, shared dashboard widget, or alert input.

Get an API key