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.
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 client asks your API to upload, saying what (name, type, size).
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.
The browser uploads directly to S3 with it.
An S3 event, or a call from the client, records the upload and starts any processing.
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.
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.
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.
Book a free 30-minute call about it. Bring your setup and your bill; you'll leave knowing what we'd do first and roughly what it costs, whether or not you hire us.
Or keep reading
Which API Keys Are Safe in Your Frontend? A Field Guide for Apps Built Fast
Everything in a browser bundle or mobile app is public, including any variable your framework inlines at build time. Which keys are designed to be public and what actually protects you when they are, which must never ship, and what to do in the first hour after one leaks.
Read
Row-Level Security: The Check Between Your Users' Data and Everyone Else
Apps on Supabase, Firebase and similar platforms let the browser talk to the database directly. That is fine only if the database enforces who sees what, because anyone can call the same API without your UI. How row-level security works, the gaps that catch people (views, functions, storage), and a ten-minute test.
Read
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.