All posts
Internet Fundamentals

File Uploads Done Right: Presigned URLs, Limits, and Not Proxying Through Your Server

By

October 26, 2026

5 min read

Uploading through your API runs into payload limits (6 MB for synchronous Lambda, 10 MB for API Gateway), ties up servers and pays for the bytes twice. Letting the browser upload straight to S3 with a presigned URL avoids all three. How it works, enforcing size and type, scanning for malware, and serving files back privately.

Internet Fundamentals
File Uploads
Amazon S3
Presigned URLs
Security

The first upload feature usually posts the file to the app server, which writes it to storage. It works until files or users grow. Serverless APIs refuse large bodies outright: synchronous Lambda invocations accept 6 MB, API Gateway 10 MB.

The presigned URL pattern

  1. The client asks your API to upload, saying what (name, type, size).

  2. Your API checks the user, chooses the object key itself (for example users/<id>/<random>.jpg, never the client's file name as a path) and returns a presigned URL valid for a few minutes.

  3. The browser uploads directly to S3 with it.

  4. An S3 event, or a call from the client, records the upload and starts any processing.

Want a second opinion on this for your system?

Book a free 30-minute call. You'll leave knowing what we'd do first and roughly what it costs, whether or not you hire us.

Presigned PUT or POST

Presigned PUT

Presigned POST

Simplicity

One URL, one request

A form with policy fields

Size limit

Sign the Content-Length where your SDK supports it, or check after upload

Enforced by S3 with a content-length-range condition

Content type

Can be part of the signature

Can be constrained in the policy

Large files

Multipart upload with a presigned URL per part

Up to 5 GB in one request

Rules worth following

  • Keep the bucket private. New buckets block public access by default; serve files through CloudFront with origin access control, or with short-lived presigned GET URLs.

  • Keep upload URLs short-lived. URLs signed with temporary credentials stop working when those credentials expire, whatever expiry you set.

  • Do not trust the extension or the browser's content type. Check the file's real type after upload, before processing or displaying it.

  • Scan uploads before other users can download them. GuardDuty Malware Protection for S3 scans new objects and can tag the result.

  • Serve user files from a different domain from your app, so a malicious HTML or SVG file cannot run script on your origin.

  • Add a lifecycle rule that removes abandoned uploads and incomplete multipart uploads.

hoolco Monthly Review

Once a month: what changed in tech that month and what it means for you, from cloud and AI to security and the tools you build with. Every item links to its source. No sales pitch, unsubscribe in one click.

As of October 26, 2026. Provided as is, for general information, and accurate to the best of our knowledge on the date shown. Not legal, compliance, tax, financial or other professional advice. Prices, limits and vendor services change; check current vendor documentation before relying on anything here. Terms of use.