Event schema
Fields the query expects
| Field | Type | Why it exists |
|---|---|---|
| timestamp_utc | Timestamp | Attempt completion time in UTC. |
| route_template | Utf8 | Stable route template. |
| request_id | Utf8 | Identifier shared by the original attempt and retries. |
| attempt_number | Int64 | One-based attempt sequence. |
| status_code | Int64 | HTTP status returned for the attempt. |
| retry_after_ms | Int64 | Applied retry delay in milliseconds. |
| environment | Utf8 | Deployment environment. |
Copy the query
WITH request_outcomes AS (
SELECT
route_template,
request_id,
COUNT(*) AS attempts,
MIN(CASE WHEN status_code = 429 THEN attempt_number END) AS first_limited_attempt,
MAX(CASE WHEN status_code BETWEEN 200 AND 299 THEN attempt_number END) AS last_success_attempt
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(CASE WHEN first_limited_attempt IS NOT NULL THEN 1 ELSE 0 END) AS rate_limited_requests,
SUM(CASE
WHEN last_success_attempt > first_limited_attempt THEN 1
ELSE 0
END) AS recovered_requests,
100.0 * SUM(CASE
WHEN last_success_attempt > first_limited_attempt THEN 1
ELSE 0
END) / NULLIF(SUM(CASE WHEN first_limited_attempt IS NOT NULL THEN 1 ELSE 0 END), 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. We review the synthetic sample output separately. Check field types, thresholds, and counting rules 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_template | requests | rate_limited_requests | recovered_requests | recovery_rate_pct |
|---|---|---|---|---|
| /api/search | 4 | 3 | 2 | 66.67 |
| /api/export | 2 | 1 | 0 | 0 |
Synthetic example output. Run the query against your own event schema and thresholds before using it for operational decisions.
Reproduce the example
Download the sample data
The JSON bundle includes the event schema with field types, reproducible input rows, exact SQL, expected output, review notes, and engine version. The CSV contains the displayed result.
How the SQL works
- 1The first CTE creates one record per logical request, preventing retries from inflating request volume.
- 2A request counts as recovered only when a successful attempt number follows a 429 attempt number.
- 3Keeping rate-limited request count beside the percentage makes low-volume results visible.
Edge cases to check
- Use an idempotency or logical request identifier that survives retries.
- Keep attempt numbers stable and ordered within each logical request; a success recorded before a later 429 is not a recovery.
- 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 setupSet up the events this query needs
Related instrumentation and guides
Continue the analysis
Calculate API error rate by route
Rank API routes by 5xx error rate. Exclude routes with fewer than 20 requests so one failure does not dominate the results.
Open recipeCalculate p50, p95, and p99 API latency
Compare median and tail latency by endpoint with DataFusion-compatible percentile SQL.
Open recipeCalculate API error-budget burn rate
Turn hourly request failures into an SLO burn-rate series that shows how quickly the allowed error budget is being consumed.
Open recipeRun it on your 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.