# RFC - WebSockets
## Scenario
We are looking to have a realtime WebSockets experience for the Activity Feed page where transactions from the mempool are streaming into the feed, in realtime.
This needs to be publishable from our Rails backend, and subscribeable from our React frontend. Currently this is all in one repo, but the solution must also work if we extract the React FE into its own repo.
We initially discussed looking into a couple different technologies: ActionCable and Socket.io.
## Options
As best I can tell from the research I did into Socket.io, it is not a viable option. Reason being, it currently only supports and maintains backend server implementations in Node.JS, Java, and Python. See: https://socket.io/docs/v4/
There are some older WebSocket options for Rails like [Faye](https://faye.jcoglan.com/); however that is much more convoluted, requires more configuration and maintenance at all layers, and much less community support since the release of ActionCable.
In theory there are other general pub/sub options we can look into. But for this particular WebSockets case, there are two main options I think we should consider: ActionCable and Ably.
### 1 - ActionCable
I was able to get everything up and running for our requirements, in this [ActionCable spike PR](https://github.com/BitClout-Pulse/bitclout-pulse-rails/pull/113). I also created [this Loom screencast](https://www.loom.com/share/661ea4041a284349bdc52dc85b585017), walking through how it works.
**Pros**
- Designed to work seamlessly with Rails, specifically for WebSockets
- Works as desired with our auth system
- Lots of community support and documentation
- Highly maintainable for any future developers, as it follows all of Rails' conventions
- Works as desired in Heroku
- Encapsulates the logic very tightly, allowing for any future refactoring
**Cons**
The unknowns are around scaleability. [This article](https://ably.com/blog/rails-actioncable-the-good-and-the-bad) explains very well the potential issues that could come with WebSockets at scale, with ActionCable. Take it with a grain of a salt, as this is written by an ActionCable competitor, but does provide some insight into things we may need to consider down the line.
One inherent con could be a single server. The Rails docs do discuss [configuring a standalone cable server](https://guides.rubyonrails.org/action_cable_overview.html#standalone), so that is something that we could explore as we get more data around usage.
#### 2 - Ably
[Ably](https://ably.com/) is a platform specifically designed for a scaleable, global, [realtime WebSocket experience](https://ably.com/pub-sub-messaging). Ensuring message ordering, delivery, uptime, and more. They have well maintained gems and packages for a [Rails backend](https://github.com/ably/ably-ruby) and a [JavaScript frontend](https://github.com/ably/ably-js).
**Pros**
- Highly scaleable, ensuring everything we would want and expect in such a provider
- Designed for developers
- Well maintained gems/packages for Ruby/JavaScript
- Extensive documentation
- Numerous third party integrations and plugins (i.e. AWS Kinesis/SQS/Lambda, Zapier, etc.)
**Cons**
Really the only real con is [the cost](https://ably.com/pricing). At this point we do not have any usage data to make reliable cost comparisons. That said, I would have to assume that testing the waters with ActionCable and Heroku will be overall cheaper, in the v1/v2/etc. stages.
Not a con, per se, but the backend implementation does require the use of [EventMachine](https://github.com/eventmachine/eventmachine). I am not familiar with any pros/cons here, and would need further investigation to know if this is a concern or not.
## Recommendation
I would recommend we implement our v1 in ActionCable. The implementation is very light and straightforward. I propose we begin by testing how the existing spike would work when deployed to staging, and then behind a feature flag in production. We can simultaneously work on the React FE implementation, and deploy/test as we go.
We can then gather data on usage and issues, and then iterate and discuss from there.