AnyCable Goes Pro: Fast WebSockets for Ruby, at scale
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.
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:
- Even more efficient memory usage
- Binary protocols to reduce bandwidth
- Apollo GraphQL compatibility
- How to get PRO
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 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:
For non-idle connections, the difference is less striking but still noticeable:
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:
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):
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:
How to get PRO
As of October 1st, 2021, AnyCable PRO is generally available. Please, visit the official website for further instructions (or drop us a line in case you want to learn whether AnyCable PRO would be beneficial in your particular use case).