Why Large Files Crash Browser Tabs (and How Streaming Fixes It)

Memory limits, Blob buffering, the File System Access API and backpressure: what it takes to move a file bigger than your RAM through a browser.

By ShareDrop.org Engineering · Published 2026-02-06 · Last verified 2026-08-08 · Tested against: 64 KiB chunking with 8 MiB/1 MiB backpressure watermarks

Ask anyone who has built browser file transfer: small files are trivial, and large files are where tabs die. The crashes trace back to one root cause — buffering an entire file in memory — showing up in three different places.

Failure point 1: reading

The naive approach reads the whole file into an ArrayBuffer. A 4 GB video on a laptop with 8 GB of RAM ends the story right there. The fix is streaming: file.stream() yields chunks on demand, so the amount of file in memory at any moment stays constant regardless of file size.

Failure point 2: sending faster than the network

A disk reads at hundreds of MB/s; a typical uplink carries a fraction of that. Push chunks into a WebRTC data channel as fast as you read them and the channel's internal send buffer absorbs the difference — growing until the tab is killed. The standard fix is backpressure via bufferedAmount: pause reading when the buffered amount crosses a high-water mark, resume on the bufferedamountlow event. ShareDrop.org pauses at 8 MiB and resumes at 1 MiB, so sender memory stays bounded whether the file is 10 MB or 100 GB, and whether the link is fiber or hotel Wi-Fi.

Line chart of sender bufferedAmount over time with backpressure: the buffer rises quickly to the 8 MiB high-water mark, reading pauses, the buffer drains at network speed to the 1 MiB low-water mark, and reading resumes — a sawtooth that never exceeds 8 MiB
Sender-side bufferedAmount over time with ShareDrop.org's production watermarks. Disk fills the buffer in moments; the network drains it slowly; the sawtooth never exceeds 8 MiB no matter how large the file is.

Failure point 3: receiving

The receiver has the hardest problem: browsers historically offered no way to write a download progressively — you accumulated Blobs in memory and triggered a download at the end. That works until it doesn't, and “doesn't” arrives at different sizes on different devices. Two paths exist today:

Receiving browserSaving pathMemory while receivingPractical limit
Chrome / Edge (desktop)Streamed to disk (File System Access API)Flat — a few MiB of chunk bufferDisk space
Firefox (desktop)In-memory assemblyGrows with the file512 MB, enforced before the transfer starts
Safari (macOS / iOS)In-memory assemblyGrows with the file512 MB, enforced before the transfer starts
Mobile browsers in generalIn-memory assemblyGrows with the file512 MB, enforced before the transfer starts

Chunk size: smaller than you might expect

Data channel messages cannot be arbitrarily large — implementations negotiate a maximum message size, and large messages block the channel. ShareDrop.org uses 64 KiB chunks with a small binary header (transfer ID, file ID, chunk index), which keeps messages well within every browser's limits and gives fine-grained progress and incremental hashing for free. Chunking is also what makes resume-after-disconnect possible: the receiver reports the last chunk written to disk, and the sender continues from there instead of starting over.

The numbers, and how they are verified

Takeaways when evaluating any transfer tool

Standards referenced