An accepted response means the server has taken responsibility for later processing; it does not mean the task succeeded. For a long-running case report, first persist an operation record and a job request durably, then return an accepted response with a status resource the client can read. The status representation should distinguish queued, running, succeeded, failed, and cancelled states, with stable identifiers and safe error information. Define whether cancellation is best effort and what happens if it arrives after completion. Expire completed status records under a published lifetime, and keep final report access subject to normal authorization.
Accepted Operations and Status Resources
Working case
Reviewer 29 requests a report for 62 cases. The report takes longer than an ordinary HTTP response, so the API creates operation 847, records its owner, queues the job, and responds with a path to the operation state. The browser can leave and return without losing the job. If the worker fails after generating 47 cases, the status must say failed or partial according to the product contract; it cannot keep showing running forever. Another reviewer must not learn about the report merely by guessing operation 847's identifier.
Implementation boundary
function acceptedReport(operationId) {
return {
status: 202,
headers: { Location: `/api/report-operations/${operationId}` },
body: { operationId, state: "queued" }
};
}
console.log(acceptedReport(847).body.state);
// Output: queuedReturn this response only after the operation and enqueue intent are committed. An in-memory task started after responding can vanish on process restart. The status endpoint checks the caller's authority and returns a machine-readable state, progress only when it is accurate, and a final result link only for an authorized user. Polling should have a reasonable interval and backoff; a live channel can reduce delay but needs reconnect rules. The client should stop polling after a terminal state or a user-visible timeout without assuming the server cancelled the work.
Cost and boundaries
Durable operation records, worker capacity, and status polling add storage and request traffic. For n reports polled every p seconds, status requests scale roughly with n/p while they remain active, so set a sensible interval and terminal cleanup. Holding an HTTP connection open for a short task may be simpler; use a status resource when work duration or disconnect recovery justifies it. Progress estimates can be expensive or misleading, so a coarse stage label may be more honest than an invented percentage.
Failure trace
The API returns 202 before writing the operation record. A process restarts between response and enqueue, leaving a client with a status path that returns not found forever. Commit first, then respond. Another failure is a worker that marks the report succeeded before the output file is durable; the client follows the result link and gets an error. Test crash points around acceptance and completion, and verify status transitions, authorization, expiry, and idempotent repeat requests under one operation key.
Verification
- A restart immediately after 202 does not lose the operation.
- Status transitions and terminal result access are authorized and accurate.
- Repeated submission with one idempotency key does not create two reports.
Practice drill
Start a report, capture the operation path, close the browser, and return from a second session of the same user. Verify queued, running, and terminal states. Kill the API process immediately after acceptance and verify the worker still finds the job. Fail the worker after partial output and inspect the final state. Try the status path as another user, then repeat the original request with the same idempotency key and confirm it maps to the intended operation rather than creating a duplicate.
Decision note
Use a durable status resource when work outlives a normal request, and make acceptance, ownership, and terminal outcome observable.
Common Mistakes
- Returning 202 before persisting the operation and enqueue intent.
- Using a status identifier as the only access control.
- Reporting success before the final result is durable.
Connected lessons
API Mutation and Failure Contracts; Conditional Writes and Lost-Update Prevention; Request Deadlines, Retries, and Backoff; Structured API Errors and Recovery; Background Jobs and the Outbox Boundary; Idempotent Write Requests and Lost Responses; Authorization: check permission for this record on every request.
Apply and check
Build Project: conflict-safe case API and review Web Development: API mutation contracts quiz.
Further connections
Large Export Download and Integrity.
Further connections
Trace Context Across Requests and Jobs; User Journey SLOs and Burn Alerts.
Further connections
Job Admission, Idempotency, and Status Resources.
Further connections
Model-Backed Web Application Boundaries; Model Gateway Identity and Request Budgets.
