Build a resumable upload with the tus protocol
A resumable upload needs negotiated capability, durable offsets, metadata policy, conflict checks, truthful progress, expiry, cleanup, and processing states.
A progress bar is not evidence that an upload can recover.
If the network fails at 97 percent, the useful questions are whether the server knows the durable offset, whether the client can rediscover the upload URL, whether bytes can repeat safely, whether the session still belongs to the user, and what happens to abandoned partial files.
The tus resumable upload protocol uses HEAD to discover the server offset and PATCH to continue from that exact byte boundary.
We will implement the core session, persist a local file fingerprint to upload URL mapping, reconcile offsets before resuming, and separate byte transfer from later processing.
The server offset is truth. The progress animation is a view of it.
Validate size, type, metadata, quota, and ownership; return a stable upload URL and expiry.
Client sends bytes at Upload-Offset; server verifies current offset, persists the chunk, and returns the next durable offset.
Client restores the upload URL, sends HEAD, compares file fingerprint and server offset, then continues or explains why it cannot.
Define the upload journey
Separate file selection, session creation, byte transfer, server validation, processing, ready state, cancellation, and replacement.
I would pressure-test that decision with four questions:
- When does an object exist?
- When are bytes durable?
- Which processing follows?
- What can the user cancel?
The failure mode here is calling transfer completion finished. In large browser uploads over unstable mobile and office networks where progress, retry, duplicate creation, partial bytes, authentication expiry, checksum failure, cancellation, server cleanup, and post-upload processing affect whether user work arrives, that can hide the exact boundary a reviewer or teammate needs to understand. My working artifact would be an end-to-end upload state model. I want it close enough to the implementation that it can change the work, not created afterward to decorate the story.
The result I would look for is product states aligned with the full ingestion path. That is a narrower claim than saying the whole system improved, but it is also one I can verify and defend.
In practice, I would put an end-to-end upload state model beside the question “When does an object exist?” before the first implementation review. The next pass would use “When are bytes durable?” to test the boundary, then “Which processing follows?” to expose the state most likely to be missed. I would keep “What can the user cancel?” for the release check because it asks whether the decision still holds outside the ideal path. The work is ready to move when the artifact can explain the choice and the observed result supports product states aligned with the full ingestion path.
Validate before session creation
The server should check authorization, quota, declared length, metadata limits, allowed types, and account scope before allocating a durable partial upload.
The practical review starts here:
- Who may upload?
- How large may it be?
- Which metadata is trusted?
- What quota is reserved?
Those questions keep accepting any partial file then validating at completion from becoming the default. I would capture the decision in an upload-creation validation contract, then use it while the work is still cheap to change. For recoverable large-file ingestion, the artifact should make ownership, constraint, and next action visible without requiring a private explanation.
Success would look like bounded resource and abuse exposure. If I cannot point to that evidence, I have a direction, not a finished decision.
The implementation move is to make an upload-creation validation contract part of the working surface. I would use it to answer “Who may upload?” while scope is still flexible, and “How large may it be?” before code or content becomes expensive to unwind. During QA, “Which metadata is trusted?” and “What quota is reserved?” become concrete checks rather than discussion prompts. That sequence turns recoverable large-file ingestion into something the team can operate and gives me a specific outcome to report: bounded resource and abuse exposure.
- UploadingBytes are moving
Progress reflects server-acknowledged offset, current connectivity, pause capability, and remaining size estimate.
- UploadedTransfer is durable
The server holds the expected byte count, but scanning, transcoding, extraction, or import may still be pending.
- ReadyProduct result exists
Post-processing succeeded, the new object is visible, and any partial-session cleanup or source replacement is complete.
Store sessions independently
An upload record should track owner, expected and current length, storage location, metadata, creation and expiry, status, checksum state, and processing reference.
Before implementation, I would answer:
- What identifies the session?
- Where are partial bytes stored?
- How is offset updated atomically?
- When does it expire?
The artifact is a durable upload-session schema. Its job is to expose the tradeoff early enough that design, engineering, support, or product can disagree with something concrete. The common trap is using a temporary file name as the whole state model; it moves uncertainty downstream and makes the final interface carry a problem the system never resolved.
For me, the useful receipt is recoverable ownership and cleanup. That connects a tus-compatible upload session whose server-owned offset makes interruption and continuation explicit to an observable result instead of a process claim.
I would test this with one typical case and one boundary case. The typical case should make “What identifies the session?” easy to answer. The boundary should force a decision about “Where are partial bytes stored?” and “How is offset updated atomically?.” I would record both in a durable upload-session schema, including the part that stayed unresolved after the first pass. The final check, “When does it expire?,” is where the artifact earns its place: it either supports recoverable ownership and cleanup, or it shows exactly why another iteration is needed.
Implement atomic offset updates
The server must compare the request offset with durable state, append the chunk, and advance offset without two writers corrupting the session.
I would use these prompts during the working review:
- Can PATCH requests race?
- When are bytes durable?
- How is mismatch returned?
- What if storage succeeds but metadata fails?
If the team slips into updating progress before the chunk is committed, the product can still look complete while its operating rule stays ambiguous. I would make a locked or conditional append operation the shared reference and keep it small enough to update as evidence changes.
The standard is one authoritative byte boundary. That tells me whether the decision helped the product, not merely whether the document was completed.
The working sequence is small: draft a locked or conditional append operation, review it against “Can PATCH requests race?,” implement the narrowest useful path, and then return with evidence for “When are bytes durable?.” I would use “How is mismatch returned?” to inspect product consequence and “What if storage succeeds but metadata fails?” to decide whether the result is stable enough to ship. This keeps updating progress before the chunk is committed visible as a known risk and makes one authoritative byte boundary the release receipt rather than a hopeful conclusion.
| Signal | Decision | Working note |
|---|---|---|
| Offset | Client and server disagree | Trust the server, resend only from its offset, and never append bytes based on local progress alone. |
| Identity | File no longer matches | Fingerprint, size, metadata, or selected file changed; require a new session instead of corrupt continuation. |
| Session | Expired or unauthorized | Renew authority when safe, or create a new upload while explaining what happened to the partial object. |
Persist a safe client fingerprint
The browser can map a selected file's stable-enough fingerprint to an upload URL, while recognizing that name and size alone may collide.
I would pressure-test that decision with four questions:
- Which file properties exist?
- Is content hashing affordable?
- How long is mapping retained?
- Does account identity scope it?
The failure mode here is resuming any same-named file into an old session. In large browser uploads over unstable mobile and office networks where progress, retry, duplicate creation, partial bytes, authentication expiry, checksum failure, cancellation, server cleanup, and post-upload processing affect whether user work arrives, that can hide the exact boundary a reviewer or teammate needs to understand. My working artifact would be a local upload fingerprint record. I want it close enough to the implementation that it can change the work, not created afterward to decorate the story.
The result I would look for is continuation only when file identity is credible. That is a narrower claim than saying the whole system improved, but it is also one I can verify and defend.
In practice, I would put a local upload fingerprint record beside the question “Which file properties exist?” before the first implementation review. The next pass would use “Is content hashing affordable?” to test the boundary, then “How long is mapping retained?” to expose the state most likely to be missed. I would keep “Does account identity scope it?” for the release check because it asks whether the decision still holds outside the ideal path. The work is ready to move when the artifact can explain the choice and the observed result supports continuation only when file identity is credible.
Reconcile with HEAD
Before resuming, ask the server for the durable offset and update client progress rather than assuming the last locally observed request completed.
The practical review starts here:
- Is the session reachable?
- What offset is durable?
- Has it expired?
- Does length still match?
Those questions keep continuing from the last progress event from becoming the default. I would capture the decision in a resume preflight, then use it while the work is still cheap to change. For recoverable large-file ingestion, the artifact should make ownership, constraint, and next action visible without requiring a private explanation.
Success would look like correct recovery after ambiguous interruption. If I cannot point to that evidence, I have a direction, not a finished decision.
The implementation move is to make a resume preflight part of the working surface. I would use it to answer “Is the session reachable?” while scope is still flexible, and “What offset is durable?” before code or content becomes expensive to unwind. During QA, “Has it expired?” and “Does length still match?” become concrete checks rather than discussion prompts. That sequence turns recoverable large-file ingestion into something the team can operate and gives me a specific outcome to report: correct recovery after ambiguous interruption.
Handle authentication renewal
Upload URLs need authorization on every operation, and long transfers require a renewal path that does not expose permanent tokens or orphan valid sessions.
Before implementation, I would answer:
- How is each request authorized?
- Can credentials expire mid-upload?
- Who may resume?
- How is ownership revoked?
The artifact is an upload-session authorization lifecycle. Its job is to expose the tradeoff early enough that design, engineering, support, or product can disagree with something concrete. The common trap is embedding a long-lived bearer secret in the upload URL; it moves uncertainty downstream and makes the final interface carry a problem the system never resolved.
For me, the useful receipt is secure continuation across long transfers. That connects a tus-compatible upload session whose server-owned offset makes interruption and continuation explicit to an observable result instead of a process claim.
I would test this with one typical case and one boundary case. The typical case should make “How is each request authorized?” easy to answer. The boundary should force a decision about “Can credentials expire mid-upload?” and “Who may resume?.” I would record both in an upload-session authorization lifecycle, including the part that stayed unresolved after the first pass. The final check, “How is ownership revoked?,” is where the artifact earns its place: it either supports secure continuation across long transfers, or it shows exactly why another iteration is needed.
Design truthful progress and controls
Show server-acknowledged bytes, connection and pause state, retry behavior, and the distinction between transfer and processing.
I would use these prompts during the working review:
- Which offset drives percent?
- Can pause be real?
- What does retry repeat?
- When is the file usable?
If the team slips into animating to 100 percent before the server commits, the product can still look complete while its operating rule stays ambiguous. I would make an uploading/uploaded/processing/ready UI matrix the shared reference and keep it small enough to update as evidence changes.
The standard is progress users can trust. That tells me whether the decision helped the product, not merely whether the document was completed.
The working sequence is small: draft an uploading/uploaded/processing/ready UI matrix, review it against “Which offset drives percent?,” implement the narrowest useful path, and then return with evidence for “Can pause be real?.” I would use “What does retry repeat?” to inspect product consequence and “When is the file usable?” to decide whether the result is stable enough to ship. This keeps animating to 100 percent before the server commits visible as a known risk and makes progress users can trust the release receipt rather than a hopeful conclusion.
Expire and clean partial data
Abandoned sessions need a retention policy, quota release, storage deletion, audit behavior, and protection against cleanup racing an active PATCH.
I would pressure-test that decision with four questions:
- How long are partials kept?
- Who can terminate?
- How does cleanup claim a session?
- What evidence remains?
The failure mode here is keeping partial files forever or deleting by age alone. In large browser uploads over unstable mobile and office networks where progress, retry, duplicate creation, partial bytes, authentication expiry, checksum failure, cancellation, server cleanup, and post-upload processing affect whether user work arrives, that can hide the exact boundary a reviewer or teammate needs to understand. My working artifact would be an upload expiry and garbage-collection job. I want it close enough to the implementation that it can change the work, not created afterward to decorate the story.
The result I would look for is bounded storage without active-session loss. That is a narrower claim than saying the whole system improved, but it is also one I can verify and defend.
In practice, I would put an upload expiry and garbage-collection job beside the question “How long are partials kept?” before the first implementation review. The next pass would use “Who can terminate?” to test the boundary, then “How does cleanup claim a session?” to expose the state most likely to be missed. I would keep “What evidence remains?” for the release check because it asks whether the decision still holds outside the ideal path. The work is ready to move when the artifact can explain the choice and the observed result supports bounded storage without active-session loss.
Test at byte boundaries
Verification should interrupt before and after chunk commit, repeat PATCH, race writers, mismatch offsets, expire auth, change files, corrupt checksums, cancel, and fail processing.
The practical review starts here:
- Can bytes duplicate?
- Can offset move backward?
- Does resume choose the right file?
- Are transfer and processing failures distinct?
Those questions keep testing one small file on localhost from becoming the default. I would capture the decision in a protocol-level upload failure suite, then use it while the work is still cheap to change. For recoverable large-file ingestion, the artifact should make ownership, constraint, and next action visible without requiring a private explanation.
Success would look like evidence that large user work reaches the product intact. If I cannot point to that evidence, I have a direction, not a finished decision.
The implementation move is to make a protocol-level upload failure suite part of the working surface. I would use it to answer “Can bytes duplicate?” while scope is still flexible, and “Can offset move backward?” before code or content becomes expensive to unwind. During QA, “Does resume choose the right file?” and “Are transfer and processing failures distinct?” become concrete checks rather than discussion prompts. That sequence turns recoverable large-file ingestion into something the team can operate and gives me a specific outcome to report: evidence that large user work reaches the product intact.
What I would show in the work
The public version needs evidence from the work itself. For this topic, the first five artifacts I would reach for are:
- an end-to-end upload state model
- an upload-creation validation contract
- a durable upload-session schema
- a locked or conditional append operation
- a local upload fingerprint record
I would not publish all five at equal weight. One should orient the reader, one should reveal the hardest tradeoff, and one should prove the result. The others can live in a downloadable note or appear as supporting frames. That edit matters because a tus-compatible upload session whose server-owned offset makes interruption and continuation explicit becomes harder to understand when every process detail is treated as equally important.
I would also show one rejected direction. The useful version is specific: which option looked attractive, which constraint made it wrong, and what evidence supported the narrower choice. That gives an engineering manager something real to question and keeps the case study from reading like the final answer was obvious from the beginning.
# POST create upload of N bytes Tus-Resumable, Upload-Length, validated metadata; response Location and optional Upload-Expires.
# HEAD discover durable position Response Upload-Offset and Upload-Length; client updates visible progress before sending another byte.
# PATCH continue at exact offset Content-Type application/offset+octet-stream; reject mismatched offset; commit chunk then return new Upload-Offset.
Resource path
The practical follow-up I would build is a tus upload starter with creation request, upload URL, offset HEAD, PATCH chunks, metadata validation, auth renewal, fingerprint persistence, progress UI, checksum option, termination, expiry, cleanup, processing states, and failure tests. I am treating that as a resource backlog item, not pretending the adjacent downloads below are the same artifact. The related cards cover useful pieces of the workflow today; this specific file should only be published when its examples, fields, and instructions are complete.
The first version should stay concise: context, constraint, decision, evidence, owner, and follow-up. Its value would come from helping someone repeat this exact review, not from adding another generic PDF to the site.
Review checklist
The article-specific review questions are:
- When does an object exist?
- Who may upload?
- What identifies the session?
- Can PATCH requests race?
- Which file properties exist?
- Is the session reachable?
- How is each request authorized?
- Which offset drives percent?
- How long are partials kept?
- Can bytes duplicate?
I would add two editorial checks before publishing: can a recruiter find the point in the first minute, and can an engineer trace at least one claim to an implementation or production receipt? If either answer is no, the article needs another edit.
Implementation notes
For recoverable large-file ingestion, I would write the implementation note before polish. It would name the changed surface, source of truth, owner, failure boundary, and verification path. Those details prevent the principle from floating above the actual code or operational workflow.
The proof signals I care about are specific to this article:
- correct recovery after ambiguous interruption
- secure continuation across long transfers
- progress users can trust
- bounded storage without active-session loss
- evidence that large user work reaches the product intact
I would choose two or three of those signals for the first release rather than instrumenting everything. The strongest pair usually combines one direct behavior check with one operating check: a route and a data query, a keyboard path and a support state, a handler replay and a reconciliation result, or a migration count and a rendered screen.
The follow-up belongs in the note before shipping. It should say what remains temporary, what evidence would trigger another pass, and who owns that decision. That is how the first version stays intentionally narrow without making the boundary invisible.
Case-study packaging
I would structure the case-study version around the four visual lessons already established:
- Resumable upload is a session protocol.
- Product progress has distinct stages.
- Resume can fail for understandable reasons.
- Core requests keep byte ownership explicit.
The opening frame explains the product pressure. The middle two show the decision moving through the system. The last frame is the receipt: what was checked, what held, and what remained unresolved. That order lets the reader move from product judgment into implementation detail without reconstructing the whole project first.
I would include one caveat tied to large browser uploads over unstable mobile and office networks where progress, retry, duplicate creation, partial bytes, authentication expiry, checksum failure, cancellation, server cleanup, and post-upload processing affect whether user work arrives: a data limit, rollout boundary, unsupported state, external dependency, or result that is still directional. A precise caveat makes the evidence easier to trust because it shows where the claim stops.
The final test is whether the page creates a better conversation. If the artifact helps someone ask a sharper question about product judgment, implementation detail, or release proof in a live interview, it belongs in the story.
Interview angle
In an interview, I would explain this through a tus-compatible upload session whose server-owned offset makes interruption and continuation explicit. The story should start with the product pressure, then move into the system constraint, the artifact, and the proof. That order keeps the answer grounded. It also gives the interviewer several places to go deeper: data, frontend architecture, design systems, support, migration, accessibility, or release process.
The strongest version of the answer includes a tradeoff. I want to be able to say what I chose, what I left alone, and how I knew the work helped. That is more credible than presenting every project as a clean win.
The hiring signal
A resumable upload flow is a hiring signal because it shows I can join an HTTP protocol, browser persistence, storage operations, security checks, and honest product progress into one recoverable journey.
That is the level I want this site to communicate. The work should show taste, but it should also show operating judgment. It should make me look like someone who can enter a real product system, understand the messy middle, ship the useful version, and leave enough proof for the next person to trust it.
Use this after reading.
Practical downloads and templates that turn the article into something you can bring into a product review, implementation pass, or agent workflow.
Agent-Ready API Spec Template
An OpenAPI and Postman starter template for APIs that AI agents can discover, call, and recover from safely.
Front-End State Recipes
Reusable recipes for optimistic actions, loading, empty, error, data-transition, and disabled-control states.
UI PR Risk Review Checklist
A merge-readiness checklist for product intent, states, accessibility, visual durability, and UI implementation risk.