Skip to content

[Feature] Browser-side ActorSystem with Web Workers #210

Description

@pathosDev

Size / Priority

  • Size: M

Rationale

Frontend state-machines (Redux, XState, Zustand) all reinvent actor patterns. actor-ts in the browser:

  • Off-thread compute (Web Workers).
  • Type-safe message passing.
  • Backpressure via Worker IPC.
  • Bridge to server cluster via WebSocket → use the same actor protocol.

Real win: one actor model for frontend + backend, with messages crossing the wire transparently.

Design sketch

// actor-ts/browser subpackage

// Spawn an actor in a Web Worker:
const system = createBrowserActorSystem();
const worker = system.actorOfWorker(import.meta.url, props);

// Bridge to server cluster:
const bridge = system.connectToCluster('wss://api.example.com/cluster');
const serverActor = await bridge.actorAt('/user/services/orders');
await serverActor.ask(new GetOrder('42'));

Implementation:

  • Web Worker per dispatcher.
  • MessageChannel for IPC between Workers + main thread.
  • WebSocket for server-cluster bridge.
  • Shared types via TypeScript project references.

Integration

  • Actor: same core; Worker is just a different mailbox-dispatcher.
  • RemoteActorRef: WebSocket-based remote.
  • Cluster bridge: same WireMessage format.

Out of scope / non-goals

  • Multi-Worker clustering — too much complexity.
  • SharedArrayBuffer — out of scope.

Open design questions

  1. Worker per actor vs Worker per dispatcher: dispatcher (lower overhead).
  2. Serialisation: structuredClone for IPC; JSON/CBOR for WS.
  3. Bundle size: minimal core only.

Test plan

  1. Spawn actor in Web Worker; message exchange works.
  2. Cross-Worker tell.
  3. Bridge to server → ask server actor.
  4. Browser app reactive to server events.
  5. Bundle size ≤ 50KB.

Acceptance criteria

  • actor-ts/browser subpackage.
  • Web Worker dispatch + IPC.
  • WebSocket cluster bridge.
  • Sample app.
  • Documentation.
  • CHANGELOG entry.

Pre-implementation checklist

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpriority: lowNice-to-have / niche / demand-driven

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions