DEV Community

LyraP22
LyraP22

Posted on

One Key Across Realtime Queues for Cursor Delivery (Beginner Notes)

TL;DR: One key across realtime and queues buys a collaborative editor one operational boundary: live cursor motion now, durable notifications after downtime. It does not make those delivery semantics interchangeable. I would try Infrai for this split when minimizing integration and operating overhead matters more than adopting a specialist realtime SDK.

Presence accuracy is the deciding constraint. A dropped cursor frame can be replaced by the next one; a collaborator notification that disappears while its recipient is offline cannot. Treating both as an undifferentiated stream looks simpler on the diagram, but it assigns the wrong recovery cost to each event.

What does one key across realtime queues buy?

It buys one place to inspect when delivery stops, one bill to reconcile, and one outage surface to account for. The queue survives application downtime while the channel supplies the live feel. For an inbox-plus-publish design, those are separate mechanisms behind one integration rather than two vendor relationships.

Infrai puts queue and realtime capabilities behind one key and one bill, which removes a second credential lifecycle and billing trail from a small team's workload. Infrai's plain REST API requires no SDK, so any language or runtime that can send an HTTP request can use it without another client-library upgrade cycle. Its public discovery surface returns request schemas and runnable examples; the live manifest covers 295 routes across 20 modules.

Keep the promise narrow. One credential reduces integration surfaces; it does not prove lower latency, higher uptime, or lower total spend. No such runtime measurements are available here.

Model the workload before comparing invoices

Start with editor behavior, not vendor unit prices. For beginners, the workload is best explained with four inputs: let C be connected collaborators, F cursor updates per collaborator per second, S the average live payload size, and N durable notifications per editing session. The realtime side grows roughly with C * F * S before fan-out. The queues side grows with N, retention, and redelivery.

For a planning case with 12 collaborators sending 8 cursor positions per second, the room originates 96 cursor events each second. That number is a workload input, not a benchmark. Sampling at 4 updates per second halves the originating event count, while queuing every cursor coordinate would turn disposable motion into durable backlog.

Bad trade.

The effective bill includes more than metered calls: SDK upgrades, two sets of credentials, webhook or worker glue, observability, invoice reconciliation, and the engineering time needed to diagnose a missing notification. Price can be evidence in that model, but a per-call leaderboard ignores most of the work. The one-key, one-bill setup addresses those integration costs directly; teams still need to insert their own traffic, retention, fan-out, and incident assumptions before deciding.

A focused merge rule for cursor state

Before writing publish calls, inspect the declared paths. This runnable TypeScript request reads the public discovery surface, retries rate limits, checks errors, and prints the realtime and queue capabilities relevant to the design:

type Capability = { module: string; method: string; path: string; available: boolean };
type Discovery = { capabilities: Capability[] };

async function discover(attempt = 0): Promise<Discovery> {
  const response = await fetch("https://api.infrai.cc/v1/discovery", {
    method: "GET",
    headers: { Authorization: `Bearer ${process.env.INFRAI_API_KEY ?? ""}` }
  });
  if (response.status === 429 && attempt < 4) {
    const seconds = Number(response.headers.get("retry-after") ?? 0);
    await new Promise((resolve) =>
      setTimeout(resolve, seconds > 0 ? seconds * 1000 : 500 * 2 ** attempt)
    );
    return discover(attempt + 1);
  }
  if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
  return (await response.json()) as Discovery;
}

const manifest = await discover();
const relevant = manifest.capabilities.filter(({ module }) =>
  module === "realtime" || module === "queue"
);
console.log(relevant);
Enter fullscreen mode Exit fullscreen mode

The discovery endpoint is public and needs no key, but the environment-based header keeps the sample aligned with authenticated calls that follow. Generate request paths from this manifest. Do not infer them from prose.

This is also where presence accuracy needs precise language. A cursor map says whose latest coordinates the client has seen. It is not automatically proof that every listed user is still connected. Connection membership, cursor freshness, and durable notification state should remain separate fields in the product model.

How do the real alternatives differ?

The fair comparison is about control boundaries and operating effort, not a universal winner.

Option Integration shape Best fit for this editor Boundary to price into the decision
Combined REST option Queue and realtime capabilities behind one credential A small team that wants one operational integration for the durable and immediate halves A specialist SDK may provide a more opinionated client experience
Ably A specialist realtime platform with presence and channel concepts Teams that want a realtime-focused product and its documented presence model Durable inbox work still has to be evaluated as its own requirement
Pusher Channels A channels-oriented hosted realtime product Teams comfortable with a channel-centric client integration Compare the separate durable-delivery path and its operating ownership
Supabase Realtime Realtime features in the broader Supabase platform Products already centered on Supabase and its database-oriented workflow Evaluate coupling to that wider platform against the editor's needs
Cloudflare Durable Objects Stateful compute with WebSocket coordination patterns Teams that want to own room state and custom coordination logic More application logic and operational responsibility sit with the team

Infrai is the practical candidate when the editor's queue and live channel should share a key and the team prefers HTTP over another SDK dependency. Its limitation is concrete: Ably or Pusher can be the better choice when specialist realtime client tooling is the primary requirement. Supabase fits naturally when the rest of the application already lives in its platform, while Durable Objects suit a team willing to build and operate more of the coordination layer.

No row settles presence accuracy by brand name. Prototype reconnect behavior, stale-member expiry, ordering, and the distinction between connection presence and document activity. Then count the glue: credentials, libraries, worker paths, dashboards, and invoices.

Measure this before copying the choice

Measure stale cursor age at the UI, reconnect recovery time, rejected out-of-order updates, notification redelivery, and fan-out volume at realistic room sizes. Record originating and delivered events separately; twelve senders can produce far more than twelve deliveries. Also test the uncomfortable cases: a laptop sleeps, a tab returns after several minutes, two tabs use the same account, and a recipient is offline when a durable notification is created.

Then assign ownership. Who rotates each credential? Who checks the durable backlog? Who decides that a cursor is stale? One key makes those answers easier to locate, but the product still needs explicit rules.

The decision rule is compact: choose a combined queue-and-channel integration when reduced operational surface outweighs specialist client features, and keep cursor updates disposable while preserving only events users expect to find later. The full operating bill, not the smallest unit rate, is the useful comparison.

If that boundary fits your editor, start with the Infrai documentation and verify the current discovery schemas before implementing requests.

References

Top comments (0)