DEV Community

Cover image for 7 Engineering Lessons From Building File Processing Directly in the Browser
Sora Labs
Sora Labs

Posted on

7 Engineering Lessons From Building File Processing Directly in the Browser

I've been building SoraFiles, a privacy-first web app for working with PDFs and images directly in the browser.

The interesting part has not been creating another upload form.

It has been removing the upload step entirely for supported workflows.

The basic architecture is:

User file
-> Browser File API
-> Local JavaScript / WebAssembly processing
-> Result
-> Download

Instead of:

Browser
-> Upload
-> Processing server
-> Temporary storage
-> Download

That sounds simple until you try to make it reliable on phones, Safari, large PDFs, corrupt files, repeated user actions, and limited browser memory.

Here are seven engineering lessons that have mattered most.

============================================================

1. TREAT EVERY PROCESSING OPERATION AS A JOB

The simplest implementation is also the one most likely to create stale-state bugs.

A user clicks Process.

The job starts.

Before it finishes, they remove the file and select another one.

If the first operation is still allowed to update the interface, the old result can suddenly appear inside the new workflow.

That is confusing and dangerous.

A better model is to treat every processing operation as a job with:

  • a unique identity
  • a state
  • cancellation
  • ownership of its resources

The lifecycle can be thought of as:

Idle
-> Ready
-> Processing
-> Success / Error / Cancelled

Before any asynchronous task updates the UI, the application should verify that it still belongs to the current active job.

That one idea prevents a surprising number of bugs.

============================================================

2. WEB WORKERS HELP, BUT OWNERSHIP STILL MATTERS

PDF rendering, OCR, compression, and image conversion can become expensive quickly.

Moving heavy work into Web Workers helps keep the interface responsive.

But a Worker does not magically solve memory problems.

Large buffers may still need to move between the main thread and the Worker.

So the important questions become:

  • Who owns this buffer?
  • Was it copied or transferred?
  • Can the main thread still use it?
  • What happens when the user cancels?
  • Who cleans it up?
  • Can the Worker be terminated safely?

Local processing becomes much easier to reason about when data ownership is explicit.

============================================================

3. CLEANUP IS PART OF THE ALGORITHM

A browser-local file application can create a lot of temporary resources:

  • canvases
  • image bitmaps
  • PDF rendering tasks
  • object URLs
  • Blobs
  • ArrayBuffers
  • workers
  • event listeners
  • temporary decoded documents

If you create them and never clean them up, the browser may keep enough memory alive to make the app unstable on mobile.

I now think of cleanup as part of the actual processing pipeline:

Validate
-> Decode
-> Process
-> Encode
-> Expose result
-> Cleanup

Not:

Process
-> Hope garbage collection eventually fixes everything

This matters especially on iPhones and lower-memory devices.

============================================================

4. A 20 MB FILE DOES NOT MEAN 20 MB OF MEMORY

Compressed file size and in-memory size are very different things.

A 20 MB PDF may temporarily involve:

  • the original ArrayBuffer
  • decoded page data
  • several canvases
  • preview images
  • intermediate output
  • the final result Blob

Images can expand dramatically when decoded into raw pixels.

So large-file support is not just about removing an arbitrary upload limit.

It requires:

  • bounded concurrency
  • sequential processing where possible
  • avoiding unnecessary buffer copies
  • releasing resources quickly
  • lower-resolution previews
  • cancellation
  • capability-aware limits

Desktop browsers can hide inefficient architecture.

Phones expose it.

============================================================

5. PREVIEW RENDERING CAN BECOME A PERFORMANCE BUG

A preview looks like a UI problem.

It is also a memory problem.

Suppose a PDF page is displayed inside a 320-pixel-wide card.

If you render that page internally at several thousand pixels and simply shrink it with CSS, the preview may look correct while still consuming far more memory than necessary.

A better approach is:

  1. Determine the actual visible preview size.
  2. Account for device pixel ratio.
  3. Render close to the resolution the UI genuinely needs.

The browser is both your renderer and your processing machine.

Waste resources on the preview and you leave fewer resources for the actual file operation.

============================================================

6. DEFINE WHAT ANALYTICS MUST NEVER RECEIVE

Analytics usually starts with:

"What should we track?"

For software handling private documents, I think the first question should be:

"What should never reach analytics?"

For SoraFiles, file-derived information should remain outside the analytics layer.

That includes things such as:

  • filenames
  • document text
  • OCR output
  • metadata values
  • passwords
  • signatures
  • image pixels
  • generated file contents

You can still learn whether the product works.

For example:

Tool opened
-> Processing started
-> Processing succeeded

That tells you whether users can complete a workflow.

You usually do not need to know what was inside their document.

The rule I like is:

Analytics should answer "Did the workflow work?" without answering "What was inside the user's file?"

============================================================

7. HONEST LIMITATIONS BUILD MORE TRUST THAN PERFECT-SOUNDING CLAIMS

Some file operations are relatively straightforward.

Others are not.

Examples of difficult workflows include:

  • PDF to Word
  • Word to PDF
  • OCR
  • PDF repair
  • complex spreadsheets
  • unusual fonts
  • forms
  • embedded objects
  • complicated page layouts

Browser libraries are powerful, but they do not perfectly reproduce every edge case.

If a conversion may simplify a complex layout, tell the user before processing.

If transparency must be flattened, explain it.

If a very large file may exceed the browser's practical memory limit, say so.

Users can understand limitations.

What destroys trust is discovering them only after downloading the result.

============================================================

WHY LOCAL PROCESSING IS INTERESTING

Server-side processing still has real advantages:

  • predictable compute
  • larger memory pools
  • powerful native libraries
  • easier handling of huge files
  • consistent execution environments

Local processing has different advantages:

  • files can stay on the user's device
  • no upload wait
  • reduced server-side exposure
  • some workflows can continue offline
  • less processing infrastructure is required

So I do not think the right question is:

"Should everything run locally?"

A better question is:

"Does this operation genuinely require the user's file to leave their device?"

For many routine PDF and image operations, modern browsers increasingly make the answer:

No.

============================================================

OPEN SOURCE AND INSPECTABILITY

SoraFiles is open source under AGPL-3.0.

Open source does not automatically make software secure.

It does not replace:

  • testing
  • dependency review
  • secure implementation
  • privacy engineering
  • vulnerability management

But it makes architectural claims easier to inspect.

People can look at the code and see how the processing path works.

For privacy-focused software, that inspectability matters.

============================================================

CLOSING THOUGHT

Building file processing directly inside the browser changed the way I think about privacy engineering.

The strongest privacy improvement was not another paragraph in a privacy policy.

It was removing unnecessary data movement from the architecture.

Once that decision is made, privacy becomes an engineering problem:

  • memory management
  • workers
  • cancellation
  • state machines
  • browser compatibility
  • output validation
  • honest limitations
  • carefully separated analytics

That work is less visible than putting a privacy badge on a landing page.

It is also what makes the privacy claim meaningful.

If the user's device is already capable of doing the work, uploading their private file should not automatically be the default.

SoraFiles:
https://sorafiles.com

Source code:
https://github.com/Sora-Labs2026/SoraFiles

DISCLOSURE

Sora Labs develops SoraFiles.

SoraFiles is used here as the practical case study for the engineering lessons described in this article.

Top comments (0)