title File Upload Flow actor User participant Browser participant "Upload API" as API participant "Storage Service" as S3 participant Database User->Browser: Select file Browser->API: POST /upload/init API-->Browser: Pre-signed upload URL Browser->S3: PUT file (direct upload) S3-->Browser: Upload complete Browser->API: POST /upload/confirm API->S3: Verify file exists S3-->API: File metadata API->Database: Save file record API-->Browser: 200 OK + file URL Browser-->User: Show uploaded file
What this diagram shows
This sequence diagram models the presigned URL upload pattern — the standard way to handle file uploads in cloud-native applications. Rather than routing the file through your API server (which wastes bandwidth and compute), the client uploads directly to the storage service using a short-lived, pre-authorized URL your server generates.
The two-phase design (init → upload → confirm) is critical: the confirm step lets your backend verify the file actually arrived in storage and save the metadata to your database. Skipping the confirm step would leave your database out of sync with storage.
Step-by-step flow breakdown
- User selects file — the browser's file picker opens; the user picks a file. No network call yet.
- POST /upload/init — the browser calls your API with the filename, content type, and size. Your API validates the request (auth, file type allowlist, size limit) before generating the URL.
- Presigned URL returned — your API calls AWS
s3.getSignedUrl('putObject', {...})and returns the URL to the browser. The URL encodes the bucket, key, content type, and expiry (typically 15 minutes) in the query string. - PUT directly to S3 — the browser fetches the presigned URL with the file as the body. This call goes directly from the browser to S3 — your server is not in the path. Upload progress is shown from this response.
- POST /upload/confirm — the browser tells your API the upload succeeded (sending the key/filename). This step is essential — it's how your backend knows the file is in storage.
- API verifies file exists — your API calls
s3.headObjectto confirm the file is in the bucket and retrieves size and content type from S3's response. - File record saved — your API inserts a row in the database with the S3 key, URL, size, MIME type, owner ID, and upload timestamp.
- File URL returned — the browser receives the CDN URL for the uploaded file and displays it to the user.
When to use a file upload sequence diagram
- Implementation docs — show frontend devs exactly which API calls to make and in what order, including the two-phase confirm step
- Security review — confirm the presigned URL is generated server-side (AWS keys never exposed to the browser) and has a short expiry
- CDN and CORS planning — map out where the S3 bucket's CORS config needs to allow
PUTfrom your domain - Debugging upload failures — determine which step failed: presigned URL generation, the PUT itself, or the confirm call
Common variations
Multipart upload for large files
For files over ~100MB, use S3 multipart upload. Add a step to initialize the multipart upload, generate presigned URLs per part, upload parts in parallel, then complete the multipart upload with the ETags.
Upload without the confirm step (simpler but fragile)
Some implementations skip the confirm step and assume the upload succeeded if the PUT returned 200. This is simpler but risks database records pointing to files that never actually uploaded. The confirm pattern is safer.
Image processing pipeline
After Save file record, add API->Queue: Process image and a background worker that reads from S3, resizes, generates thumbnails, and writes back. The user sees the original immediately; thumbnails appear asynchronously.
Virus scanning
Between the PUT and confirm steps, add a scanning service: S3->Scanner: Trigger scan (S3 event) and Scanner-->API: Scan result. The file is quarantined until the scan completes.
Related sequence diagram examples
Frequently asked questions
What is a presigned URL for file uploads?
A presigned URL is a temporary, signed URL generated by your backend using AWS (or GCS/Azure) credentials. It authorizes the client to PUT one specific file to one specific storage location, with an expiry time. Your AWS keys never reach the browser.
Why upload directly to S3 instead of through your server?
Three reasons: speed (file goes browser→S3, not browser→server→S3), cost (no server egress bandwidth for large files), and scalability (large uploads don't hold server connections or memory).
Is the confirm step mandatory?
Not technically — but practically yes. Without confirming, your database has no record of the file. If the upload silently fails or is interrupted, you'd have orphaned database entries or missing files. Always confirm and verify with a headObject call before saving to your database.
Can I edit this file upload diagram?
Yes — click Open in Editor. Add multipart upload, virus scanning, image processing, or adapt for GCS/Azure Blob. Export as PNG, SVG, or Mermaid. Free, no account required.