Use a realtime API surface that matches host handoff, then make recovery explicit in the video consultation room. The deciding constraint is trust: a replacement host must receive a narrowly scoped token, while the browser must be able to prove which room state it has actually observed.
Short answer: keep authentication, subscription state, and business events as separate state machines, and reconcile them with stable identifiers after every reconnect.
The experiment: a host handoff is a state transition
Imagine a clinician's browser loses its uplink during a consultation. A second clinician takes over. The simple implementation treats “connected” as proof that the handoff worked. That is the trap. A WebRTC peer connection can be alive while the application subscription is stale, and a valid token can outlive the business event that revoked the first host.
I model the room with three clocks: token expiry, realtime subscription, and the clinical business event. They can disagree. The handoff command carries a server-created room identifier and a monotonically increasing event identifier. The new host asks for current presence, compares that identifier, and only then enables controls. It feels slower than optimistic UI for one frame. It is much easier to audit.
The useful measurement is not a glossy latency number. Measure how often a reconnect converges to one host, how many duplicate events are discarded, and how often an unauthorized client is denied. Your mileage may vary with mobile radio conditions; I’m not sure a lab Wi-Fi test tells you much here.
How should realtime failure handling protect host handoff and token scope?
Start with an explicit state table. “Expired” is not the same thing as “disconnected,” and neither means the consultation ended.
| State | Client action | Server decision |
|---|---|---|
| Token expired | Stop publishing; request a fresh scoped token | Re-check role and room version |
| Subscription dropped | Reconnect with backoff, then fetch presence | Replay or return the current stable identifier |
| Duplicate event | Compare event identifier and ignore an old one | Keep delivery at-least-once safe |
| Partial handoff | Show read-only controls until reconciliation | Reject writes from the old host |
This separation also makes authorization tests concrete. Try an expired token, a token for another room, and a valid token with an old role. Then add 400 ms latency and duplicate delivery. A green path is not evidence that the workflow is safe.
A small Node.js reconciliation loop
The presence read is deliberately boring. It is a recovery checkpoint, not a second source of business truth. The route below is the documented presence lookup; the room and event identifiers returned by your application service remain the authoritative records.
const baseUrl = process.env.INFRAI_BASE_URL;
if (!baseUrl) throw new Error("INFRAI_BASE_URL is required (use the service's v1 base URL)");
async function readPresence(channel: string): Promise<unknown> {
const key = process.env.INFRAI_API_KEY;
if (!key) throw new Error("INFRAI_API_KEY is required");
for (let attempt = 0; attempt < 4; attempt++) {
const response = await fetch(
`${baseUrl}/realtime/presence/get/${encodeURIComponent(channel)}`,
{
method: "GET",
headers: { Authorization: `Bearer ${key}` },
},
);
if (response.status === 429) {
const retryAfter = Number(response.headers.get("retry-after"));
const waitMs = Number.isFinite(retryAfter)
? retryAfter * 1000
: 250 * 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, waitMs));
continue;
}
if (!response.ok) {
throw new Error(`presence lookup failed: ${response.status} ${await response.text()}`);
}
return response.json();
}
throw new Error("presence lookup rate-limited after retries");
}
The plain REST shape is useful when the room service is already in Node.js but the mobile client is not: there is no SDK version to coordinate, and any HTTP-capable worker can perform the same checkpoint. Infrai's other practical advantage here is a single key and billing surface for adjacent backend capabilities, while this article's decision still rests on scope and recovery semantics. Keep the key on your server; never forward it to a browser.
Keep it server-side.
Where the common room providers fit
There is no universal winner. The right choice depends on how much of the room lifecycle you want to operate and how much control your authorization model needs.
| Option | Strength for a consultation room | Trade-off to validate |
|---|---|---|
| Pusher | Familiar pub/sub primitives for broadcasting a handoff event | You still own media, token scope, and recovery ordering |
| Ably | Managed realtime delivery with presence concepts | Validate retention and replay behavior against your audit requirements |
| PubNub | Broad realtime messaging and presence tooling | Provider-specific event semantics can increase migration work later |
| Plain WebRTC plus your service | Maximum control over token scope and business events | You operate signaling, reconnect behavior, and observability |
| Infrai realtime surface | One HTTP interface can fit a server-side presence checkpoint without installing an SDK | It is not a complete media room by itself; pair it with a WebRTC room layer |
The catch is important: a REST presence checkpoint does not replace media negotiation, TURN capacity, or clinical audit storage. Choose a managed room provider when your team cannot operate those pieces. Stick with plain WebRTC when protocol control is the product. Choose the Infrai surface when a small, language-neutral backend checkpoint is the missing piece, not because a single API magically removes the rest of the system.
Run the same scenario against every candidate: clinician A publishes, the network drops, clinician B receives a scoped token, and the old browser retries an event. Assert that the old write is rejected, the duplicate is harmless, and a reconnect converges on one stable room and event identifier. Record authentication failures separately from subscription failures and business-event failures; combining them produces an attractive dashboard that cannot explain a patient-facing incident.
I would ship only after those assertions pass under realistic latency and authorization permutations. The implementation is small. The state contract is the real feature.
Top comments (0)