Why client-side first
The decision to process PDFs entirely in the browser was not primarily a technical one. It was a values one. When someone uploads a document to a server — any server — they are making a trust decision. We did not want users to have to make that trust decision with us.
Library choices
The JavaScript PDF ecosystem is more fragmented than you might expect. We evaluated five libraries before settling on our current stack. PDF.js is the standard for rendering. For creation and editing we use pdf-lib. For compression and heavy operations we brought in a WebAssembly port of MuPDF.
The WASM tradeoffs
Using WebAssembly introduces a tradeoff. The WASM binary for our PDF processing is around 4MB. Loading a 4MB binary on first visit adds a perceptible delay — on a fast connection, maybe 600ms; on a slower connection, potentially several seconds.
“We solved it with lazy loading: the WASM module only initialises when a user selects their first file. By then, they have committed to the task.”
The unexpected UX problem
We expected the technical challenges. What we didn't anticipate was the UX problem that client-side processing creates: when something is happening inside the browser, it's hard to show meaningful progress.
Real-world performance
The WASM implementation handled 20MB files in roughly the same time the JavaScript implementation handled 5MB files. At 50MB the WASM library was 4.7× faster than the JavaScript alternative.
The memory problem
Memory management is unsolved. Browsers impose memory limits that vary by browser, by device, and by how much memory other tabs are consuming. Our current approach is chunked processing and graceful user communication.
Enjoyed this article?
Get new articles, product updates and insights from Muqira in your inbox.
Found this useful? Share it.





