SOFTWARE / SYSTEMS / AIEngineering news. Technical depth.
Architecture / 3 MIN READ

How should a resumable upload API recover when client and server offsets disagree?

Treat the server’s reported offset as the only authoritative upload state.

Treat the server’s confirmed offset as the protocol state. If the client and server disagree, the client should stop guessing, issue HEAD for the upload resource, read the current Upload-Offset, and resume exactly there. For an append-at-offset contract, the server should reject any PATCH whose starting offset does not match current state with 409 Conflict, so retries after disconnects do not duplicate bytes or silently skip data (tus resumable upload protocol, RFC 9110).

Why should the server offset be authoritative?

After a timeout or broken connection, the client cannot know whether the last chunk was committed. HTTP does not carry application state between requests, and a missing response leaves the client without confirmation of the outcome (RFC 9110). In practice, that means the upload resource itself has to tell the client where to continue.

For each upload, compare the request’s expected offset with the stored offset and append bytes only if they match, as one guarded operation. A separate preliminary check cannot prevent another request from advancing the offset before the append.

What should happen after an interrupted response?

Assume the client has uploaded 70 bytes, sends the next 30-byte chunk, and loses the response. Two states are now plausible: the server is still at 70, or it advanced to 100 before the response was lost. The client should not resend the 30 bytes blindly.

The recovery path is:

  • HEAD the upload URL
  • read Upload-Offset
  • send the next PATCH starting exactly at that offset

In tus, HEAD discovers the resume position. A subsequent PATCH must supply that position through Upload-Offset, and the server checks it against the upload’s current state before accepting the append (tus resumable upload protocol).

How should the API respond to an offset mismatch?

Treat a mismatch as a synchronization failure, not as a hint to merge overlapping ranges. Under tus, the server rejects this request with 409 Conflict when its current offset differs from the client’s expected position (tus resumable upload protocol). That is the right contract even if you are not implementing tus verbatim.

A compact checklist:

  • HEAD returns the current committed offset
  • HEAD includes Cache-Control: no-store
  • PATCH requires one explicit starting offset
  • server compares that offset immediately before append
  • on mismatch, return 409 Conflict and do not mutate the upload
  • validate chunk framing and any optional checksum before advancing offset
  • only advance the stored offset after the bytes are accepted for that upload resource

Worked example?

Client state says 70. It sends 30 bytes with Upload-Offset: 70. The network drops before the response arrives.

Recovery:

  1. Client sends HEAD /uploads/abc
  2. Server replies Upload-Offset: 100
  3. Client resumes from 100, not 70

If the server instead reports 70, the client retransmits from 70. If the client ignores the probe and sends another PATCH with Upload-Offset: 70 after the server already moved to 100, the correct response is 409 Conflict (tus resumable upload protocol).

This guidance applies to append-only resumable uploads. If your API allows sparse out-of-order writes or separate multipart assembly, you need a different reconciliation model than a single monotonic offset.

Follow-up: should the client ever trust its local offset after a timeout?

No. Local offset is only a resume hint. After any ambiguous failure, probe the resource and trust the server’s reported offset.

Follow-up: should the server accept overlapping retries to be forgiving?

Usually no. Strict offset matching keeps retries deterministic and prevents duplicate bytes from becoming valid state.

Next step: write your upload contract so HEAD is the recovery probe and offset equality is enforced immediately before append, then add a test that drops the response after a committed chunk and verifies resume behavior.

Reviewed: 2026-09-05

SOURCES & REVIEW

Sources are linked throughout this guide. Product capabilities can change; consult the linked documentation for your deployment.

Read our editorial approach ↗