awesome-everything RU
↑ Back to the climb

Browser & Frontend Runtime

What workers are and why they exist

Crux Workers run JavaScript off the main thread — web workers compute, service workers proxy the network, each with a hard boundary the DOM cannot cross.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at junior altitude — the surface
◷ 10 min

Parse a 5 MB JSON file on the main thread and the page freezes for ~150 ms — dropped frames, dead buttons. The browser’s answer is not “make the thread faster.” It is “give you more threads.”

The main thread problem

The browser has one thread for JavaScript, layout, paint, and input. While it is busy, nothing else runs. Parse a large file, run a crypto hash, or filter a huge dataset on the main thread and every animation and button response stalls for the duration.

The browser’s answer is off-main-thread execution — workers. Four kinds exist, each for a different job:

  • Web worker — a second JS thread for CPU-bound work (parsing, crypto, image processing). No DOM, no window, no document.
  • Service worker — a network proxy sitting between the page and the server. Intercepts requests, serves cached responses, survives page close.
  • Worklet — a tiny hook into the browser’s render or audio pipeline (paint worklet, audio worklet). Even more constrained than a worker.
  • SharedArrayBuffer — shared memory between threads (not a worker itself, but the escape hatch from message-passing). Gated behind cross-origin isolation headers.
Workers at a glance
Web worker startup
5–20 ms
5 MB JSON parse, main thread
~150 ms freeze
5 MB JSON parse, web worker
0 ms jank
Frame budget at 60 fps
16.67 ms
Frames dropped by 150 ms parse
~9 frames

The office metaphor

The main thread is you at your desk: you answer the phone (input) and update the whiteboard (DOM) yourself. A web worker is a colleague in a back room — you send a big calculation by note, they do it without disturbing your desk, they send the answer back by note. They cannot touch your whiteboard. Only you can.

A service worker is the mailroom: every letter in or out passes through it first, and it can answer some from its own filing cabinet without going outside. It keeps running even when you leave for the day.

Bea · Browser uploads a photo to edit. Sven · Origin server narrates: “Applying the filter is millions of pixel operations — on the main thread, a 600 ms freeze. So we post the image data to a web worker. The worker churns the pixels on its own thread; the main thread stays free. It posts the result back and we paint it.”

The fundamental rule

Workers have no DOM. A worker’s global is WorkerGlobalScope — it has no document, no window, no elements. This is not a limitation to work around; it is the design. It keeps the DOM single-owner and race-condition-free. A worker can compute what to render and post the result back, but the main thread must apply it.

The one exception: OffscreenCanvas. A canvas bitmap is not part of the DOM tree — it is just a pixel buffer. You can transfer an OffscreenCanvas to a worker, and the worker can draw into it entirely off the main thread. Everything else in the DOM stays main-thread only.

Order the steps

A page hands a heavy calculation to a web worker. Drag the steps into the order they happen.

  1. 1 Main thread creates the worker: new Worker('calc.js')
  2. 2 Main thread sends input data: worker.postMessage(data)
  3. 3 Worker runs the calculation on its own thread
  4. 4 Worker sends the result back: postMessage(result)
  5. 5 Main thread's onmessage handler receives the result
Quiz

Why can't a web worker update the page directly?

Quiz

What makes a service worker different from a web worker?

Complete the analogy

In the office metaphor, the colleague in the back room does heavy calculations for you and reports back by note, but cannot touch your whiteboard. Which kind of worker is that?

Compute it

A page parses a 5 MB JSON file on the main thread and it takes roughly 150 ms. The frame budget at 60 fps is 16.67 ms. Roughly how many frames does that one parse drop?

frames
Why this works

Workers were introduced because JavaScript is single-threaded by design — sharing mutable state across threads requires locks, and locks in a UI context cause deadlocks and priority inversion. The worker model avoids all of that by banning shared state entirely. Each worker has its own heap, its own globals, its own event loop. Data crosses the boundary only through postMessage (which copies it) or through explicit shared-memory primitives (SharedArrayBuffer + Atomics). The constraint is the safety guarantee.

Recall before you leave
  1. 01
    What is the fundamental difference between a web worker and a service worker?
  2. 02
    Why do workers have no DOM access?
  3. 03
    What is the one DOM-related exception for workers?
Recap

The browser’s main thread is the single owner of JS execution, layout, paint, and input — anything blocking it stalls the whole page. Workers provide additional threads: web workers for CPU-bound computation (no DOM, communicates via postMessage), service workers for network proxying (intercept fetch, serve cache, survive page close). Neither can touch the DOM — that constraint is what makes them safe. A 150 ms JSON parse on the main thread drops ~9 frames at 60 fps; moved to a web worker, it costs the main thread nothing.

Connected lessons
appears again in41
Continue the climb ↑Web worker mechanics: dedicated, shared, and OffscreenCanvas
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.