C.W.K.
Stream
Lesson 03 of 04 · published

Requests Don't Own Long Work

~10 min · requests, workers, async, durability

Level 0Empty Shelf
0 XP0/35 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"A request that owns hours of work is a job you can kill by closing a laptop."

The Tempting Mistake

The obvious way to build 'transcribe this archive' is a request handler that does it: the browser calls an endpoint, the handler loops over videos transcribing each, and returns when the archive is done. It works in a demo. It is a disaster in production, because a request is the most fragile owner imaginable. Its lifetime is tied to a TCP connection, a browser tab, a hotel Wi-Fi signal, a laptop lid. Any of those ends and your multi-hour job dies mid-flight, half-done, with no clean way to resume.

The deeper problem isn't the timeout. It's ownership. If the request owns the work, then the work only exists as long as the request does — and requests are designed to be short. You've put hours of value inside a container built to be disposable.

Plan, Enqueue, Observe — Never Own

Recall inverts it. A request never runs the transcription. It does one of three cheap, fast things and returns immediately:

  • Plan — compute what a run would do (which videos, how many) without spending anything.
  • Enqueue — create a durable batch and its queued jobs in the database, then return a batch id. Milliseconds.
  • Observe — read the current status, progress, and ETA of a batch that's already running.

The actual hours of transcription are owned by a persistent worker — a process kept alive by the operating system's service manager, independent of any request. It claims queued jobs and grinds through them whether or not anyone is watching. This is why disconnecting the operator's laptop, or killing the status command, does nothing to the batch. The work was never in the request. The request just wrote a durable intention and walked away.

The Test: Close the Laptop

Here's the one-line test for whether you got this right: start the work, then close the laptop. Does it keep going? If yes, the work lives in a durable queue owned by a persistent worker. If no, some request is secretly holding the job hostage, and the first flaky network will lose hours of it. Recall passes this test by design: the request's only job is to durably record what should happen; a worker that outlives every request makes it happen.

Code

The request enqueues and returns; a worker owns the hours·python
# WRONG: the request owns hours of work
@router.post('/archive/transcribe')
async def transcribe_archive(req):
    for video in select_videos(req):
        do_transcription(video)   # blocks for HOURS
    return {'status': 'done'}     # close the tab and it all dies

# RIGHT: the request writes intent and returns in milliseconds
@router.post('/archive/start')
async def start_batch(req):
    batch = create_batch(req)             # durable rows
    enqueue_jobs(batch)                    # queued, owned by the DB
    return {'batch_id': batch.id}          # returns instantly

# A persistent worker (kept alive by the OS service manager),
# not the request, claims those jobs and runs the hours.

External links

Exercise

Find (or imagine) an endpoint in your own work that does something slow inline — generates a report, processes an upload, runs a long export. Apply the close-the-laptop test: if the caller disconnects mid-way, is the work lost? Redesign it so the endpoint only creates a durable record of intent and returns a handle, and a separate persistent worker does the slow part. Write down what the handle is and how the caller checks progress.
Hint
The pattern has three moving parts: (1) an endpoint that writes a durable job/batch row and returns its id fast, (2) a worker that lives outside any request and claims those rows, (3) a status endpoint the caller polls with the id. If you can't name all three, the slow work is probably still trapped inside a request.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.