Lesson 1 of 4 · 60 min

Build the smallest complete export flow

Produce a contract covering submit, status, completion, and authorized retrieval.

A vertical workflow connects one useful user action through every required layer. For a report export, the goal is not an attractive button or an isolated worker. The user must submit a request, recover its status, obtain the right result, and understand a failure. Build that complete route with a small fixture before expanding formats or filters.
The initial API validates the export specification and authorization. It records a job and a durable intention to process it. The response contains a stable job ID and the information needed to retrieve status. The browser stores the job ID in a recoverable location such as the page URL when appropriate. A refresh should recover the existing job rather than start another export automatically.
A status response is a versioned description of the job. It should say accepted, running, succeeded, failed, or cancelled, and include only fields appropriate to that state. A succeeded job can expose a result identifier or a short-lived download route. A failed job needs a category and a safe message. Do not expose raw storage paths, provider errors with secrets, or another account's job through guessed identifiers.
Keep the first artifact narrow. One input format, one output format, one user role, and a small dataset are enough to test the contract. The absence of a spreadsheet export option does not prevent validating the complete CSV path. In contrast, skipping authorization or treating queue acceptance as completion leaves the central workflow incomplete.

Worked example

The fictional export contract is:
code
1POST /exports2  input: operationKey=K8, report=weekly, range=2026-09-01..073  output: jobId=J8, state=accepted, version=14GET /exports/J85  output: jobId=J8, state=succeeded, version=4, resultId=F86GET /exports/J8/download7  requires: current permission for J88  output: authorized access to F8
The browser moves to a page containing J8. If the initial response is lost, retrying K8 resolves to J8 under the API contract. The worker prepares F8 privately, then uses one guarded database transaction to bind its pointer and mark the job succeeded. The object-store write is separate; only the committed pointer is visible through authorized retrieval.

Make acceptance a durable promise

In this workbook, accepted means that validation and permission checks passed, a job exists durably, and processing intent is recoverable. It does not mean a worker has started or that computation will succeed. HTTP 202 describes acceptance with processing incomplete. The application still needs its own status resource and terminal-state contract; a status code cannot supply recovery by itself.
Consider the gap between inserting the job and enqueueing it. If the API commits J8 and then crashes before enqueueing, a browser can see accepted forever unless another mechanism discovers pending work. A transactionally stored processing intention, such as an outbox entry, lets a dispatcher retry publication. The queue can deliver twice, so the worker also needs a claim and completion protocol. The outbox solves durable intent, not every later duplication.
An inspectable operation record separates these duties:
code
1operation: {account:A2, key:K8, type:weekly-export,2            inputDigest:H8, jobId:J8}3job: {id:J8, owner:A2, state:accepted, version:1,4      inputVersion:1, resultPointer:null}5dispatch: {eventId:E8, jobId:J8, state:pending}
The operation lookup is scoped to account and operation type. Reusing K8 with a different payload must follow an explicit contract, normally rejecting the mismatch rather than silently changing J8. The input digest is a comparison aid; its canonicalization rules must be defined. This teaching record does not establish a complete production schema.

Define what each route proves

Route resultEvidence establishedEvidence not established
Accepted J8Durable request and processing intentWorker execution or success
Running J8Current recorded attempt stateGuaranteed future completion
Succeeded J8 with F8Committed result referenceCaller still has download permission
Download allowedCurrent access decision under policyPermanent access after expiry
A refresh reads status. An intentional new export sends a new operation. These actions can share a screen, but they have different identities. A shareable URL must carry only an identifier suitable for the product's exposure policy. Every read still checks permission. An unguessable job ID does not substitute for ownership verification.
The user may close the page before the response arrives. If K8 was retained in a permitted local location before submit, recovery can resolve it after sign-in. If neither job nor operation identity was retained, the product needs another authorized discovery route, such as recent exports. Memory-only state cannot guarantee recovery after browser restart.

Bind completed content without a cross-system transaction claim

Use immutable private output per attempt, such as private/J8/A3. The worker finishes and verifies the content, then performs one guarded database transaction. That transaction checks current job state, current attempt owner or fencing version, and cancellation flag, then atomically binds the result pointer with state succeeded. Only the committed pointer is reachable through the user download route.
This design does not make the object-store write and database transaction atomic. A crash after private object creation but before binding can leave an orphan. The object remains inaccessible through the product, and a retention process can remove it later. A stale worker cannot replace the committed pointer because its guarded transition fails. A database commit followed by a lost acknowledgement can be reconciled by reading the job; it must not publish another result merely because acknowledgement is missing.
The fixture must specify result content. For values 4, 6, and 9, the export must have three valid rows and total 19 under the declared format. A succeeded job pointing to an empty object violates the contract even if every route returned 200.

Misconceptions and a second exercise

One misconception is that accepted abbreviates success. It is a distinct state with unresolved work. A second is that a stable filename makes publication atomic. Readers can observe incomplete writes unless the storage protocol and access path prevent it. The guarded pointer design separates preparation from visibility and explains its orphan case.
Exercise: J8 is accepted; the dispatcher delivers E8 twice; the first worker loses its lease after preparing private output. A second worker completes. State the allowed result. The model answer permits duplicate deliveries and private orphan objects, but only the winning guarded pointer becomes downloadable. Award one point for durable dispatch, one for ownership checks, one for private orphan handling, and one for content verification. This is stronger evidence than asserting exactly one worker ever ran.
Draw the acceptance transaction and completion transaction separately. Explain what survives a crash at each boundary and what the browser can display truthfully. The narrow fixture tests these guarantees before adding formats or a progress stream.

Exercise and solution

A learner refreshes after acceptance but before completion. Describe the first action on page load. Read J8's status after authentication. Do not repeat POST merely because the component mounted. If the job ID was lost with the original response, resolve using K8 according to the operation API. Award one point for retrieval, one for stable identity, and one for avoiding creation in a mount effect.

Interview probe and wrap-up

Which part would you build first in a two-hour work sample? A strong answer chooses a small fixture that crosses submit, durable state, and result display, then adds one meaningful failure. Follow up with an unavailable worker. A weak answer spends the entire period polishing the initial form. A complete narrow path gives every later improvement a stable place to connect.

Sources

docsHTTP Semantics, RFC 9110, section 15.3.3: 202 Acceptedietf.orgdocsAWS transactional outbox patterndocs.aws.amazon.comdocsStripe idempotent request contractdocs.stripe.comdocsNext.js data security guidancenextjs.org

Checkpoint

The API commits a job but crashes before queue publication. Which mechanism preserves processing intent?

AMark the job running immediately.BRetry with a fresh browser key.CStore durable dispatch intent with the job and retry publication.DIncrease the frontend timeout.
Sign up free to answer and see why

Checkpoint

K8 is replayed with changed dates under a payload-bound contract. What should happen?

AReject the mismatch and require a defined new-operation path.BDelete the old job first.CChange the running input.DReturn the old result as the new report.
Sign up free to answer and see why

Checkpoint

A private output exists before pointer commit. What may users retrieve?

AThat object because its name is stable.BThat object when a worker logs success.CAll attempt objects under the prefix.DOnly a committed authorized result; this attempt remains private.
Sign up free to answer and see why

Checkpoint

Accepted has no current worker claim. Accurate UI wording?

AFailed because no worker is visible.BAccepted; waiting for processing.CCompleted; download pending.DWorker is definitely executing.
Sign up free to answer and see why

Checkpoint

A stale attempt finishes after another succeeds. Which rule protects publication?

ALatest timestamp wins.BReplace only when object sizes match.CGuard pointer binding by current job state and attempt authority.DLet the client choose the newest URL.
Sign up free to answer and see why

Can you explain what accepted proves, recover after refresh, and show how private output becomes an authorized completed result? State the relevant identifiers, failure boundary, and evidence in your own words before selecting your confidence.

Not yetGetting thereConfident

Sources

Free to read · better with Enzo

Learn it with Enzo

Save your progress, answer the checkpoints, and let Enzo quiz you on what you just read.