File size and performance limits, measured
What each tool actually handled, on a machine we describe in full, with the harness published so you can rerun it.
Home › Tools › File size and performance limits, measured
Every number on this page came from a run that actually happened on the machine described below. Where a combination was not tested, the cell says Not tested rather than carrying an estimate. This sweep is still in progress: 6 of the 35 that have a size ladder have been measured so far, and the rest are listed below with every cell marked Not tested. The tables are complete as a list of tools; they are not yet complete as a set of results.
QuickMerge does all of its work inside your browser. Nothing is uploaded, which means there is no server policy setting a maximum file size — the ceiling is your own hardware, your browser's memory model, and in several places a guard the tool page sets on itself. Those three are different things, and this page keeps them apart.
What follows is one machine, one sweep, on August 11, 2026. It is not a guarantee about your laptop. It is a floor and a shape: a tool that finished a given file on 4 cores with 15.7 GB of RAM will not do dramatically worse on a modern laptop, and where a tool refused, the table says which of the two ceilings it hit.
How this was measured
- Test dateAugust 11, 2026 (UTC)
- Operating systemUbuntu 24.04.4 LTS (linux 6.18.5-fc-v20, x64)
- CPUIntel(R) Xeon(R) Processor @ 2.80GHz — 4 cores
- Installed memory15.7 GB
- Chromium151.0.7922.34
- Firefox153.0
- WebKit26.5
- Browser modeHeadless, default flags, one fresh browser per run
- Playwright1.62.1
- Node.jsv22.22.2
- Per-run timeout180 seconds
- Library sourceslocal cache (scripts/measure/.engine-cache) — no network during the sweep
- Fixture seed1366773063
The harness drives the real tool pages the way a person does: it loads the page, waits for the processing library to arrive, puts a file into the file input, presses the button, and waits. Completion is detected by wrapping URL.createObjectURL before the page's own script runs, so the moment the tool produces its output blob is the moment the clock stops, and the blob's size is the recorded output size. Nothing about the page's markup is assumed.
Test files are generated from a fixed seed, so two runs feed the tools byte-identical inputs:
- PDF file size — A 10-page text PDF padded with one raw-RGB image XObject to reach the target size. Rungs: 1, 5, 10, 25, 50, 100, 250, 500 MB.
- PDF page count — Text-only pages with no images, so the variable is page count rather than bytes. Rungs: 10, 100, 500, 1000, 2500 pages.
- Image file size — Square RGB PNG of incompressible noise, stored uncompressed to hit the target size. Rungs: 1, 5, 10, 25, 50, 100 MB.
- Image pixel count — Square RGB PNG of a smooth gradient, so the file stays small and the variable is pixel count. Rungs: 1, 5, 10, 25, 50, 100 MP.
- Pasted or loaded text — ASCII words, one line of twelve per newline. Rungs: 1, 5, 10, 25, 50, 100 MB.
Each tool is walked up its ladder by binary search rather than one rung at a time, which finds the same answer — the largest fixture that finishes — in three or four runs instead of eight. A run that produces neither a result nor an error within 180 seconds is recorded as a timeout and left as a timeout. It is not retried until it passes.
The processing libraries (pdf-lib, pdf.js, Tesseract.js and the rest) are served from a local cache during the sweep instead of from their CDNs, so CDN latency cannot show up inside a processing time. The harness, the fixture generator and the raw results are all in the repository: scripts/measure, and the complete dataset is measurements.json.
Two different ceilings
When a tool stops working there are two quite different reasons, and most people meet the first one:
- The page refuses the file. 23 of QuickMerge's 49 tools check the file size before they start and reject anything above a number written into the page. That number is a product decision, not a measurement — it was chosen to stop people from locking up a phone. When you see “exceeds 50 MB”, you have hit a guard, not a wall.
- The browser gives up. Above the guard, the real limits are the JavaScript heap and the way these libraries work. Both pdf-lib and pdf.js load the entire document into memory as a single byte array; there is no streaming path. A browser tab that has to hold the source file, a parsed object graph of it, and the output at the same time is using several times the file's size in RAM.
The tables below report the guard where a tool has one, and what was measured underneath it.
PDF file size: what completed
Largest fixture each tool finished, per engine. “Time” and “What happens above” are the Chromium run — the engines agree on where the ceiling is far more often than they agree on how long it takes to get there.
| Tool | Chromium | Firefox | WebKit | Time at that size (Chromium) | Ceiling set by | What happens above |
|---|---|---|---|---|---|---|
| Merge PDF | 50 MB | 50 MB | 50 MB | 2.0 s | page limit | Refused by the page: “exceeds 50MB limit”. |
| Split PDF | 5.0 MB | 50 MB | 50 MB | 1.1 s | too slow | Still running after the 180-second cap, with no error shown. |
| Organize PDF | 50 MB | Not tested | 50 MB | 2.2 s | browser or engine | Failed: “File exceeds the 100MB limit. Split it first, then organize the parts.”. |
| Rotate PDF | 50 MB | 50 MB | 50 MB | 441 ms | page limit | Refused by the page: “File exceeds 100MB”. |
| Compress PDF | 100 MB | Not tested | 100 MB | 10.7 s | browser or engine | Failed: “File size must be less than 200MB.”. |
| PDF to Word | 50 MB | Not tested | Not tested | 973 ms | browser or engine | Failed: “File size must be less than 50MB.”. |
| PDF to JPG | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Redact PDF | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| PDF metadata | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Watermark PDF | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Remove PDF watermark | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Add page numbers | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Protect PDF | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Unlock PDF | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| OCR | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| PDF summarizer | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Smart file organizer | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Stamp generator | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
PDF page count: what completed
Largest fixture each tool finished, per engine. “Time” and “What happens above” are the Chromium run — the engines agree on where the ceiling is far more often than they agree on how long it takes to get there.
| Tool | Chromium | Firefox | WebKit | Time at that size (Chromium) | Ceiling set by | What happens above |
|---|---|---|---|---|---|---|
| Merge PDF | 2,500 pages | 2,500 pages | 2,500 pages | 1.5 s | Not tested | Completed the largest fixture tested — the ceiling is above this ladder. |
| Split PDF | 2,500 pages | 2,500 pages | 2,500 pages | 2.0 s | Not tested | Completed the largest fixture tested — the ceiling is above this ladder. |
| Organize PDF | 100 pages | Not tested | 100 pages | 4.7 s | browser or engine | Failed: “This PDF has 500 pages — the limit is 300. Split it first, then organize the parts.”. |
| Rotate PDF | 2,500 pages | 2,500 pages | 2,500 pages | 1.2 s | Not tested | Completed the largest fixture tested — the ceiling is above this ladder. |
| Compress PDF | 2,500 pages | Not tested | 1,000 pages | 2 min 42 s | Not tested | Completed the largest fixture tested — the ceiling is above this ladder. |
| PDF to Word | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| PDF to JPG | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Redact PDF | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| PDF metadata | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Watermark PDF | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Remove PDF watermark | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Add page numbers | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Protect PDF | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Unlock PDF | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| PDF summarizer | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Smart file organizer | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
Image file size: what completed
Largest fixture each tool finished, per engine. “Time” and “What happens above” are the Chromium run — the engines agree on where the ceiling is far more often than they agree on how long it takes to get there.
| Tool | Chromium | Firefox | WebKit | Time at that size (Chromium) | Ceiling set by | What happens above |
|---|---|---|---|---|---|---|
| Image to PDF | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| OCR | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Image converter | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| JFIF to JPG | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Compress image | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Resize image | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Crop image | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Remove image metadata | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Image to Excel | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Screenshot to Excel | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| QR code reader | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
Image pixel count: what completed
Largest fixture each tool finished, per engine. “Time” and “What happens above” are the Chromium run — the engines agree on where the ceiling is far more often than they agree on how long it takes to get there.
| Tool | Chromium | Firefox | WebKit | Time at that size (Chromium) | Ceiling set by | What happens above |
|---|---|---|---|---|---|---|
| Image to PDF | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| OCR | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Image converter | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| JFIF to JPG | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Compress image | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Resize image | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Crop image | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Remove image metadata | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Image to Excel | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Screenshot to Excel | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| QR code reader | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
Pasted or loaded text: what completed
Largest fixture each tool finished, per engine. “Time” and “What happens above” are the Chromium run — the engines agree on where the ceiling is far more often than they agree on how long it takes to get there.
| Tool | Chromium | Firefox | WebKit | Time at that size (Chromium) | Ceiling set by | What happens above |
|---|---|---|---|---|---|---|
| Text to PDF | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Text to Excel | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| QR code generator | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| JSON formatter | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Hash generator | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| Base64 encoder | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
| URL encoder | Not tested | Not tested | Not tested | Not tested | Not tested | Not tested |
Peak memory
Only Chromium exposes performance.memory to a page. Firefox and WebKit do not, so there is no peak-heap figure for them here and none has been carried across from the Chromium column — those measurements simply do not exist.
The last column is the ratio of peak heap to input size, which is the number worth remembering: it is roughly how much RAM a tool wants relative to the file you give it.
| Tool | Ladder | At this size | Peak JS heap | Heap ÷ input |
|---|---|---|---|---|
| Merge PDF | PDF file size | 50 MB | 9.5 MB | 0.2× |
| Merge PDF | PDF page count | 2,500 pages | 9.5 MB | 1.1× |
| Split PDF | PDF file size | 5.0 MB | 9.5 MB | 1.9× |
| Split PDF | PDF page count | 2,500 pages | 9.5 MB | 1.1× |
| Organize PDF | PDF file size | 50 MB | 9.5 MB | 0.2× |
| Organize PDF | PDF page count | 100 pages | 9.5 MB | 27.8× |
| Rotate PDF | PDF file size | 50 MB | 9.5 MB | 0.2× |
| Rotate PDF | PDF page count | 2,500 pages | 9.5 MB | 1.1× |
| Compress PDF | PDF file size | 100 MB | 9.5 MB | 0.1× |
| Compress PDF | PDF page count | 2,500 pages | 9.5 MB | 1.1× |
| PDF to Word | PDF file size | 50 MB | 9.5 MB | 0.2× |
Why the ceiling is where it is
The heap, not the disk. A browser tab gets a JavaScript heap of a few gigabytes at most, and on mobile far less. A 100 MB PDF is not 100 MB of memory once it is open: pdf-lib holds the original bytes, then a parsed object for every page, font and image inside it, then builds the output document alongside the input. Three to five times the file size is normal, and the tables above show the measured ratio for each tool.
WebAssembly memory is its own budget. The tools built on WebAssembly — the PDF encryption pair, and Tesseract for OCR — get a linear memory that grows in 64 KB pages and, on a 32-bit WASM build, cannot exceed 4 GB no matter how much RAM the machine has. Growing that memory means allocating a new, larger block and copying the old one into it, so a WASM tool's memory use spikes at exactly the moment it is running out.
Nothing here streams. Neither pdf-lib nor pdf.js has a streaming mode in the browser. The whole file is read into an ArrayBuffer before any work starts, which is why the size ladder finds a cliff rather than a slope: below the cliff everything is comfortable, and one rung above it the allocation fails outright.
Rasterising changes the arithmetic. Three tools — compress, redact, and PDF to image — render each page to a canvas before writing it back out. A canvas costs four bytes per pixel regardless of how simple the page is, so a full-page render at print resolution is tens of megabytes of memory per page, and page count matters more than file size.
The main thread is doing the work. Most of these tools run on the page's main thread, so while a large file is processing the tab is unresponsive. Nothing has crashed — the browser simply has no spare moment to repaint. On the timings above, anything past a few seconds is a frozen tab from the person's point of view.
What this page is not
The caveats here are not fine print; they are the reason the numbers are worth anything.
- One machine. Intel(R) Xeon(R) Processor @ 2.80GHz, 4 cores, 15.7 GB of RAM, on Ubuntu 24.04.4 LTS (linux 6.18.5-fc-v20, x64). A newer laptop will be faster. A phone will be very much slower, and will hit memory limits far below these.
- One run per combination. These are single measurements, not averages over repeated trials, and there are no error bars. Treat a difference of tens of percent between two engines as noise; treat a difference of several times as real.
- Headless browsers. Headless Chromium, Firefox and WebKit are not identical to the browsers on your desk, particularly around GPU-backed canvas work.
- Synthetic files. The fixtures are generated, not collected. A real 50 MB PDF full of embedded fonts and vector art will behave differently from a generated one of the same size — probably worse.
- WebKit is not iPhone Safari. The WebKit column is Playwright's Linux WebKit build. Safari on iOS has a different JavaScript engine configuration and much tighter per-tab memory limits, and it was not tested here. Do not read the WebKit column as an iPhone result.
- Binary search assumes monotonicity. The search takes it for granted that if a tool handles a given size it also handles every smaller one. That is true of everything observed here, but it is an assumption the method makes.
If you want to check any of this, the harness is in the repository and reproduces from a fixed seed. Run it on your own hardware and you will get your own numbers, which are the ones that actually apply to you.
For which tools run in which engine at all, see browser compatibility for all QuickMerge tools.