SyncTrix logoSyncTrix
All articles
Platform10 min read

Large file uploads keep failing and users are losing work

Uploads fail at proxy limits, request timeouts and memory ceilings. Routing files through your application server is the root cause of most of them.

By Marcus Hale
Large file uploads keep failing and users are losing work

Small files upload fine. Anything substantial fails - sometimes with a 413, sometimes a timeout, sometimes the connection simply drops after several minutes. Each symptom points at a different limit in the chain between browser and storage, and every component in that chain has its own default that was not chosen with your files in mind.

01Identify which limit you are hitting

The error identifies the layer. A 413 means a proxy or web server rejected the body size. A timeout after a consistent duration means a request timeout somewhere in the chain. A process restart during upload suggests the file is being buffered into memory. Failures only on slow connections point at an idle or overall request timeout.

Each has its own configuration in its own component, and raising one without the others simply moves the failure. Enumerate the full path - browser, CDN, load balancer, reverse proxy, application server, framework - and check the relevant limit at each hop.

LayerTypical limitSymptom
CDN or WAFBody size cap413 before reaching origin
Load balancerIdle and request timeoutConnection dropped mid-upload
Reverse proxyMax body size, read timeout413 or gateway timeout
Application serverRequest size and timeoutRejected or truncated
FrameworkMultipart memory thresholdMemory spike or OOM
Storage APISingle-request object limitFails above a size threshold
Limits along the upload path

02Stop routing files through your application

The durable fix is to remove the application server from the data path. Issue a presigned URL and have the browser upload directly to object storage. Your server handles authorisation and records metadata; the bytes never traverse it, so its limits, timeouts and memory become irrelevant.

This also removes a scaling constraint. Uploads no longer consume application server connections and memory, so a few users uploading large files cannot degrade the experience for everyone else - a failure mode that is otherwise easy to trigger and hard to diagnose.

03Multipart uploads survive interruption

A single-request upload of a large file over an unreliable connection restarts from zero on any failure. Multipart upload splits the file into chunks uploaded independently, so a failed chunk is retried alone and progress is preserved.

This is what makes resumable uploads possible. On a mobile connection that drops periodically, the difference between resuming and restarting determines whether the upload ever completes at all.

ApproachHandles interruptionServer load
Through the application serverNoHigh - buffers and connections
Presigned single requestNoNone during transfer
Presigned multipartYes, per chunkNone during transfer
Resumable protocolYes, with offset trackingMinimal coordination
Approaches compared

04Validate after upload, not before

With direct uploads, the file arrives in storage without your application inspecting it. Validation must therefore happen after arrival: check the actual content type by inspecting the file rather than trusting the declared one, enforce size limits in the presigned policy, and scan where the threat model requires it.

Upload to a quarantine location and move to the permanent one only after validation passes. This prevents unvalidated content being served and gives a clear place to discard rejected files.

05Show progress and report failures clearly

Users abandon uploads that appear frozen. A progress indicator driven by actual bytes transferred, with an estimated time remaining, prevents the retries that cause duplicate uploads and additional load.

Report failures specifically. A message stating the file exceeds the maximum size, or that the connection was interrupted and the upload can be resumed, lets the user act. A generic failure message produces a support ticket and a repeated attempt that fails identically.

Topics

large file upload fails413 request entity too largeupload timeout nginxpresigned url upload s3multipart upload implementation

Marcus Hale

Lead Architect · SyncTrix

Writes about the engineering decisions behind production systems - architecture, delivery and the trade-offs that only show up at scale.

Building something like this?

SyncTrix engineers AI, SaaS, platform and cloud systems for enterprises and high-growth teams. Tell us what you're shipping and we'll scope it with you.

Talk to an engineer