Skip to content

Returning Results from Background Jobs

A background job, by definition, doesn't return a value the way a normal function call does — the caller has already moved on. Getting the result back (or knowing when it's done) requires an explicit mechanism, and picking the wrong one is a common source of silently-lost work.

flowchart LR Junior["Junior: fire-and-forget vs. needing a result"] --> Middle["Middle: polling vs. callbacks/webhooks"] Middle --> Senior["Senior: result storage, TTLs, and lost results"] Senior --> Professional["Professional: result-backend internals at scale"]
flowchart LR Caller[Caller submits job] --> Queue[Job queue] Queue --> Worker[Worker processes it] Worker --> Result["Result stored somewhere\n(DB, cache, callback)"] Caller -.how does it find out?.-> Result

Choose a level

Level Guide You are done when
Junior Fire-and-forget vs. needing a result You can identify which of your background jobs actually need to report a result back.
Middle Polling vs. callbacks You can compare polling and webhook/callback patterns for retrieving a job's result.
Senior Result storage and TTLs You can explain what happens if a caller checks for a result after it's already expired or been evicted.
Professional Result-backend internals at scale You can design a result-retrieval system for a high-volume job queue (e.g. Celery's result backend).

Practice rule

Before submitting any background job, ask: "does anything actually need to know the outcome of this specific job, and by when?" If the honest answer is "no, it's genuinely fire-and-forget," don't build result-retrieval machinery you don't need — it's a real, avoidable cost.