DEV Community

EmersonPrice3718
EmersonPrice3718

Posted on

Realtime Channels in 2026: What They Actually Deliver and Never Store

Short answer: A realtime channel delivers an event to subscribers connected now; it does not retain an inbox. For a property-management app, store each tenant notice in your database and use a channel to tell active clients that their view should refresh. The bill to examine first is therefore the retained notice history, not an imagined channel archive. If a notice must still appear after a reload, its durable record belongs in storage you control.

What actually accumulates on the bill?

Suppose a manager sends one maintenance notice to 200 units and the product promises that each resident can see it later. If the application stores one notice plus 200 recipient delivery or read-state records, the retained term grows with recipients: 201 records for that notice before indexes and revisions. That is an illustrative schema calculation, not a measured vendor bill. Publishing an event does not remove those records. Conversely, keeping an event for every transient presence change in a permanent history would make a short-lived signal into a retention obligation. Count retained rows, their indexes, and the period you keep them before optimizing transport calls.

The useful change is to retain the notice and recipient state but publish only a small notification signal, such as a notice ID and a property-scoped channel identifier. A connected client fetches authoritative content from the application. A disconnected one fetches it on return. No replay promise is smuggled into the channel.

This also separates two clocks: a durable notice can remain visible for months under your retention policy, while an online indicator is meaningful only near the moment it was observed. Treating them as the same data type makes both presence accuracy and deletion policy harder to reason about.

What does a realtime channel actually store after everyone disconnects?

Nothing about the delivered events. A channel is transport with subscribers, not a database table or an unread-message queue. Best-effort delivery is a design property: a client that loses its connection can miss a signal, so the client must reconcile its state from the database after reconnect or reload. A signal can carry a version or ID, but that does not make it proof that every recipient received the underlying notice.

No receipt follows from a publish.

Presence deserves a stricter definition than "got my last event." Decide whether the UI means an active connection, recent application activity, or a resident who actually opened the notice. Those are different observations. For example, if an app labels a resident "online" solely because its last notification publish succeeded, a disconnected resident can be shown as present; publication says nothing about that resident's connection. Use an explicit presence observation for the live indicator and a stored read event for read status. Neither should be inferred from the other.

On write, commit the notice and its recipient association first, then emit a signal. If publication fails after the commit, reconciliation still finds the notice; for a stronger guarantee that a committed notice eventually triggers a publish attempt, use a transactional outbox and an idempotent worker in your own system. This is an architectural pattern, not a claim that any compared transport provides an outbox. If the signal arrives before a replica or cache exposes the new notice, retry the read according to your application's consistency policy instead of treating the signal payload as durable truth.

Which transport fits a property inbox?

The meaningful comparison is what a disconnected resident can recover and what presence actually measures. No transport should silently become the system of record for lease notices.

Option Useful boundary What to verify before choosing
Ably Channels Managed pub/sub with documented history and presence features History and presence are separate features; define how long history is available and still keep the application's authoritative notice and read state.
Pusher Channels Managed channels with documented presence channels Presence membership reflects connected clients, not proof that a notice was read or retained in the property inbox.
Firebase Cloud Firestore Persistent documents with realtime listeners The document store can serve as the notice source of truth, but a snapshot listener is not, by itself, a precise definition of active user presence.
Supabase Realtime Database-change broadcasts and presence for an existing Supabase stack Keep durable notice records in the database; a presence state is not a read receipt.
Infrai realtime channels A plain REST API for channel operations and publishing, callable from any HTTP-capable language without an SDK version to manage Treat delivery as best effort and keep reload history in your own database; evaluate live presence separately from durable recipient state.

Ably is attractive if managed presence and an optional history feature fit your recovery requirements; determine the actual retention configuration and semantics before relying on history. Pusher offers a clear presence-channel model, although presence membership does not substitute for a persisted inbox. Firestore changes the architecture more substantially: the database itself can hold the notices and listeners can report changes, so it is a reasonable choice when the team wants that document model as its source of truth. Supabase Realtime is especially relevant when notice records already live in a Supabase database. Infrai fits when an existing backend already owns the inbox and wants an HTTP publishing surface without adding a language-specific client dependency. Its REST interface is an integration advantage, not a reason to claim that a channel stores missed notices. Its limitation is the channel's lack of retained delivery history: if managed replay is a hard requirement, choose Ably's history feature or a durable database listener instead.

Infrai also offers one key across 295 routes in 20 modules; a property application using more than notifications can manage one credential instead of separate keys for each backend capability. Its self-describing public discovery surface exposes request schemas before an integration commits to a payload. That reduces credential and schema drift across the notice workflow. It does not reduce the need for an application-owned notice database.

To inspect the current descriptor for a publish operation, set INFRAI_BASE_URL to the service's v1 base URL and INFRAI_API_KEY to your key, then run this Python snippet; it makes a discovery request and prints the matching capability rather than guessing a publish body's field names. The operation is inspection, not a publish, so there is no write to retry or duplicate. When implementing the actual write, use an application-generated event ID or idempotency key and handle a 429 with backoff.

import json
import os
import time
import urllib.error
import urllib.request

url = os.environ["INFRAI_BASE_URL"].rstrip("/") + "/discovery"
for attempt in range(5):
    request = urllib.request.Request(
        url,
        headers={"Authorization": "Bearer " + os.environ["INFRAI_API_KEY"]},
        method="GET",
    )
    try:
        with urllib.request.urlopen(request, timeout=15) as response:
            data = json.load(response)
        break
    except urllib.error.HTTPError as error:
        if error.code != 429 or attempt == 4:
            raise RuntimeError(f"Discovery returned HTTP {error.code}: {error.read().decode()}") from error
        retry_after = error.headers.get("Retry-After", "")
        time.sleep(int(retry_after) if retry_after.isdigit() else 2 ** attempt)
else:
    raise RuntimeError("Discovery did not succeed")

matches = [item for item in data["capabilities"]
           if item["method"] == "POST" and item["path"] == "/v1/realtime/publish"]
if not matches:
    raise RuntimeError("Publish capability missing from discovery")
print(json.dumps(matches[0], indent=2))
Enter fullscreen mode Exit fullscreen mode

The channel count is seldom the retention decision. A property-scoped channel can route timely invalidations; the costly conceptual mistake is to use a broadcast as the only copy of a notice that residents are entitled to revisit.

What should the client do when it returns?

Fetch the stored inbox before relying on new signals. Then subscribe and reconcile again if the subscription window can race with writes. Deduplicate by the database notice ID, and persist read state through your application's authenticated write path. This sequence tolerates duplicate signals and missed signals without inventing exactly-once delivery.

For the presence label, choose an expiry and wording consistent with the underlying observation. "Connected" should follow connection membership if that is what the provider measures; "read" requires a durable acknowledgement in the application. A property manager deciding whether to telephone a resident should never be handed a green dot that actually means only "we published successfully."

The deliberate omission is an event-by-event archive of transient signals. That keeps a transport event from becoming a second, divergent notice database. It costs you forensic detail if you later need to reconstruct exactly which transient update a device saw, and it means reconnecting clients must read stored state rather than replaying every broadcast. If that reconstruction is a requirement, record a bounded delivery audit separately, with explicit retention and privacy rules; do not quietly call the channel history an audit log.

Further reading

Top comments (0)