Under The Hood
frontend javascript HTML spec (structured clone, transferables)

Web Workers: Structured Clone Algorithm vs Transferable Zero-Copy

Last updated
Prerequisites:
Web Workers and postMessage basics
Understanding of ArrayBuffer and typed arrays
  • web-workers
  • structured-clone
  • transferable
  • postmessage
  • zero-copy
  • concurrency

Read at your depth

The practical view

worker.postMessage(value) copies data using the structured clone algorithm: it recursively copies plain objects, arrays, Maps, Sets, Date, RegExp, typed arrays, and ArrayBuffers. The original stays usable in the sender. For large buffers, pass a transfer list: worker.postMessage(buffer, [buffer]) — this transfers the ArrayBuffer (zero-copy) and detaches it from the sender (buffer.byteLength becomes 0). Transferables include ArrayBuffer, MessagePort, ImageBitmap, OffscreenCanvas. Use transfer for big binary payloads to avoid double memory and serialization cost. Note: functions, DOM nodes, and class instances are NOT cloneable.

The same idea in other frameworks

react equivalent
React and its workers (e.g. webpack workers) use transferable ArrayBuffers for asset/binary transfer to keep the main thread responsive.

Legacy vs modern

Sending a large ArrayBuffer: structured clone vs transferable

Structured cloning copies every byte; transferring detaches and hands the same bytes to the worker — O(n) vs O(1).

before → after
postMessage without transfer list
worker.postMessage(buffer); // ❌ OLD: full structured clone — bytes are copied
Transferable zero-copy handoff
worker.postMessage(buffer, [buffer]); // ✅ NEW: detaches + transfers, no copy

Interview gotchas

Context

This is the core performance/semantics question about worker messaging — interviewers want the copy-vs-detach distinction and a deployment instinct for when to use each.

The mechanical answer

Structured clone is a deep serialization that recursively copies the value graph (handling cycles, Maps, Sets, Dates, typed arrays) so both sides end up with independent copies; it is correct for small state messages but costs O(n) time and memory for large payloads. A transferable is a resource whose ownership moves: the sender's object is detached and the receiver gets the same underlying bytes/ports, making the handoff O(1) and zero-copy. Choose structured clone for small configuration/state, transferables for large one-way binary streams (frames, audio, WASM memory) where the sender no longer needs the data. Mixing them — cloning when you could transfer — is a classic performance bug.

Trap

The naive answer is 'transferables are just faster postMessage'. Transferables change ownership: the source buffer is detached and unusable, which breaks code that assumes it can keep using it. Another trap: assuming any object can be transferred — only ArrayBuffer, MessagePort, ImageBitmap, OffscreenCanvas, and a few others support transfer; everything else falls back to cloning (or throws for functions/DOM nodes).

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.