1.5 KiB
ADR-0003: Multi-Client Sessions with Connection-Scoped Routing
Status
Accepted
Context
Users expect to stay logged in on multiple devices simultaneously (Discord-style). The signaling server already issued multiple session tokens per user, but WebSocket broadcasts deduplicated by oderId, which prevented a user's second device from receiving chat, typing, or voice-state updates from their first device. Voice had no per-device identity, so two clients could both attempt to transmit audio.
Decision
Introduce a stable per-install clientInstanceId on the product client. Route server broadcasts by connection id (exclude only the sender socket) while keeping presence user_joined / user_left identity-scoped. Track voiceActive per connection; relay RTC to the voice-active socket. Enforce single voice owner per user via VoiceState.clientInstanceId and voice_client_takeover handoff between connections.
Consequences
- Positive: Chat and presence sync across a user's devices; voice behaves like Discord (one transmitting client, passive viewers, explicit takeover).
- Positive: Stale-tab hygiene uses
(oderId, connectionScope, clientInstanceId)eviction without kicking other devices. - Negative:
findUserByOderIdsemantics change — RTC now prefers voice-active connections; callers must not assume one socket per user. - Negative: Clients must include
clientInstanceIdon identify and voice payloads; older builds without it still work but cannot participate in multi-device voice exclusivity reliably.