ADR-0021 — Dual resumable upload mechanism (tus + provider multipart)

V1 Freeze (2026-06-12): Proposed. V1 ships single-shot presigned PUT with a size cap; resumable multipart is the agreed next increment (P1/P2) but not committed to the freeze.

Context

Enterprise uploads are large and networks are flaky, so uploads must be resumable without re-sending received bytes. But “resumable” is a property achievable several ways, and the right mechanism differs between the smart (chunking) client and a browser/third-party client, and between direct-to-storage and proxied transfers (storage/05). We must not proxy bulk bytes through compute on the default path (ADR-0011).

Decision

Resumability is provided by three composed mechanisms, chosen by client/mode:

  1. Content-addressed resume (Mode A, smart client): committed chunks are durable; resume = re-NegotiateChunks and skip present ones. Content addressing gives resumability for free — no special protocol.
  2. Provider multipart (Mode B1, direct): large whole-object uploads go straight to the provider via presigned part URLs; resume via the provider’s ListParts. No bytes through our compute.
  3. tus (Mode B2, proxied fallback): browsers/CORS/firewall cases upload to the gateway via the tus protocol (HEADUpload-Offset, PATCH from offset); the gateway streams to the provider with a bounded buffer.

Abandoned uploads are reclaimed by staging TTL + provider lifecycle abort of stale multipart + a reconciler (storage/05 §5).

Consequences

Positive

Negative / costs

Alternatives considered

Scaling

Presigned issuance is stateless (scales with control-plane replicas); the data plane scales on the provider (ADR-0011). The only compute-bound path (tus) is the rare fallback and is explicitly capacity-bounded.

References