Backend

AnyCable Goes Pro: Fast WebSockets for Ruby, at scale

If you’re interested in translating or adapting this post, please.

A year into AnyCable’s 1.0 release, we introduce the Pro version. It adds special ingredients to our performant and scalable real-time formula that keeps the familiar Rails Action Cable API for full-duplex messaging and backs it with the blazing-fast Go server for WebSocket connections. Going Pro can reduce your memory footprint by additional 40%, save bandwidth costs, and get you priority support. And it’s all free while in beta!

AnyCable has always been and will always be an open source project at its core. Started as a single library half a decade ago, it grew into a current family of tools under a dedicated GitHub organization. However, as AnyCable keeps getting traction in the Rails and Ruby ecosystem, keeping all tools up to date while developing new features stops being a hobby and turns into a separate enterprise that will only benefit from a proper support mechanism.

As AnyCable is designed to ease the growing pains of applications that depend on real-time, full-duplex communications with thousands of always-connected clients, its adopters tend to play in the big league. Their needs often outpace the leisurely rhythm of community-driven open source development. And while the core of the code behind AnyCable will always remain free, open source, and open to community PRs, we’ll be adding commercial features on top—to help Pro users reach an even bigger scale.

We’ll be adding Pro-only, commercial features on top of the existing codebase to help customers handle extra high load.

One may ask: “What about sponsorship?”. We have it, too. But it never meant to be fuel for the project development; it’s just to show gratitude.

If you are not yet familiar with AnyCable, please take time to read the original introductory post that describes the architecture and the performance characteristics of the open core. Make sure to keep the current tab open and come back to learn about the brand new commercial features:

In this post, we’ll be focusing on three aspects of AnyCable Pro: memory footprint, support for binary protocols, and effortless GraphQL compatibility.

More efficient memory usage

One of the main reasons Rails developers choose AnyCable over the built-in Action Cable is the massive reduction in RAM costs.

AnyCable’s Go server uses up to 3 times less memory than the Action Cable’s default backend. Still, we’ve found room for even more improvement—for scenarios when clients act mostly as consumers and not producers (the number of messages sent to a server is much less than the number of messages broadcasted from a server to the clients). Think your “social media” real-time notification system.

For Action Cable benchmarks, we run eight Puma processes. Read more in the benchmarks docs.

For the Pro version, we rewrote the underlying client-server communication mechanism from the surefire “two goroutines per connection” to the more nuanced “goroutines pool plus epoll/kqueue” technique, which gave us a further boost:

AnyCable Pro vs. AnyCable vs. Action Cable memory usage handling 20k idle clients

Handling 20k idle connections

For non-idle connections, the difference is less striking but still noticeable:

AnyCable Pro vs. AnyCable vs. Action Cable memory usage running broadcast benchmark for 5k clients

Running broadcast benchmark for 5k connections

Heroku has a hard limit at 10,000 open files (and thus, TCP connections). That’s why we can only benchmark up to 9k connections per dyno.

This improvement is especially useful for containerized or otherwise walled-off deployments (Kubernetes, Heroku), where you’d prefer scale by adding new smaller instances rather than upgrading to more powerful and expensive “machines”. Here are the results of benchmarking different AnyCable versions against Action Cable on a single Heroku 1X dyno:

AnyCable Pro vs. AnyCable vs. Action Cable memory usage handling 9k idle clients on Heroku

Handling 9k idle connections on Heroku 1X dyno

We’ve reduced the amount of utility memory required for handling connections from O(N) to O(1), but we still need to keep client states—hence the overall memory growth is still linear. We plan to do more work on state reduction and compaction in the future Pro versions.

Support for binary protocols

Action Cable protocol uses JSON payloads in WebSocket messages during the client-server communication. JSON is a simple, human-readable (and writable) format; programmers love it. However, machines are much better at digesting binary formats, unreadable for humans: they are more compact and faster to process.

AnyCable Pro adds support for the two most popular binary formats: Msgpack and Protocol Buffers.

Using binary communication drastically decreases the amount of data sent over the network. You can find some numbers in the AnyCable Pro documentation. See, for example, the difference in the data sent out during the Websocket Shootout benchmark (5k connections, 1.5m messages):

Protobuf vs. Msgpack vs. JSON

Bandwidth comparison

Currently, adopting binary protocols requires monkey-patching client JavaScript libraries. That approach works fine, but we’ve already started implementing our own AnyCable JS SDK that will enable us to introduce protocol-level features more easily in the future. Stay tuned!

Effortless Apollo GraphQL compatibility

Last but not least, we’ll showcase the Apollo GraphQL protocol support.

Currently, using GraphQL subscriptions with graphql-ruby backend and Action Cable as transport requires using a custom Apollo “link”. This approach, however, has a couple of problems. Firstly, most developer tools aimed at GraphQL developer experience have no clue about Action Cable but support the extremely popular Apollo right out of the box. Secondly, it is much easier to find a working and up-to-date client library for Apollo (for instance, React Native does not provide an Action Cable library officially).

With AnyCable Pro, you can enjoy all of Apollo’s tooling without ever mentioning Action Cable in the client code! Just connect your WebSocket transport to <anycable-pro-go>/graphql endpoint, and that’s it. AnyCable translates the incoming Apollo messages into the corresponding Action Cable actions and vice versa.

For example, you can use subscriptions in the Apollo Studio:

Using Apollo Studio with AnyCable

Early access program

We’re just at the very beginning of AnyCable’s new and exciting journey into the commercial open source, and we are eager to share everything we’ve built so far with you—at no cost while the features are still in beta.

Sign up for AnyCable Pro free early access program here and be the first to try out new features

We are launching a early access program: drop us a line in a contact form, tell us about your AnyCable usage and which problems you are trying to solve with cables—and we’ll give you early access to the Pro version for 2 months, for free! You can also expect priority support from me and fellow Martians behind this project.

Humans! We come in peace and bring cookies. We also care about your privacy: if you want to know more or withdraw your consent, please see the Privacy Policy.