ADR 007: Durable receipt jobs with ARQ¶
- Status: Accepted
- Date: 2026-08-19
- Phase: P1
- Supersedes: ADR 005 for production/demo with Redis
Context¶
ADR 005 used FastAPI BackgroundTasks after 202. A process crash lost
in-flight extraction. Recruiters and the 90-day plan need a queue with retry
and a stable job id.
Render free is still one web instance. A second paid worker is nicer; until
then the API start script can run arq in the same service.
Decision¶
- Queue name
REDIS_KEY_PREFIX+:arq(defaultreckonflow:arq). - Job function
extract_receipt(receipt_id)with_job_id=receipt-extract:{id}. max_tries=3. The job raises after recording a failedextraction_runsrow so ARQ retries. Already-extractedrows no-op.RECEIPT_QUEUE=inlinein tests: keep BackgroundTasks so pytest needs no Redis worker.RECEIPT_QUEUE=arqwhen Redis is up (local compose, Render). If enqueue fails, fall back to inline and logreceipt.arq_enqueue_failed— the demo still extracts; that path is not durable.
HTTP contract unchanged: 202 + poll GET /receipts/{id}.
Consequences¶
- Need Redis and a running ARQ process for durability.
- Tracing is a table +
GET /api/v1/receipts/runs, not Langfuse. - Token counts stay
nulluntil a provider exposes usage (stub never will).