Skip to content
API Design Learn/Production REST II: Correctness & Scale
Browsing as a guest. Sign in to save your progress and earn XP as you complete chapters.

Long-Running Operations

7 min read

You'll learn to

  • -Model an operation that takes longer than a single request-response cycle using 202 Accepted and a polling resource
  • -Design the operation resource's terminal states so a client can reliably tell when it's actually done

Some operations - generating a large report, processing a video, running a bulk export - genuinely take longer than a client should be expected to wait on a single open HTTP connection for. Modeling these as ordinary synchronous requests either times out or forces the client to hold a connection open far longer than is reasonable; the fix is to accept the request immediately and let the client check back on progress.

202 Accepted: "I've Started, Check Back Later"

Accepting the request immediately, without doing the work synchronously
POST /reports
{"type": "annual_summary", "year": 2025}

HTTP/1.1 202 Accepted
Location: /operations/op_789
{"id": "op_789", "status": "pending"}

202 signals "the request is valid and has been accepted for processing" - distinct from 201 (already created) and 200 (already fully done). The response includes a Location pointing at an operation resource the client can poll to check progress, following the same pattern as the Location header on a 201 Created response, just pointing at a resource representing the in-progress work instead of the finished result.

The Operation Resource and Its Terminal States

Polling the operation resource for status
GET /operations/op_789
HTTP/1.1 200 OK
{"id": "op_789", "status": "processing", "progress_pct": 40}

# ...later...
GET /operations/op_789
HTTP/1.1 200 OK
{
  "id": "op_789",
  "status": "completed",
  "result_url": "/reports/rep_501"
}
  • -pending: accepted, not yet started.
  • -processing: actively running, optionally with progress information.
  • -completed: finished successfully - the response should point at the actual result, not require the client to guess where it landed.
  • -failed: finished unsuccessfully - include enough detail for the client to understand why, using the same error-shape conventions as any other failure response.

The terminal states (`completed`, `failed`) need to be genuinely final and unambiguous - a client polling this resource needs to know for certain when to stop polling, and a `status` field that can flicker or revert leaves that decision unreliable.

For clients that need to react the moment an operation finishes rather than polling repeatedly, pairing this pattern with a webhook (from the previous module) that fires on completion is a natural combination - poll as a fallback, webhook for immediacy.

Interview Signal is part of Pro

See a real weak answer next to a real strong one for this exact topic.

Quiz is part of Pro

Test what you just read with a short quiz, and bank the XP.

Ready to Build This?

Design Long-Running Ops in the API Design Lab's Production Patterns act.

ScaleDojo Logo
Initializing ScaleDojo