Today I ate a snowflake… oh, wait a sec, this is not Twitter :) This is our monthly newsletter about the world of realtime web development.
If you happen to be around San Francisco next week, come say “hi!” to us at the SF Ruby Meetup where Team AnyCable will be hanging out (and giving talks). Or you can join the live stream 🎥!
Posts
Back to Basics: Why We Chose Long Polling Over WebSockets
This story of favoring long-polling over other transports in 2025 is an interesting read. Just check out the analogy:
Short polling is like a train that departs strictly according to a timetable—it leaves the station at fixed intervals regardless of whether there are passengers or not.
WebSockets, on the other hand, are like having a dedicated train line always ready to transport passengers.
Long polling? It's like a train that waits at the station until at least one passenger boards before departing.
(Although I would say that WebSockets are more like taxis; there is no overhead for pulling a whole train just for the sake of a single passenger.)
Learn how to make Rails Action Cable instrumentation-friendly and expose metrics to Prometheus (using the Yabeda framework).
Guide to Twilio + OpenAI Realtime on Rails (Without AnyCable)
One more blog post about stitching Twilio Media Streams and OpenAI Realtime together; this time, in pure Ruby (as you might guess from the title). We shared our AnyCable-ed version a couple of issues ago.
Releases
A new release of the future Action Cable brings various performance improvements. The most significant one is fastlane broadcasts support (or less JSON encoding/decoding). See more in this PR. And here are some benchmarks:
This release brings AnyCable presence (which we’ve announced the last time) to Action Cable channels:
A new chapter in the life of our friends from Centrifugo.
Frame of curiosity: ping pong 🏓
Persistent network connections (like WebSockets) require a mechanism to inform each communication end (say, client and server) whenever the other one unexpectedly goes out of sight, to distinguish silence from disrupted connectivity. This discovery can be implemented at a different level (or layer). For example, TCP protocol supports sending tiny keep-alive packets to detect network failures (as we explain in our documentation).
Usually, higher-level protocols (Application Layer) implement their own heartbeats. The primary reasons are better control over heartbeat logic (e.g., intervals, etc.) and proxy/firewall handling (as some intermediate nodes might skip keep-alive packets).
Both WebSockets and HTTP/2 come with their own heartbeats: PING/PONG messages. Yet almost all realtime protocols/frameworks implement their own keepalive logic! We can see “ping”-”pong” (or “ok”-”ko”) messages passing through every WebSocket connection. Why so? Primarily because pings and pongs are hidden from client-side (browser) code: you can’t initiate them, you can’t listen to the corresponding events, you don’t even know if the server uses them or not (more info here).
So, we add ping-pong-like features to our realtime protocols.
Let’s consider Action Cable, for example. The server sends a “ping” message to every connected clients every 3 seconds. The client uses this pings to detect if the server is still alive and operational (i.e., it not only checks connectivity but verifies that the server can do its job). Here’s an important difference from lower-level heartbeats: the network could be up, while the server (in this case, a Ruby application) experiences performance issues—it’s better for clients to know about that and try to re-connect to a different node*.
In many cases, “ping” messages (when accompanied by “pong”-s) are used to measure the latency between the peers (see the Action Cable metrics article linked above). That’s another reason for having them.
Thus, protocol-level heartbeats are justified. However, at scale, the number of transmitted messages could be enormous. For example, with 10k Action Cable clients, the server sends ~3k messages per second.**
From the client-perspective, receiving and sending pings is also not free, especially, for mobile devices: you can easily drain power by constantly asking a mobile app to process pings. (That’s why we made it possible to configure ping interval on per-client basis in AnyCable.)
Know your pings!
* Ping in Action Cable are only goes in one direction, from server to clients; unfortunately, that doesn’t prevent all the possible networking problems. See this PR for discussion.
** The calculations are borrowed from this issue.