Back to guides
Engineering
July 22, 2026
3 min read

Polling three chat networks without melting

7

7cubit Team

More in Engineering

Polling three chat networks without melting

Unified chat looks like one scrolling panel. Behind it are three different systems: YouTube's quota-metered API, Facebook's paged comments on a live video, and Twitch's IRC connection. Treating them as one generic polling loop would spend quota too quickly, open duplicate sockets, and make an idle dashboard do work for a show that is not live.

ApexStream keeps the chat panel on Hobby and above and gives each platform the collection method it actually needs.

Who gets unified chat

Unified chat read and reply are available on Hobby and above. Free can still send video to its destinations, but it does not get the aggregated chat panel. That is both plan packaging and a practical boundary: polling chat has an ongoing cost, especially on the YouTube quota.

YouTube: cache the identity and respect the interval

YouTube Data API v3 has a default project quota on the order of 10,000 units per day. Listing live chat messages consumes quota, so the system does not rediscover the active broadcast on every tick.

The poller resolves the broadcast's liveChatId once for the session and reuses the cache. It follows the pollingIntervalMillis returned by YouTube rather than choosing a faster loop for the sake of a snappier panel. A 30-second-class floor keeps a few connected destinations from consuming the budget immediately.

If a target returns quotaExceeded, the poller backs off that target and activates a global YouTube breaker for the worker. Quota belongs to the Google project, not to one customer row, so continuing to poll every target would turn one limit into a project-wide outage.

There is also a basic guard: if the station is not live, the dashboard does not poll YouTube at all.

Facebook: follow the cursor

Facebook comments are collected with stored cursors per target. Each run asks for the next page instead of downloading the whole comment thread again. The live video identity comes from the same Redis-backed session context that outbound replies use, keeping reading and writing attached to the same live object.

New messages are normalized into the common chat store and associated with the stream log. Facebook is a pull-and-merge path here, not a WebSocket.

Twitch: keep one IRC session

Twitch chat uses IRC through a client library. The poller maintains clients keyed to the live session and target rather than opening a new connection on every dashboard refresh. Shutdown disconnects them cleanly, and the in-process map helps prevent accidental duplicate sessions within one worker.

IRC messages are converted to the same shape as the other networks: platform, author, text, timestamp, and stream log ID.

What the panel receives

The panel's job is to make the origin visible without asking the host to understand the transport. A YouTube message may arrive through the live list path while Facebook and Twitch messages arrive through the stored, normalized path. The display can still sort them together because the records share the stream log and timestamp shape.

The interface consumes one merged stream of normalized messages. Platform badges remain visible so a host knows where a comment came from. The chat can be a few seconds behind the platform because inbound collection is eventually consistent; sending a reply is a separate outbound action.

Poll runs self-schedule and do not overlap. If one API call takes longer than the normal interval, the next run waits instead of piling another copy of the same work on top.

The rules that prevent a quota fire

  • Only Hobby and above run the unified chat poller.
  • Cache YouTube's broadcast identity and honor its suggested cadence.
  • Back off the target and the worker when the YouTube project quota trips.
  • Reuse Facebook cursors and Twitch IRC sessions.
  • Skip chat polling when the station is not live.
One panel is a user interface. It is not a single protocol. The quiet work is giving each network a reason not to be polled the wrong way.

That is why unified chat can stay simple for the host while the collection layer remains careful about quotas, cursors, sockets, and show state.

When chat falls behind, the useful first question is whether the station is live and whether the platform-specific breaker is active. Reloading the dashboard does not clear a YouTube quota window, and opening more tabs should not create more pollers.