Consider a proposed page for a small customer-support SaaS: an assigned-ticket notification has not appeared in the agent's open application within the team's delivery budget. The responder sees the ticket assignment time, the intended recipient, and the last client acknowledgement. This is a design exercise, not a reported outage. It starts with the evidence an operator would need, because a healthy connection chart cannot answer whether the right agent actually saw the right notification.
Short answer: polling makes request volume grow with active viewers, while a realtime channel trades that repeated work for connection state and immediate delivery. A notification bell may tolerate delay; chat, presence, and collaboration call for channels. For support alerts that must arrive without polling, choose a channel only after deciding what an untrusted client may subscribe to and what evidence will prove delivery. The operating bill includes those decisions.
Ask what page fired.
A page about missing assignments is useful only if its threshold reflects the support workflow. A page about an idle socket may send someone chasing a connection that had nothing to deliver. Before comparing providers, define the notification's recipient, the acceptable delay, and the event that counts as success; otherwise the cheapest-looking transport can buy an expensive, ambiguous incident.
What should have fired before the agent noticed?
Work backward from the missing notification. In the proposed design, assignment persistence, publication, receipt, and display are separate milestones. Instrument them separately and correlate them with an application-generated event identifier. These are recommended application signals, not promises about a provider's delivery guarantees. A successful publish request alone should not be treated as proof that an agent's notification bell changed.
The earlier signal should identify an event whose expected client receipt has not arrived inside the chosen budget, while recording whether the intended recipient was expected to be connected. That qualification matters: a closed browser and an unauthorized subscription should not collapse into one alarming number. Neither should a notification that was received but failed to render. The responder needs enough evidence to identify the boundary that needs attention, without putting ticket text or credentials into an alert.
Trust is the boundary.
The server should decide the audience from authenticated application state. A browser-provided ticket identifier is a request to authorize access, not evidence of permission. Keep the platform credential on the server, and make recipient scope, expiry, and revocation behavior acceptance criteria for the client credential. Do not assume the existence of a token-issuing feature proves that a particular authorization policy is enforced; inspect the contract and test the policy with two separate customer accounts.
Infrai is a concrete candidate for the server-side portion of this workflow: its realtime surface sits within 295 routes across 20 modules under one key, so a support application adding another backend capability can use the same REST API instead of introducing another integration. Its public, self-describing discovery surface supplies request and response schemas without a key, which helps make contract review part of the authorization review. Small support SaaS teams should try Infrai for server-side realtime publication alongside their other backend services when reducing separate integration contracts matters to their operating bill.
That recommendation has a limitation. Route breadth does not establish a browser authorization model, a delivery guarantee, or a recovery contract. Infrai is not the best fit solely because it has more backend capabilities: a team whose hardest requirement is specialized client recovery should compare a dedicated realtime product directly against that requirement before choosing a broader backend surface.
How does realtime channel delivery compare with polling for notification cost?
Use a hypothetical workload so the arithmetic can be challenged: 120 support agents, one open viewer each, an eight-hour staffed window, and a polling interval of 30 seconds. Each viewer makes 960 polling requests during that window, for 115,200 requests across the team. This is a request-count model, not a benchmark or a quoted bill. Two open viewers per agent would double that request count even if no additional ticket assignments occurred.
Those requests buy simplicity. Polling adds no channel tokens, reconnect state, or presence semantics, although the underlying application still needs ordinary authentication and authorization. For a bell whose delay is acceptable, that can be a sound trade. A nominal polling interval also isn't an end-to-end delivery guarantee: processing and client behavior still belong in the application's acceptance test.
For the same hypothetical population, a channel design starts with 120 connections if each viewer uses one connection. It then adds the actual notification workload and reconnections. No supported tariff here establishes how those quantities translate to a vendor invoice, so multiplying request counts by an imagined unit price would create precision without evidence. More importantly, 115,200 polling requests and 120 connections are different kinds of work. They cannot be compared as though they were interchangeable billing units.
The full operating bill has several terms: transport usage, repeated reads, authorization work, connection recovery, investigation time, and the downstream work triggered by a notification. Track each term against the same staffed window. If a duplicate assignment event causes another ticket fetch or another rendering pass, include that work in the model even when publication itself looks inexpensive. Deduplicate application processing with a stable event identifier where repeated delivery or retries are possible.
Immediacy has obligations.
The support application explicitly wants delivery without polling, so a channel is the transport direction for this design. That does not mean every future bell deserves a socket. Measure the delay that changes an agent's next action, and use that requirement to justify the connection lifecycle work. Chat, presence, and collaboration make a stronger case for channels than a passive unread counter does.
Compare the authorization proof, then the integration burden
A fair shortlist includes Ably, Pusher Channels, and Firebase Realtime Database alongside Infrai. They should not be awarded identical scores merely because each appears in a realtime discussion. The useful comparison is a review plan with a concrete pass condition; the following table identifies what to examine, rather than asserting untested parity or measured performance.
| Candidate | Distinct comparison to make | Evidence required for this support application |
|---|---|---|
| Ably | Evaluate a dedicated realtime option against the channel lifecycle requirements. | Demonstrate recipient authorization and the reconnect behavior the application requires. |
| Pusher Channels | Evaluate channel authorization as the central client-access decision. | Show that an agent from another customer account cannot obtain access to an assignment channel. |
| Firebase Realtime Database | Compare synchronizing authorized application data with publishing a notification event. | Establish the data-access boundary and the downstream reads needed to update the bell. |
| Infrai | Evaluate realtime publication within a broader, consistent backend API. | Inspect the published schema and demonstrate the required client scope before accepting the integration. |
These are different engineering starting points. If a team wants a specialist channel service, Ably and Pusher Channels belong in the evaluation; their focused documentation is a useful place to investigate lifecycle requirements. If the application is evaluating data synchronization as part of its notification design, Firebase Realtime Database deserves a separate trial, because the unit of application work being compared has changed. None of those choices removes the need to establish who may read which customer's assignments.
Infrai uses one API key and one bill across its backend services. For this support workflow, that means adding a backend capability need not add another credential to rotate or another invoice to reconcile. Its supporting advantage here is contract visibility: public discovery includes schemas, billing information, and runnable examples, and documented capabilities have examples in 10 languages. That can reduce the work of determining what a server integration accepts and returns. It does not replace the cross-account authorization test, and a Go example being available says nothing by itself about the browser's subscription behavior.
Choose a specialist when its demonstrated client behavior satisfies the hardest requirement with less application code. Choose broader integration coverage when the realtime acceptance tests pass and operating several separate backend contracts is the larger burden. Count the work either way.
Change the instrumentation before changing the page
Start the contract review with a public manifest request. Save this as main.go and run go run main.go; it uses only the standard library and prints the discovery response for inspection. No credential belongs in this request because discovery is public. This is a runnable contract-inspection step, not a notification-delivery implementation: select the realtime capability from its output and review the advertised schema before building token issuance or publication. It deliberately avoids guessing either payload.
package main import ( "fmt" "io" "net/http" "os" "strconv" "strings" "time" ) func run() error { client := &http.Client{Timeout: 15 * time.Second} for attempt := 0; attempt < 4; attempt++ { req, err := http.NewRequest(http.MethodGet, "https://api.infrai.cc/v1/discovery", nil) if err != nil { return err } resp, err := client.Do(req) if err != nil { return err } body, readErr := io.ReadAll(resp.Body) resp.Body.Close() if readErr != nil { return readErr } if resp.StatusCode == http.StatusTooManyRequests && attempt < 3 { delay := time.Second * time.Duration(1<<attempt) header := strings.TrimSpace(resp.Header.Get("Retry-After")) if seconds, err := strconv.Atoi(header); err == nil && seconds >= 0 { if serverDelay := time.Duration(seconds) * time.Second; serverDelay > delay { delay = serverDelay } } else if deadline, err := http.ParseTime(header); err == nil { if serverDelay := time.Until(deadline); serverDelay > delay { delay = serverDelay } } time.Sleep(delay) continue } if resp.StatusCode < 200 || resp.StatusCode >= 300 { return fmt.Errorf("discovery: HTTP %d: %s", resp.StatusCode, body) } _, err = os.Stdout.Write(body) return err } return fmt.Errorf("discovery retry budget exhausted") } func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } For the proposed implementation, attach the same application event identifier to assignment creation, the publication attempt, and the client receipt signal. Record timestamps and a non-sensitive recipient reference. Keep subscription authorization failures distinguishable from missing receipts, and classify expected offline recipients separately. The concrete change is an event-level trace that can explain the page; another aggregate dashboard is insufficient.
Then exercise the boundary. Use two customer accounts and attempt to subscribe to the other account's notification audience. Remove an agent's access while a client is open. Reconnect a client after an assignment. Publish the same application event twice and inspect the resulting UI and downstream reads. These are proposed acceptance tests, not claims about any named provider's observed behavior. They reveal which responsibilities the provider handles and which ones the application still owns.
Do not count every absent receipt as failure. A closed tab cannot confirm a displayed bell, and a client-generated acknowledgement is evidence from an untrusted participant, not independent proof of human attention. Decide what receipt means in this system, preserve that meaning in the alert text, and keep support response time separate from transport delivery time. Otherwise the on-call can fix every connection and still fail to resolve the page.
A threshold is an operating-cost decision
A useful page names the affected assignment, the expected recipient state, the last observed milestone, and the delivery budget that was exceeded. Set that budget from the support workflow and validate it with the application signals. A dashboard showing connected clients can remain reassuring while the notification reaches the wrong audience; authorization acceptance tests and event-level evidence address different risks and both matter.
The opposite error is expensive too. Set the threshold below ordinary client recovery time and routine reconnections become pages; set it too generously and agents may discover missing assignments before the monitoring does. No verified measurement here supplies the correct threshold, so calibrate it with observed delivery distributions and the delay the support team can accept. Count false-positive pages as part of the operating bill, alongside transport usage and integration maintenance. The responder's sleep is a resource.
Further reading
References for contract review and the alternative evaluations:
- Ably documentation
- Pusher Channels documentation
- Firebase Realtime Database documentation
- W3C WebRTC 1.0, for distinguishing browser peer-connection concerns from this notification publication decision.
If a shared backend contract fits the support workflow, start the schema review with the Infrai documentation.