Telemetry
Background jobs SQL recipe

Detect Background-Job Retry Storms

Find time buckets where repeated job attempts create disproportionate queue work and failures.

Intermediatejob_attemptsReviewed 2026-07-28Tested with Apache DataFusion 45.2.0

Question answered

Which job types are spending the most work on retries right now?

A retry storm can increase throughput while useful completions fall. Measuring attempts, unique jobs, retry share, and failure share together separates productive load from repeated work.

Event contract

Fields the query expects

FieldTypeWhy it exists
timestamp_utcTimestampAttempt completion time.
job_idUtf8Stable logical job identifier.
job_nameUtf8Stable job type.
attemptInt64One-based attempt number.
statusUtf8completed, retrying, or failed.
DataFusion SQL

Copy the query

sql
SELECT
  date_trunc('hour', timestamp_utc) AS hour,
  job_name,
  COUNT(*) AS attempts,
  COUNT(DISTINCT job_id) AS logical_jobs,
  SUM(CASE WHEN attempt > 1 THEN 1 ELSE 0 END) AS retry_attempts,
  100.0 * SUM(CASE WHEN attempt > 1 THEN 1 ELSE 0 END)
    / NULLIF(COUNT(*), 0) AS retry_attempt_rate_pct,
  100.0 * SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END)
    / NULLIF(COUNT(*), 0) AS failed_attempt_rate_pct
FROM job_attempts
WHERE timestamp_utc >= now() - INTERVAL '24 hours'
GROUP BY date_trunc('hour', timestamp_utc), job_name
HAVING COUNT(*) >= 20
ORDER BY retry_attempt_rate_pct DESC, attempts DESC;

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

Retry-attempt rate by job

CRM synchronization produces far more attempts than logical jobs and is consuming worker capacity with repeated work.

hourjob_nameattemptslogical_jobsretry_attemptsretry_attempt_rate_pctfailed_attempt_rate_pct
2026-07-27 14:00sync_crm_accounts1,8404921,11860.7622.34
2026-07-27 14:00send_receipt_email3,1803,0611193.740.44

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

How the SQL works

  1. 1Distinct job IDs estimate useful logical work while the raw count measures worker attempts.
  2. 2Attempt numbers above one isolate repeated work without treating an eventual success as a first attempt.
  3. 3Failure rate stays beside retry share so a deliberately retried transient dependency is distinguishable from terminal failure.

Edge cases to decide

  • Fan-out jobs can legitimately create several child IDs; define the logical work identifier before comparing counts.
  • Immediate retries and scheduled backoff have different capacity effects and may need separate fields.
  • A retry storm can move between hourly buckets; add a shorter operational query when response time matters.

Recommended dashboard

  • Bars: retry_attempt_rate_pct by job
  • Trend: attempts and logical_jobs
  • Table: jobs with the most attempts and newest error type

Alert guidance

Alert when retry share, attempt volume, and queue age are elevated together for consecutive complete 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