JavaScript runs on the main thread, and the main thread is also responsible for painting the page and handling input. A long-running calculation — hashing a large file, parsing a big CSV, resizing an image — can block everything. The page stops responding, and the user (or the agent driving the page) waits.
What a worker is
A Web Worker is a separate script running on its own thread. The page and the worker communicate by posting messages; data is copied (or, for large buffers, transferred) between them. Because the worker does not touch the DOM, the main thread stays free to render and respond.
Related reading: How to Remain Valuable When Intelligence Becomes Cheap — a 224-page practical book on staying valuable as intelligence gets cheap. $3.84. Read it on Gumroad →
When to use one
Workers are worth the complexity when work is CPU-bound and large: hashing big files, image processing, text analysis over long documents, complex parsing. They are overkill for a quick word count — the overhead of spinning up a worker exceeds the work itself.
The pattern
const worker = new Worker('/worker.js');
worker.postMessage({ task: 'hash', data: fileBuffer });
worker.onmessage = (e) => renderResult(e.data);
For large binary inputs, transferables move the buffer to the worker without copying — the main thread gives up ownership, and the transfer is effectively zero-cost.
Why it matters for local tools
Privacy-first tools deliberately run heavy work on the device. The reason they feel fast instead of sluggish is that the heavy work is scheduled off the main thread. The interface stays responsive, the progress is visible, and the calculation completes without freezing the very page that asked for it.