Compress documents in the browser, not on your servers

Most document pipelines start the same way. A user picks a 14 MB scan, the browser uploads all 14 MB, a queue picks it up, a worker compresses it to 1.2 MB, and the original is deleted. You paid for the bandwidth, the queue, the worker and the storage — to end up with a file you could have had before the upload started.

The alternative is to compress first and upload the result.

What actually moves

Run the compression client‐side and the arithmetic inverts. Only the compressed bytes cross the network; the raw original never leaves the device. On a typical scanned bundle that is the difference between shipping 14 MB and shipping under a megabyte, per document, per user.

That matters most where you have least control: mobile data, hotel wifi, a field agent on a train. Upload time stops being a function of scanner resolution.

Where the work happens

The Abscode Browser JS SDK does this with WebAssembly. It compresses JPEG, PNG, single‐ or multi‐page TIFF and PDF entirely on the user’s device, with no server round‐trip, and hands back a single PDF, a multi‐page TIFF, or one JPEG per page.

<title id=“d‑compress‑t”>Where compression happens changes what crosses the network</title> Server‐side: the browser uploads the full 14 MB scan and the server compresses it. Browser‐side: the browser compresses first and uploads 1.2 MB.SERVER‐SIDEBrowser14 MB uploadServer compressesStoreIN THE BROWSERBrowser compresses1.2 MB uploadStore
The pipeline is the same length either way. Only one of them puts 14 MB on the wire.

The controls are the ones that actually determine output size:

  • DPI — the single biggest lever. 300 DPI is the usual floor for reliable OCR; 600 is rarely worth the bytes for text documents.
  • Page layout — A0 through A6, or explicit dimensions.
  • Filter — colour, greyscale, or bitonal. A bitonal filter on a text‐only page is dramatic, and destructive if the page turns out to have a photo on it.
JS
scanner.SetDPI(300);
scanner.SetPageLayout(A4);
scanner.SetFilter(BW);

const pdf = await scanner.compressToPdf(files);

The result is in memory the moment the call resolves. There is no job id to poll and no webhook to wire up.

The infrastructure you no longer run

This is the part that tends to get underestimated. Server‐side document processing is not one service. It is an upload endpoint, object storage for originals you are about to throw away, a queue, a worker pool sized for peak rather than average, an autoscaling policy, a dead‐letter path, and monitoring for all of it.

Client‐side, that becomes a function call. No queue, no worker fleet, no autoscaling group doing image work. The compute is the user’s, and it is already idle.

It also works offline once the page has loaded, which server‐side processing categorically cannot.

The privacy argument is the strongest one

For anything touching identity documents, the interesting property is not speed. It is that nothing is transmitted to be processed, so there is no third‐party processing hop.

That removes an entire category of question. There is no processor to name in a data‐processing agreement for this step, no retention window to justify for the originals, and no region to pin for a service that never sees the file. Under the DPDP Act and GDPR alike, the cheapest data to protect is data you never collected.

If your compliance review has ever stalled on “where does the unredacted scan live between upload and compression” — the answer becomes “it doesn’t”.

When to keep it on the server

Client‐side is not automatically right.

  • You need the original. Some archival and legal workflows require the untouched file. Compress a derivative, keep the source.
  • The work is batch. Ten thousand documents from an overnight drop have no browser tab to run in. That is what the server SDKs are for.
  • Output must be provably identical. Browsers vary. If a regulator will compare hashes across submissions, do it once, centrally.
  • The device is a potato. A five‐year‐old budget Android compressing a 200‐page TIFF is a bad experience. Set a page threshold and fall back.

The practical shape for most teams is both: compress at capture in the browser or on the device, and keep a server path for batch and for the exceptions.

Try the ordering change first

Before evaluating any SDK, the cheap experiment is to look at what your current pipeline uploads versus what it stores. If those two numbers are far apart, the gap is bandwidth and compute you are paying for to discard.

Our optimizations save time and space first; the money follows.