Skip to content

[Arch Review] WebSocket fan-out serializes each broadcast payload once per subscriber #196

@Pappet

Description

@Pappet

Severity

Medium — redundant CPU that scales with (message rate × connected viewers).

Problem

Every store event is broadcast to all WebSocket subscribers, and each subscriber's task serializes the same payload independently.

  • MessageStore::insert sends one StoreEvent::NewMessage(Box<summary>) over the broadcast channel (src/store.rs:120).
  • Each connected client runs its own handle_ws loop, and for every event calls send_ws_event (src/web.rs:230-243), which does serde_json::json!{...}.to_string() — a fresh JSON serialization of the identical summary, once per socket.

With N developers watching the same Orchestra feed (the documented multi-user scenario in CLAUDE.md), an incoming message is serialized N times into N identical strings.

Why it matters

The serialization is pure duplicated work on the hot ingest-broadcast path. At high message rates with several viewers it multiplies CPU and allocation for zero benefit, and competes with the parse/validate work already on that path (#180 / KB-4).

Suggested fix

Serialize each event payload once (e.g. in insert, or a small adapter that converts StoreEvent → pre-rendered JSON String/Arc<str> before broadcasting), then have each handle_ws task send the shared bytes verbatim. The broadcast channel can carry the already-serialized frame (or an Arc<str>) instead of the structured event, so per-socket work is just a send.

Found during the architecture review.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions