Agent Wranglers

Files and uploads Recommended

Make large uploads resumable

Let any upload over 100 MB, or any upload from a phone, continue from the last received byte after a dropped connection.

How to do it

Use an open protocol rather than your own. The tus protocol 1.0 is stable and has clients and servers for most languages. The IETF draft for resumable uploads (draft-ietf-httpbis-resumable-upload, version 14 in October 2026) is still a draft, not an RFC. It adds the 104 interim response and the Upload-Offset and Upload-Complete headers. Object storage multipart uploads also work, with parts of at least 5 MiB and at most 10,000 parts on S3. Retry with growing waits, such as 0, 1, 3 and 10 seconds. Set a chunk size only when a proxy limits the body size.

Example

import * as tus from 'tus-js-client';

export function uploadSiteSurvey(file, token) {
  const upload = new tus.Upload(file, {
    endpoint: 'https://uploads.example.com/files/',
    headers: { Authorization: `Bearer ${token}` },
    retryDelays: [0, 1000, 3000, 10000],
    metadata: { filename: file.name, filetype: file.type },
  });
  upload.findPreviousUploads().then(previous => {
    if (previous.length > 0) upload.resumeFromPreviousUpload(previous[0]);
    upload.start();
  });
}
from tusclient import client

def upload_site_survey(path: str, token: str) -> str:
    tus = client.TusClient("https://uploads.example.com/files/", headers={"Authorization": f"Bearer {token}"})
    uploader = tus.uploader(path, retries=5, retry_delay=3)
    uploader.upload()
    return uploader.url

How to check

Start a 500 MB upload, cut the network at 50 percent and reconnect. The upload finishes without sending the first half again, and the stored file's SHA-256 matches the original.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers api design playbook: https://agentwranglers.se/playbook/api-design/files-and-uploads/resumable-uploads.