ADR-0008: Single-Home Consistency and Durability Boundary¶
Status¶
ADR-0008 - Accepted (2026-07-30)
Context¶
Signal Fish Server is a zero-external-runtime-dependency, in-memory signaling and relay server. Existing tests and formal models prove useful guarantees only when one process owns a room:
- the two-process H5 experiment demonstrates duplicate public room codes, stranded reconnect credentials, and rejected cross-instance signals;
SequencedRelay.tlaandReconnectReplay.tlacontain seeded split-brain counterexamples; and- the H2 relay experiment shows a shared-runner latency knee between the 120 and 240 message/s/player targets for a 16-player, 1 KiB JSON workload.
The code has extension seams named DistributedLock, MessageCoordinator, and
GameDatabase, plus room-code prefixes and region IDs. None supplies shared
authority, route ownership, sequence ownership, reconnect-token portability, or
live-room migration. Without an explicit decision, those names can be mistaken
for partial horizontal-scaling support.
The reconnect contract also needed a quantitative statement. Gameplay data is not replayed, so the recoverable object is identity and current control state, not every payload accepted before or during an outage.
Decision¶
The supported product boundary remains one active home process per room for the room's lifetime.
Multiple Signal Fish processes are supported only as isolated routing domains. An application-owned directory may assign a new room to one deployment and give every participant the deployment-specific WebSocket URL before the upgrade. The shipped server does not move a live room, redirect a connection by room code, or recover a room after its home exits.
Within that boundary:
- successful operations commit to process memory only;
- reconnect restores identity, current control state, and a fresh delivery
baseline, but never replays
GameDataorSignal; - planned drain closes loudly and requires room rebuild instead of handoff; and
- unexpected process loss loses the room.
The exact per-operation acknowledgement, fault, and recovery semantics live in the consistency and durability contract.
This ADR also adopts an invariant for additional exposure caused by a disconnect and the following outage:
additional gameplay exposure
= old queue tail
+ old post-queue, client-unobserved pipeline
+ room frames accepted while absent
With an enforced arrival curve A(T) <= B + ceil(R*T), the conditional ceiling
is Q + P + B + ceil(R*T). This does not include delivery-class omissions
already accounted before the cut. There is no default numeric promise because
the server has no room-wide gameplay ingress rate limit and the full
post-queue-to-application pipeline has no configuration-derived frame cap.
ReconnectLossBound.tla checks the bounded arithmetic, including the
zero-window burst edge, and its CI-pinned expected failure proves the
post-queue term is necessary.
The broad durability wording in legacy ADR-001 is clarified by this decision: control-event replay is bounded, gameplay-state recovery belongs to the application, and no state survives home-process loss. ADR-001's token and replay mechanisms remain accepted.
Alternatives considered¶
Consistent hashing inside Signal Fish¶
Rejected as a complete solution. Consistent hashing minimizes key movement when
the server set changes, but it does not replicate room state, transfer a live
WebSocket, fence an old owner, or make room_code available before the
WebSocket upgrade. It can be useful inside the external directory for assigning
new rooms, never as evidence that live rooms are portable.
Lease or fencing-token room ownership¶
Deferred unless a future distributed mode is explicitly adopted. A useful fencing token requires a shared authority that orders ownership epochs and every stateful consumer to reject stale epochs. That adds an external, high-availability control plane and a new failure model. If adopted later, it belongs on room ownership and handoff—not on each relay payload.
CRDT room membership¶
Rejected for the current protocol. Convergent membership does not by itself provide one sequence owner, atomic reconnect-token claims, ordered control replay, or a unique session-plan/authority decision. Eventual convergence is weaker than the current single-home room semantics. CRDTs may be appropriate for non-authoritative directory metadata in a separate system.
Consensus or replicated storage in the relay hot path¶
Rejected. It would add network coordination, external runtime dependencies, and a distributed failure mode to the latency-sensitive fallback path. The relay floor remains process-local. Any future replicated control plane must keep consensus out of per-message fan-out and arrive through a new ADR, protocol, falsification experiment, and migration plan.
Persist only GameDatabase¶
Rejected as a durability claim. Restoring room rows without the corresponding WebSockets, connection routes, replay cursors, reconnect claims, relay epochs, and session plans cannot restore a live room consistently.
Consequences¶
Positive¶
- Operators get one explicit consistency and durability contract instead of inferring guarantees from implementation names.
- The relay path keeps its zero-external-dependency and low-latency design.
- Failures are honest: reconnect, drain, and process loss have distinct client outcomes.
- Future distributed work has a clear bar: it must replace this boundary coherently rather than partially replicate one map.
Negative¶
- One home is an availability and durability limit. A home crash loses every room it hosts.
- Horizontal scale requires an application-owned directory and isolated room assignment before connection.
- Reconnecting clients must resynchronize gameplay state at the application layer.
- The quantitative disconnect-exposure ceiling needs an enforced burst/rate arrival curve and a bound through client observation; defaults alone cannot supply either.
Evidence and references¶
- Consistency and durability contract
- Single-instance deployment
- Scaling architecture
- Formal verification
- Karger et al., Consistent Hashing and Random Trees
(DOI:
10.1145/258533.258660) - Burrows, The Chubby Lock Service for Loosely-Coupled Distributed Systems
- Shapiro et al., A Comprehensive Study of Convergent and Commutative Replicated Data Types
- Gilbert and Lynch, Brewer's Conjecture and the Feasibility of Consistent, Available, Partition-Tolerant Web Services
(DOI:
10.1145/564585.564601)