Skip to content

Drive uses TUS resumable uploads via a sidecar server, not Django multipart

The Drive feature (file management for community storage) uses the TUS protocol for resumable uploads, served by a standalone tusd server process. Django only indexes files via a completion webhook — it never handles the upload bytes directly.

Considered Options

  • Django multipart upload: Standard request.FILES handling. Simple, no external dependency. Unusable for large files — no resume capability, ties up a Django worker for the entire upload duration, hard limits on upload size from reverse proxies.
  • Direct-to-S3 upload: Generate presigned URLs client-side. Avoids Django processing bytes. No resume capability, complex client-side chunking logic needed for large files, and no progress tracking.
  • TUS via sidecar (chosen): A tusd process listens on a separate port (default :1080) and writes uploaded files directly to the storage backend under the drive/ prefix. When a file completes, tusd POSTs a webhook to Django's DriveTusWebhookView with file metadata. Django creates a DriveFile record and moves the file to its final location.

Why TUS was chosen

  • Built-in resume: uploads survive network drops, browser crashes, and page navigation.
  • Chunked uploads: tusd handles chunk assembly transparently — no custom chunking logic needed.
  • Decoupled from Django workers: the web process never blocks on upload I/O.
  • Works with any storage backend: tusd writes to S3, local FS, or GCS via a single -store flag.

Consequences

  • Operationally heavier: requires running and monitoring a tusd process alongside Django.
  • Webhook secret must be shared between tusd and Django (DRIVE_TUS_WEBHOOK_SECRET).
  • The DriveFile.storage_key field stores the path tusd wrote the file to; Django may rename/move it during webhook processing.
  • Trashed files are soft-deleted (is_trashed=True) — the actual storage object is not removed until permanent deletion is explicitly triggered.

Strum — Documentação.