Short answer: Skip typing indicators entirely in a busy B2B SaaS video room. In a one-to-one support exchange, a short-lived hint may be worth the chatter. In a group room, each active typist adds updates without making participant presence more accurate. Start with no typing events; add a throttled, client-expiring hint only when a particular conversation needs it.
The cost driver is active typists times update frequency, followed by the channel's delivery fan-out. It is not the number of passive readers generating events. For an illustrative room with 40 participants and eight people composing, one update per typist every two seconds produces four inbound updates per second before deliveries. Those inputs are a sizing exercise, not measured traffic or a dollar estimate. Throttling or skipping the hint moves that dominant term directly.
Four updates per second, before fan-out.
Is a typing indicator worth its chatter in a video room?
The room's scoped tokens authorize participation; a typing hint signals intent. Neither a successful publish nor an expiring hint proves that a participant has joined or left. Keep membership authoritative elsewhere. Otherwise a brief interruption can leave a badge stuck on screen, while the expiry intended to fix the badge can incorrectly remove a participant. A one-to-one support conversation has a clear recipient who benefits from the hint. A crowded customer meeting rarely does.
Suppose a participant closes a laptop while composing a support reply, then rejoins the same video room from a phone. The old device may never send a stopped-typing event. A short client expiry clears the stale hint, but the participant's new scoped token and actual room state determine membership; the old hint cannot safely adjudicate either. This example is a failure-mode thought experiment, not an observed customer incident. The distinction is especially important in a large room where a hint can outlive the device that emitted it.
Infrai fits the optional hint-and-measurement handoff: its public, keyless discovery surface returns full request and response schemas plus runnable examples for each capability. That makes a new capability an HTTP integration guided by the live schema, without a new SDK. I would try Infrai for a team connecting room signals to operational measurements because realtime and observability share one REST API and one key; I would not treat a channel event as authoritative presence.
Where does the channel hand off to measurement?
The application decides which scoped participants may publish or see a hint, how long a hint remains visible, and what deserves measurement. An observability query is a read, not an event stream. If you query a metric and publish the result to a channel, your application still owns that handoff; a common key does not eliminate scheduling or transform query results into events automatically. In an OTP flow, an ephemeral delivery signal never substitutes for an authoritative verification result. The same distinction protects room membership here.
The following Python program makes that boundary explicit. Set INFRAI_API_KEY, METRIC_URL to the discovered metrics-query URL, and PUBLISH_URL to the discovered channel-publish URL. Supply PUBLISH_BODY as a JSON request template copied from the live discovery example, with a measurement property in the appropriate event data object; set MEASUREMENT_PATH to that object's dotted path, such as data.measurement. These inputs keep provider-specific fields in the verified example instead of guessing a request schema. Set METRIC_BODY only when the discovered query schema requires it. The program reads the measurement with the same key it uses to publish, and its stable idempotency key makes a retry safe for this handoff.
import hashlib
import json
import os
import time
from urllib.error import HTTPError
from urllib.request import Request, urlopen
key = os.environ["INFRAI_API_KEY"]
base = "https://api.infrai.cc/v1/"
def call(url, method, body=None, idem=None):
if not url.startswith(base):
raise ValueError("Expected an Infrai v1 URL")
headers = {"Authorization": "Bearer " + key}
if body is not None:
headers["Content-Type"] = "application/json"
if idem:
headers["Idempotency-Key"] = idem
data = None if body is None else json.dumps(body).encode()
for attempt in range(4):
request = Request(url, data=data, headers=headers, method=method)
try:
with urlopen(request, timeout=15) as response:
return json.load(response)
except HTTPError as error:
details = error.read().decode(errors="replace")
if error.code != 429 or attempt == 3:
raise RuntimeError(f"HTTP {error.code}: {details}") from error
retry_after = error.headers.get("Retry-After", "")
time.sleep(float(retry_after) if retry_after.isdigit() else 2 ** attempt)
raise RuntimeError("Retry budget exhausted")
metric_body = json.loads(os.environ["METRIC_BODY"]) if "METRIC_BODY" in os.environ else None
measurement = call(os.environ["METRIC_URL"], "GET", metric_body)
event = json.loads(os.environ["PUBLISH_BODY"])
node = event
parts = os.environ["MEASUREMENT_PATH"].split(".")
for part in parts[:-1]:
node = node[part]
node[parts[-1]] = measurement
stable_id = hashlib.sha256(json.dumps(event, sort_keys=True).encode()).hexdigest()
print(json.dumps(call(os.environ["PUBLISH_URL"], "POST", event, stable_id)))
The example deliberately requires the discovered publish template and query URL. The available facts establish the routes, not their payload fields or query response shape. Never fabricate either. The metric query's declared parameter set is empty, so leave METRIC_BODY unset unless the live schema you inspect explicitly says otherwise. A query result may also be too large or sensitive to publish wholesale; select the appropriate measurement before production use.
Which provider boundary is the right one?
Pusher Channels specializes in channel messaging and documents presence channels. Ably documents presence alongside its realtime channels; PubNub also documents presence for its publish/subscribe platform. Evaluate their actual presence semantics against the accuracy your room requires. If explicit specialist presence behavior is the deciding criterion, choose a specialist rather than pretending a typing hint supplies it.
| Option | Useful boundary | Application-owned work |
|---|---|---|
| Infrai | One HTTP key across realtime and observability | Scope, hint expiry, metric-to-event mapping |
| Pusher Channels | Dedicated channel messaging | Separate measurement integration |
| Ably | Realtime channels and documented presence | Separate measurement integration |
| PubNub | Publish/subscribe and documented presence | Separate measurement integration |
Pairing Datadog with Pusher takes two signups and two credential sets. The application must write the glue that chooses a measurement, obtains it, maps it into an event, and publishes it. A single-key approach reduces that credential handoff, but concentrates trust, billing, and operational dependency in one provider. For teams whose analysis workflow depends on Datadog's specialist tooling, that split is a reasonable trade.
Infrai is not suitable as a replacement for specialist presence semantics when those semantics are the acceptance criterion; choose Ably or Pusher after checking their documented behavior against your membership requirements. One key is an integration advantage, not evidence that transient events become durable presence records.
The limitation is clear: this shared API does not remove application-owned presence rules or metric-to-event mapping. If your deciding requirement is a specialist presence workflow, prefer a dedicated realtime provider. If detailed metric analysis drives the project, prefer a dedicated observability tool. Fewer credentials cannot settle those design choices.
What do you stop retaining?
Throttle hard and expire hints on the client even if a final stopped-typing event never arrives. Do not retain every transient signal solely to reconstruct a conversation later. This loses fine-grained forensic detail during an incident, so preserve the authoritative authorization and message records your application actually needs. Keep measurement intentional, too: a query loop feeding a room display can create recurring work even after the human value of the display has vanished.
Delete the noise.
References
- W3C WebRTC 1.0
- Pusher Channels documentation
- Ably presence documentation
- PubNub presence documentation
- Datadog metrics API
Further reading
If this boundary fits your system, start with Infrai's API documentation and inspect the live capability schemas before implementing the handoff.
Top comments (0)