Running ML in the Browser: The Engineering Behind Client-Side Inference
Web Workers, chunked parsing, typed arrays, and memory cliffs: the real engineering behind running statistics and ML entirely in the browser.
"It runs entirely in your browser" is one line in a product description and several months of engineering decisions behind the scenes. Browsers are a hostile runtime for data work: a single main thread shared with rendering, hard memory ceilings, no filesystem access, and hardware ranging from M-series laptops to five-year-old phones. Here's how you actually build statistical and ML workloads that survive it — the same architecture behind KPI Master.
The Main Thread Is Not Yours
The browser's main thread juggles layout, paint, event handling, and your JavaScript. Block it for 500ms and the page feels broken; block it for 5 seconds and Chrome offers to kill the tab. Any computation longer than ~50ms belongs in a Web Worker — a separate thread with its own event loop that communicates with the page via message passing. The discipline: parse, smooth, cluster, and correlate in the worker; render in the main thread; pass only the finished results (arrays of numbers, not megabytes of raw text) across the boundary, using postMessage with transferable objects where possible to avoid structured-clone copying.
Memory Is a Cliff, Not a Slope
Desktop Chrome typically allows 2–4GB per tab; mobile browsers far less, and the tab doesn't degrade gracefully — it crashes with "Aw, Snap." The failure mode that bites everyone: reading a 200MB CSV with FileReader.readAsText, then splitting it into an array of lines, then parsing each line into objects. At peak you've materialized the raw string, the line array, and the object graph simultaneously — easily 6–10x the file size in memory.
The fix is chunked, streaming parsing. Papa Parse's worker mode reads the file in slices, emits rows in batches, and never holds the whole file as a single string. Your aggregation state — running sums, min/max, reservoir samples for quantiles, per-column type counters — is a few kilobytes regardless of file size. A 100MB file then processes with a near-flat memory profile. This is the single highest-leverage optimization in browser data tooling: it converts "crashes on big files" into "takes a few more seconds on big files."
WASM: When JavaScript Isn't Fast Enough
For genuinely heavy numeric work — large matrix operations, model inference, image processing — WebAssembly runs at near-native speed and, critically, gives you manual memory layout with linear memory buffers instead of garbage-collected objects. The honest assessment from our experience: most business statistics don't need it. Holt forecasting, k-means, correlation matrices, and z-score passes over a million rows complete in well under a second in plain optimized JavaScript, especially with typed arrays (Float64Array) that avoid boxing overhead. Reach for WASM when profiling — not intuition — says JS is the bottleneck. Premature WASM is a build pipeline, a debugging story, and a bundle size you didn't need.
The Privacy Architecture You Get for Free
Client-side computation has a property no server architecture can match: the data physically never leaves the machine. No upload endpoint exists, so no upload can leak. No server-side processing means no server-side logs containing your data, no breach that exposes it, no subprocessors to list in a DPA. This isn't a policy promise that requires trusting us — it's a verifiable fact of the network tab. For users handling financial exports, HR data, or anything covered by GDPR, that distinction is the entire ballgame.
The Playbook
- Parse in chunks inside a Web Worker; never materialize the full file on the main thread.
- Aggregate incrementally with O(1) state; defer anything needing full materialization (quantiles, clustering) to sampled or typed-array representations.
- Use typed arrays for numeric columns; profile before reaching for WASM.
- Ship results back to the UI as compact summaries, render with cheap SVG, and lazy-load heavy format parsers (XLSX libraries are ~1MB) only when the file type demands them.
The browser stopped being a document viewer a decade ago. Treated with respect for its constraints, it's a credible statistical computing environment — with the best privacy story in the industry as a side effect.