Skip to content
API Design Learn/Production REST II: Correctness & Scale
Browsing as a guest. Sign in to save your progress and earn XP as you complete chapters.

File Upload APIs

7 min read

You'll learn to

  • -Design a presigned-URL upload flow so large files bypass the API server entirely
  • -Know when multipart/resumable upload is needed instead of a single presigned PUT

Routing a large file upload through the same API server that handles ordinary JSON requests works for small files, but it wastes server resources holding open connections and buffering bytes it doesn't actually need to process - the presigned-URL pattern lets the client upload directly to storage, with the API server only ever handling the metadata.

The Presigned URL Flow

Step 1: ask the API for permission to upload, not the upload itself
POST /uploads
{"filename": "report.pdf", "content_type": "application/pdf"}

HTTP/1.1 201 Created
{
  "upload_url": "https://storage.example.com/bucket/abc123?signature=...",
  "upload_id": "upl_501",
  "expires_at": "2026-08-07T10:15:00Z"
}
Step 2: the client uploads directly to storage - the API server is never in this path
PUT https://storage.example.com/bucket/abc123?signature=...
Content-Type: application/pdf

[binary file data]

HTTP/1.1 200 OK

The `upload_url` is a time-limited, cryptographically signed URL granting temporary write access to one specific storage location - the signature encodes exactly what's permitted (this bucket path, this content type, until this expiry) without requiring the client to have any broader storage credentials. The API server's only job is issuing that signed URL and recording the upload's metadata; the actual bytes never pass through it.

Multipart and Resumable Uploads for Large Files

A single PUT works fine up to some reasonable size, but for very large files (video, large datasets), a single failed connection partway through means restarting the entire upload from byte zero - multipart upload splits the file into chunks, each uploaded (and retried) independently, with a final step that tells the storage layer to assemble the chunks into the complete file. This makes a transient failure on one chunk cheap to retry, instead of expensive to restart from scratch.

A presigned URL with too generous an expiry, or scoped too broadly (write access to an entire bucket instead of one specific object), is a real security exposure - the whole value of the pattern depends on each URL being narrowly scoped and genuinely time-limited.

Interview Signal is part of Pro

See a real weak answer next to a real strong one for this exact topic.

Quiz is part of Pro

Test what you just read with a short quiz, and bank the XP.

Ready to Build This?

Design The File Vault in the API Design Lab's Production Patterns act.

ScaleDojo Logo
Initializing ScaleDojo