Problem
Worker-thread messaging is a star topology through the main thread, with no zero-copy path anywhere — and neither fact is documented or tracked as the deliberate trade-off it presumably is.
Star topology. Every worker's only channel is its MessagePort to the main-thread WorkerBroker; the broker receives each envelope and re-posts it to the target port. Worker→worker traffic therefore costs two hops and two structured clones, the main thread is on the hot path of all cross-worker messaging (a busy main thread throttles the whole mesh), and it is a single point of failure. #774 already treats the broker's re-post step as a security surface; this issue is about it being the performance and availability bottleneck by construction. MessageChannel pairs between workers would give O(1) direct routes at the cost of N² channel setup — a decision worth recording either way.
No zero-copy. PortLike.postMessage declares a transfer parameter that no caller ever passes, and SharedArrayBuffer/transferables appear nowhere in src/. Every payload crossing a thread is fully structured-cloned — twice, given the star. For the workloads workers exist for (CPU-bound processing of large buffers), the copy cost eats the parallelism gain; a Uint8Array that could move for free is copied twice per hop.
Neither is a bug — both are defensible v1 choices. The ask is to make them chosen: benchmark the broker hop (once #1177's harness can measure real transports), document the topology and its ceiling on the worker docs page, and decide whether direct worker-to-worker channels and a transferable fast path (opt-in, for ArrayBuffer-bearing payloads) are on the roadmap or explicitly out of scope.
Evidence
src/worker/WorkerBroker.ts:29,60-66 — port.onmessage → onMessage → target.postMessage(env): every cross-worker envelope relays through the main thread.
src/cluster/transports/MessageChannelTransport.ts:24 — postMessage(value: unknown, transfer?: unknown[]) declared; line 71 — the only call site passes no transfer list.
- Grep for
SharedArrayBuffer|transferList|structuredClone across src/: only the unused transfer? declaration.
Verification status
CONFIRMED-BY-READ — call sites and greps on the v0.15.0 tree; no measurement taken. From the independent production-readiness pass (2026-08-14), second batch (design decisions). Related: #774 (broker re-post as a security surface), #700/#702/#734 (worker lifecycle), #210 (browser-side workers), #1177 (benchmark coverage that would price the hop).
Problem
Worker-thread messaging is a star topology through the main thread, with no zero-copy path anywhere — and neither fact is documented or tracked as the deliberate trade-off it presumably is.
Star topology. Every worker's only channel is its
MessagePortto the main-threadWorkerBroker; the broker receives each envelope and re-posts it to the target port. Worker→worker traffic therefore costs two hops and two structured clones, the main thread is on the hot path of all cross-worker messaging (a busy main thread throttles the whole mesh), and it is a single point of failure. #774 already treats the broker's re-post step as a security surface; this issue is about it being the performance and availability bottleneck by construction.MessageChannelpairs between workers would give O(1) direct routes at the cost of N² channel setup — a decision worth recording either way.No zero-copy.
PortLike.postMessagedeclares atransferparameter that no caller ever passes, andSharedArrayBuffer/transferables appear nowhere insrc/. Every payload crossing a thread is fully structured-cloned — twice, given the star. For the workloads workers exist for (CPU-bound processing of large buffers), the copy cost eats the parallelism gain; aUint8Arraythat could move for free is copied twice per hop.Neither is a bug — both are defensible v1 choices. The ask is to make them chosen: benchmark the broker hop (once #1177's harness can measure real transports), document the topology and its ceiling on the worker docs page, and decide whether direct worker-to-worker channels and a transferable fast path (opt-in, for
ArrayBuffer-bearing payloads) are on the roadmap or explicitly out of scope.Evidence
src/worker/WorkerBroker.ts:29,60-66—port.onmessage→onMessage→target.postMessage(env): every cross-worker envelope relays through the main thread.src/cluster/transports/MessageChannelTransport.ts:24—postMessage(value: unknown, transfer?: unknown[])declared; line 71 — the only call site passes no transfer list.SharedArrayBuffer|transferList|structuredCloneacrosssrc/: only the unusedtransfer?declaration.Verification status
CONFIRMED-BY-READ — call sites and greps on the v0.15.0 tree; no measurement taken. From the independent production-readiness pass (2026-08-14), second batch (design decisions). Related: #774 (broker re-post as a security surface), #700/#702/#734 (worker lifecycle), #210 (browser-side workers), #1177 (benchmark coverage that would price the hop).