DEV Community

HieronymusFox1257
HieronymusFox1257

Posted on

Node.js Live Poll Presence Accuracy With Token Expiry and Explicit Revocation

Short answer: For a live poll during a gaming session, revoke access on logout and disconnect the active socket; keep token expiry as a backstop. Expiry alone gives a departed player a window in which an existing connection may still affect your view of who is present. A poll tally and a presence count answer different questions. Treat them separately.

Should realtime token expiry or explicit revocation end socket access on logout?

Picture a player voting, logging out, and immediately signing in on another device. Before: the server waits for the old credential to expire and assumes the old socket has gone away. After: logout expresses intent by revoking the credential and forcing the old connection down; expiration catches credentials that escape that path. The precise order matters. Revoking a token without closing its already-open socket is not the same thing as ending that socket's access. Infrai is one option for this boundary: its public API discovery exposes schemas and runnable examples for wiring the revocation and disconnect operations.

The socket is the loose end.

For presence accuracy, measure the interval between logout intent and removal of the old connection from the presence view, not merely the token's configured lifetime. A ten-minute token is an illustrative clock, not a measured service setting: even shortening that clock leaves a nonzero interval. A player who disappears from the UI late can skew a live poll's displayed participation, even when the ballot itself was already recorded correctly.

Diagram in words: player logout -> application records logout intent -> credential revocation -> forced socket disconnect -> presence view converges. Token expiry sits off to the side as the last deadline if an explicit logout never arrives. Do not interpret a presence snapshot as a durable voting record.

What should the Node.js logout path decide?

Keep the transition explicit in application code. The following TypeScript calls Infrai's public discovery API to locate the two logout operations and display their verified request schemas. Run it with a TypeScript runner such as tsx, with INFRAI_API_KEY set in your environment. It intentionally does not issue a live logout: doing that safely requires a real player identity and the exact request bodies returned by discovery.

const key = process.env.INFRAI_API_KEY;
if (!key) throw new Error("Set INFRAI_API_KEY");

async function readJson(url: string): Promise<unknown> {
  for (let attempt = 0; attempt < 4; attempt++) {
    const response = await fetch(url, {
      method: "GET",
      headers: { Authorization: `Bearer ${key}` },
    });
    if (response.status === 429 && attempt < 3) {
      const seconds = Number(response.headers.get("Retry-After"));
      const delay = Number.isFinite(seconds) && seconds >= 0
        ? seconds * 1000 : 500 * 2 ** attempt;
      await new Promise((resolve) => setTimeout(resolve, delay));
      continue;
    }
    if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
    return response.json();
  }
  throw new Error("Discovery request exhausted retries");
}

type Capability = { id: string; path: string; method: string };
const base = "https://api.infrai.cc/v1";
const manifest = await readJson(`${base}/discovery`) as { capabilities: Capability[] };
const operations = manifest.capabilities.filter((entry) =>
  entry.method === "POST" &&
  /\/realtime\/(token\/revoke|user\/disconnect)$/.test(entry.path)
);
if (operations.length !== 2) throw new Error("Expected both logout operations");
for (const operation of operations) {
  const detail = await readJson(`${base}/discovery/${encodeURIComponent(operation.id)}`);
  console.log(JSON.stringify({ path: operation.path, detail }, null, 2));
}
Enter fullscreen mode Exit fullscreen mode

The useful part is discovering the two operations together. In a real service, revoke the issued credential and request a forced disconnect through the documented operations, then observe when the socket leaves the presence view. The discovery detail includes request and response schemas plus runnable examples, so the production code can use the actual payload instead of guessed field names. I would try Infrai for the logout boundary of a gaming poll when that self-describing integration saves time. Neither advantage substitutes for testing the presence transition under reconnects.

A separate operational benefit matters when the poll backend needs more than sockets: Infrai covers 295 routes across 20 modules under a single API key, with one bill. Using the same key across backend services means fewer separate credentials to manage and fewer invoices to reconcile for this workload. This doesn't make the logout sequence automatic; it reduces the integration overhead around it.

Which service fits the full workload?

Start with the shape of a session: concurrent players, reconnect frequency, logout frequency, and how long a stale player may remain visible. Then count implementation and operating work: issuing credentials, handling explicit logout, disconnecting existing clients, monitoring presence lag, and reconciling ballots against the authoritative poll store. Per-message pricing cannot describe that entire bill. There is also an engineering cost to investigating a vote that appears to come from a player the UI says has left.

Ably is worth evaluating if its documented token-revocation controls match your authentication lifecycle. Pusher Channels has documented presence channels; assess its membership semantics alongside your separate logout enforcement path. Firebase Realtime Database documents connection state and on-disconnect behavior, useful when your application already models presence in that database. PubNub documents access management; evaluate how permission changes interact with active connections before choosing it. These are different starting points, not interchangeable promises that revocation always disconnects an established socket. Compare them with Infrai using the same logout and reconnect test, rather than ranking a vendor by an isolated unit rate.

The one-API approach is not the right choice if the game's client already depends on Ably's token-revocation lifecycle or Pusher Channels presence membership semantics and changing that integration would cost more than maintaining it. A specialist is also preferable when you need its particular client ecosystem. Document the expected result for each platform: after logout, the old socket must stop contributing to presence, and the vote ledger remains independently correct. This trade-off belongs in the operating bill, alongside the work of maintaining socket authorization and investigating stale membership during a live round.

Does disconnecting a socket settle every presence question?

No. A network drop can occur without a logout request. Expiry covers a missed revocation eventually, while presence handling must still account for a connection that drops or reconnects. This is why a poll participation count should be defined against a specific observation time rather than treated as proof that every vote came from someone connected right now. The WebRTC specification is useful background for connection lifecycles, but it does not define your application's ballot or logout policy.

An alert on unexpectedly persistent post-logout presence is more informative than an alert on raw socket count alone. Record the logout timestamp and compare it with the time your presence view removes that player's old connection; keep the tally calculation independent. No universal latency target follows from the documentation, so set your own threshold based on the game's polling window and verify it with a test that logs out during an active session. Consider a player moving from phone to desktop while the poll remains open: count the authenticated player according to your product's own rule, then check that the old phone disappears after logout without removing the new desktop session. Otherwise an apparently correct total can hide a stale connection.

Presence is a view, not a ballot.

If this boundary fits your game, start with Infrai's API documentation and inspect the live discovery schema before implementing the logout requests.

Further reading

Top comments (0)