Background jobs let a caller hand work to the platform and return immediately: enqueue an invocation over HTTP, get a jobId back at once, and let the queue run the function with retries, backoff, and a dead-letter queue — no Redis, no worker fleet, no polling loop to host.
Jobs run the same functions you deploy for HTTP traffic, with the same secrets, layers, and observability. The only difference is the trigger: a durable queue row instead of a live request.
Job lifecycle
Every job moves through a small, explicit state machine. A worker claims PENDING jobs in batches, runs them as RUNNING, and records SUCCEEDED or schedules a retry on failure. When attempts are exhausted the job lands in DEAD — the dead-letter state — where you can inspect the error and requeue it manually.
Enqueue and poll
Enqueue with one HTTP call — the response is 202 Accepted with the job id. Poll the job endpoint (or subscribe to run events in the console) to read the result:
# Enqueue: returns immediately with a job id (the function runs in the background) curl -X POST "https://api.inquir.org/functions/{functionId}/invoke-async" \ -H "Authorization: Bearer $INQUIR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"event": {"orderId": "ord_123"}}' # -> { "jobId": "…", "status": "PENDING" } # Poll until the job reaches a terminal state curl "https://api.inquir.org/jobs/{jobId}" \ -H "Authorization: Bearer $INQUIR_API_KEY" # -> { "status": "SUCCEEDED", "resultJson": … } (or FAILED / DEAD with lastError)
Retries and backoff
Retries are opt-in per enqueue: pass maxAttempts (up to 100) and failed attempts are re-queued with exponential backoff — 1 s, 2 s, 4 s and so on, capped at 5 minutes, with jitter to avoid thundering herds.
maxAttemptscounts the total attempts, not just retries; the default is 1 (no retry).- A job that stays RUNNING past the visibility timeout (22.5 min) is presumed crashed and returned to the queue — write handlers so a second delivery is safe.
- Delayed starts are supported via a schedule offset of up to 7 days — useful for reminders and cooldown windows.
Idempotency and concurrency control
Two enqueue-time options keep duplicate work and stampedes out of your system:
idempotencyKey— enqueueing twice with the same key returns the original job instead of creating a duplicate (the response marks itdeduplicated).concurrencyKey+concurrencyLimit— cap how many jobs sharing a key run at once (per customer, per repository, per anything you choose).priority— higher-priority jobs are claimed first when the queue is deep.
Dead-letter queue
When the last attempt fails, the job becomes DEAD with its final error attached, and a terminal FAILED invocation is recorded for history. Dead jobs stay visible in the console: fix the cause, press requeue, and the job returns to PENDING with a fresh attempt budget.
Jobs vs pipelines vs durable orchestration
Reach for a job when one function should run once in the background. Reach for a pipeline when several functions form a workflow with branching and fan-out. Reach for durable orchestration when the flow needs to sleep on timers or wait for external events for hours or days. All three share the same queue machinery underneath.