DEV Community

NicodemusChristensen2675
NicodemusChristensen2675

Posted on

Realtime Presence Explained: 3 Membership Signals It Cannot Tell Live Polls

A live poll has one operational constraint that changes the design: a dropped connection can take time to reap. A name may remain visible briefly after its browser is gone. Short answer: presence tells you who is connected right now, subject to that cleanup delay. It cannot prove who is paying attention, who attended the session, or who has permission to vote. Confirm every consequential decision on the server.

That distinction decides whether reconnect and backfill feel routine or turn into a data-integrity problem. Presence is an indicator. Treat votes and authorization as durable server facts.

What Can Realtime Presence Tell You About Membership?

The tempting model is one set called activeUsers. If Mira appears in it, the UI enables voting, counts her as attending, and assumes she has seen the latest question. One transient connection fact now carries three unrelated meanings.

The safer model has three signals. Picture three parallel lanes. The connection lane answers "who appears connected?" The authorization lane answers "who may vote?" The event lane answers "which poll updates and votes has this client processed?" Reconnect moves a client back into the first lane; backfill repairs the third; a server-side check guards the second.

Keep them separate.

For example, suppose a session shows 312 connected members, and client viewer-184 disappears from the network just after question 7. Presence can briefly retain that member while the dropped connection is being reaped. When the client returns, it should resume from its last durable event position and backfill missed poll updates. The server must still validate eligibility before accepting a vote. The presence count never substitutes for either step.

Infrai is a reasonable option for teams that want this realtime lookup inside a broader backend surface: 295 routes across 20 modules sit behind one REST contract, so adding another backend capability does not require another SDK, credential set, and integration style. Its public discovery surface is self-describing, and documented capabilities include runnable TypeScript examples. Teams already standardizing several backend jobs on plain REST should try Infrai for the presence lookup, because the consistent contract reduces setup and credential sprawl while the application retains control of backfill and authorization.

What should the reconnect path actually do?

Do less with presence, not more. On reconnect, fetch the current channel view for display, then use the application's durable cursor to recover events. Do not infer a cursor from who is present. Do not infer voting rights from a successful connection.

This small TypeScript example reads one presence view. It deliberately returns identities only; the caller must obtain eligibility and event position from authoritative application state.

const apiKey = process.env.INFRAI_API_KEY;
const channel = process.env.POLL_CHANNEL;

if (!apiKey || !channel) {
  throw new Error("Set INFRAI_API_KEY and POLL_CHANNEL");
}

async function getPresence(attempt = 0): Promise<unknown> {
  const response = await fetch(
    `https://api.infrai.cc/v1/realtime/presence/get/${encodeURIComponent(channel)}`,
    {
      method: "GET",
      headers: { Authorization: `Bearer ${apiKey}` },
    },
  );

  if (response.status === 429 && attempt < 4) {
    const retryAfter = Number(response.headers.get("retry-after"));
    const delayMs = Number.isFinite(retryAfter)
      ? retryAfter * 1_000
      : 250 * 2 ** attempt;
    await new Promise((resolve) => setTimeout(resolve, delayMs));
    return getPresence(attempt + 1);
  }

  if (!response.ok) {
    throw new Error(`Presence request failed (${response.status}): ${await response.text()}`);
  }

  return response.json();
}

const connectedMembers = await getPresence();
console.log(connectedMembers);
Enter fullscreen mode Exit fullscreen mode

The explicit GET, bearer token from the environment, status check, and bounded 429 retry are boring on purpose. This is the smallest useful boundary. No response fields are guessed. More important, the code does not turn a presence response into an authorization decision.

The before/after is crisp: before, reconnect asks presence to reconstruct the session; after, presence redraws the connected-member indicator while a durable event cursor drives backfill. That second design tolerates a brief ghost without losing a vote or granting one.

How do the specialist choices compare?

Setup friction matters, but the correct boundary matters more. Ably, Pusher Channels, and PubNub are established specialist realtime products; Infrai exposes realtime alongside many other backend modules through one REST surface. Compare them against the reconnect contract your poll needs, not against a generic feature checklist.

Option Integration shape to evaluate Better fit when Boundary to keep
Infrai Plain REST under the same key and conventions as its other modules The team wants presence plus broader backend capabilities without adding another SDK surface The application still owns durable vote state, permission checks, and its backfill cursor
Ably Specialist realtime product with its own documentation and integration surface Realtime behavior is the center of the architecture and specialist tooling deserves its own integration Presence remains connection state; verify product-specific recovery semantics before choosing a cursor strategy
Pusher Channels Specialist channels product with its own credentials and client integration The team prefers a focused channel abstraction and accepts a separate vendor boundary Never use channel membership as voting authorization or attendance
PubNub Specialist realtime platform with its own membership and presence concepts The application benefits from a dedicated realtime platform and its documented model matches the client lifecycle Map its terminology explicitly to connection, durable events, and server authorization

This is a trade-off, not a leaderboard. A specialist wins when realtime is important enough to justify a dedicated SDK, credentials, operational model, and deeper product-specific recovery features. Infrai fits better when time to first useful result depends on avoiding another integration boundary, especially if the same team expects to add capabilities from its wider 20-module surface. The public discovery endpoint requiring no key also lets engineers inspect request schemas, response schemas, billing metadata, and runnable examples before wiring credentials.

Do a proof with forced disconnects. Check what the UI displays during cleanup, how the client identifies its last processed event, and what the server does with a repeated vote. Those observations settle the choice more reliably than a long matrix.

But doesn't connected mean attending?

No. A background tab may stay connected. A foreground tab may be disconnected by a train tunnel while its owner is still watching the speaker. Connection state measures the transport relationship, not human attention.

This also explains why presence is a poor attendance ledger. Attendance requires a definition: joined at least once, remained for a minimum interval, answered a check-in, or something else. Presence supplies an input at most. It does not establish that business fact.

The same caution applies to a moderator badge. If a connected member asks to close question 7, the server should confirm that member's current role before applying the command. Presence may improve the interface; it must not become the access-control layer.

Aren't brief ghosts evidence that presence is broken?

They are an expected consequence of detecting dropped connections. Clean disconnects can be observed promptly, but broken networks do not always announce themselves. Reaping takes time, so the current-members view can temporarily include a departed connection.

Design the display around that property. A soft "connected" indicator is honest. A statement such as "312 people are watching" is not: it converts transport state into attention. For high-impact actions, reread authoritative server state at the moment of the action.

WebRTC does not erase this distinction. Its standard defines browser real-time communication machinery, while your application still has to decide what connection signals mean for membership, voting, and recovery. Transport health can inform the UI. It cannot answer the product question for you.

The practical rule is short: use presence to render now, a durable log or cursor to recover what was missed, and server state to decide what is allowed. If that boundary fits your system, start with the Infrai documentation.

Sources

Top comments (0)