Short answer: Send typing cues during a live logistics poll only as disposable state: coalesce updates, expire them quickly, and drop them before they compete with vote acknowledgments. If the system cannot isolate those delivery policies, skip the cues. A dispatcher choosing among loading windows may benefit from knowing that a facilitator is composing a clarification; nobody benefits from a delayed indicator that survives after the poll closes.
The delivery contract matters more than the animation. Ballots are durable business facts. A current tally is a derived view. A typing cue predicts near-future activity and becomes false merely because time passes. Putting all three on one convenient channel does not make their reliability needs equal.
Should typing indicators use a channel, or is skipping them safer?
Consider a facilitator writing a note about dock 14. Connectivity drops and the note is abandoned. If an active event waits in a retry queue, it can arrive after voting ends. Reliable delivery has preserved a lie. Losing a ballot acknowledgment creates the opposite problem: a participant may retry a ballot that the server already recorded, so the durable path needs a stable submission identifier and an idempotent response.
The useful promise for a cue is bounded visibility, not eventual delivery. Give each state a monotonically increasing sequence within a participant session and a server-assigned expiration timestamp. A receiver applies a newer state only while it remains unexpired. After reconnect, it starts from silence rather than replaying old activity.
This boundary is strict. Votes may wait; cues may vanish.
Silence wins often.
Do not publish every keypress. Publish when composition changes from idle to active, refresh only when needed to represent continuing activity, and send idle when it can arrive before expiry. The timeout is a product decision to measure with session traces, not a universal constant. Human pause length, network delay, and the damage from stale state differ between a warehouse briefing and a social conversation.
How much chatter buys a useful signal?
Let U be recipients whose behavior could change, E the cue events per composing interval after coalescing, and F concurrent facilitators. Attempted fan-out is proportional to U * E * F. That is a capacity model, not a benchmark. Measure its inputs under slow consumers, disconnects, and membership changes.
A small Python policy function makes the drop behavior explicit. It is deliberately transport-agnostic.
from dataclasses import dataclass
from datetime import datetime, timezone
@dataclass(frozen=True)
class Cue:
session_id: str
actor_id: str
sequence: int
state: str
expires_at: datetime
def should_apply(cue: Cue, last_sequence: int, poll_open: bool) -> bool:
now = datetime.now(timezone.utc)
return (
poll_open
and cue.state in {"active", "idle"}
and cue.sequence > last_sequence
and cue.expires_at > now
)
Sequence rejects reordering within one participant session. Expiration rejects an otherwise newer event that arrived too late to mean anything. Neither field turns the cue into history, and neither should share an identifier namespace with ballots.
Delivery choices after the constraint is clear
A server-relayed channel gives the application one place to enforce authorization, expiry, and per-session fan-out limits. A peer data channel can remove the server from the data path, but the application still owns participant discovery, authorization, topology changes, and departure semantics. The W3C WebRTC 1.0 specification exposes ordered delivery and retransmission controls for data channels. Those are mechanisms; they do not define what a typing cue means.
| Path | Delivery stance | Failure to design for | Useful boundary |
|---|---|---|---|
| Server-relayed session channel | Best effort, coalesced, no replay | Slow recipients retaining stale state | Moderate groups with centralized policy |
| Peer data channel | Ordered or unordered with bounded retransmission choices | Peer churn and inconsistent membership views | Small sessions already requiring peer topology |
| No cue path | No delivery or storage | Participants get no advance notice | Sessions where the signal cannot change action |
Skipping the feature is a legitimate product state, not a degraded transport mode. If only facilitators can write and their finished clarification appears immediately, the signal may add nothing actionable. In a moderated poll where depot representatives wait before selecting a route window, one facilitator cue may justify sparse fan-out.
The trade-off is concrete. A server relay is not suitable when the design requires direct peer traffic and the team cannot operate a relay data plane; a peer channel is a poor fit when large, frequently changing membership makes topology management the dominant work. Omitting cues avoids both costs, but its limitation is equally plain: participants cannot distinguish a quiet facilitator from one who is preparing information that may change their vote. None of these options is universally preferable.
Guarantees should be asymmetric. The sender does not need confirmation that every observer rendered active; waiting would put the weakest recipient on the critical path. Observers may silently discard expired cues. A ballot needs an application response tied to its submission identifier because transport delivery alone does not establish that the ballot entered poll state.
Failure modes need a separate budget
The obvious failure is a stuck indicator. The more damaging one is priority inversion: disposable updates fill buffers ahead of poll state, so participants see animation while votes appear unresolved. Separate queues or strict admission control are necessary even when both classes share one physical connection. A shared socket is not permission to share backpressure policy.
Other failures are quieter, and they compound. A mobile client resumes with an old sequence while a second tab claims the same actor; the participant is moved from the east-region poll to the west-region poll while an active update remains buffered; then the first poll closes before fan-out. Treating those as three independent retries can display the wrong actor in the wrong room after the decision is over. Use a new session epoch after reconnect, scope sequences to that epoch, bind every admitted cue to the current poll membership, recheck that the poll is open before fan-out, and discard the event if any condition fails. Retries must not outlive meaning, and a cue must never migrate between poll sessions merely because an actor identifier remains valid.
Count admitted, coalesced, dropped, expired-before-send, and expired-at-receive cues. Track queue age by message class and recipients selected per event. Do not log draft text; transition metadata operates the feature without retaining composed content. Aggregate metric retention should follow the organization's data policy instead of inheriting ballot retention by accident.
Load tests need slow readers and reconnect storms, not merely steady publishers. Hold one recipient below consumption rate, rotate membership with events in flight, and close a poll at peak activity. Verify that ballot latency remains within the system's objective while cue drops rise.
That outcome is correct.
Roll out the smallest reversible version
Start with a poll-session feature flag and enable cues only for roles whose unfinished message can affect voting, such as the facilitator. Emit two states, attach a session epoch, sequence, and server expiry, then enforce a per-session admission limit. Isolate ballot processing before exposing the flag to traffic.
Compare enabled and disabled sessions using predefined signals: fan-out volume, stale-render rate, poll completion time, clarification timing, disconnect rate, and ballot acknowledgment latency. The question is whether participants change useful behavior, not whether an animation receives attention. No observed benefit is enough reason to remove it.
Roll back by disabling admission, not draining old cue messages. Receivers already reject expired state and reconnect without replay, so shutdown requires no recovery of disposable data. The poll's durable record remains intact.
Top comments (0)