11. Object / Blob Storage
11.4 How do uploads work with presigned URLs?
At the cloakroom: Instead of the host carrying every guest's coat to the cloakroom personally, the host writes a signed note: "allow this guest to leave one coat at hook 214, valid for the next ten minutes". The guest takes the coat there directly.
In the system: The naive design streams every upload through your API servers: the phone sends 8 MB to your server, which sends it on to storage. Your servers spend their time and bandwidth shuttling bytes.
A presigned URL lets the client talk to storage directly, with permission your backend grants:
Figure: your API handles a tiny request; the heavy bytes go straight to storage.
- The app asks your API: "I want to upload a review photo."
- Your API checks the user is allowed, picks the key (
reviews/7/981.jpg), and creates a presigned URL: a normal storage URL plus a signature made with your secret credentials, covering the method (PUT), the key, and an expiry time (say 10 minutes). - The app uploads the bytes directly to storage with that URL.
- Storage tells your system the upload is done (an event notification), or the app tells your API.
- Your API saves the key and metadata in the database.
Downloads work the same way: the private e-book PDF is served by a short-lived presigned GET URL made only after checking the user bought it.
Security rules: the signature must cover everything that matters (method, key, expiry, and limits like content type or size where supported), so the URL can't be reused for another file, another action or a longer time (the Level 4 bug). Keep expiry short. On S3, presigned URLs signed with long-term credentials can last at most 7 days.
Memory code: "A signed note for one coat, one hook, ten minutes."