Laravel Reverb vs Phoenix Channels Comparison?

I recently saw that Laravel released Reverb, a first-party WebSocket server for Laravel applications. I’m curious, is there anyone out there who has tried it and also have experience with Phoenix Channels? I’d love to hear a comparison.

One of the reasons that brought me to Elixir was Phoenix’s 1st party support for WebSockets and how quickly you can spin up an app with real-time features without relying on a third party.

I’m wondering…

  1. If you had a small real-time app that doesn’t require the scalability of Elixir and purely want to build as rapidly as possible, would you consider Laravel Reverb?
  2. Do you think there’s anything that either Reverb or Phoenix Channels does better or worse than the other?
  3. Are there specific use cases where you think Reverb or Channels would be more suited?

I know Reverb is still very new, so there’s probably not many who have experience with both Reverb and Channels out there, but I thought I’d asked anyways. :slight_smile:

1 Like

I’m not familiar with Reverb and clearly you’ll get biased answers here, but I can draw some obvious and fair conclusions.

Let’s ignore scale entirely for arguments sake. With Phoenix there’s simply going to be less code to write, you’ll have less problems to think about, and less infrastructure to tinker with. No one offers out-of-the-box distributed pubsub with their built-in real-timer layer. In the case of Reverb, it either uses the pusher model of HTTP posts back and forth between client and server or uses redis for the same purpose. This means messages get load balanced to"¯_(ツ)_/¯" from the server that served the original client. This makes simple things difficult – caching, local lookup, files, etc. You immediately need to resort to some kind of IPC or async jobs to get anything to happen in the system. For example, Reverb’s page calls out the use of redis as a shining example of “scale”.

Built for Scale
Infinitely increase capacity by utilizing Reverb’s built-in support for horizontal scaling
using Redis, allowing you to manage connections and channels across multiple servers.

Not needing redis in the first place is going to scale better. Requiring you to serialize all events thru a datastore designed to be serial in nature, just to get IPC to work, even on the same instance the client is already connected to is a lot work.

The other thing to consider is Elixir’s process model itself. Processes are our unit of concurrency, unit of state, and unit of error isolation. We build all primitives from them like webservers, websockets, agents, etc. They are location transparent, which is a fancy way to say it doesn’t matter where a process lives in the cluster. Your code treats it the same if it was local or across the planet.

What location transparency means for your code is the code you write in your LiveView or channel to handle a message in the system, or broker a message from the client to other users, doesn’t need to consider “now how do I get this form this server to that server”. You just pubsub, or send/2 or GenServer.call and carry on with life. The amount of layers this removes from your concerns is astonishing compared to other platforms.

Take the app I just published for measuring page speed from around the globe worldpagespeed.fly.dev. 350 lines of code including the markup and RPC calls. The RPC calls simply do :erpc.multicall which is part of the erlang standard library to concurrently run a function across a cluster of nodes and get the results. Within the multicall we spawn headless chrome, fetch a web page, and report the results back to the caller pid. The caller pid in this case is just the LiveView process! send(pid, result) makes it way to the handle_info/2 clause of the LiveView regardless of where the work happens. Doing this elsewhere would require some kind of persistent job queue, polling among members, or external dependencies/paid services with glue code to avoid doing those things. In Elixir we do them as a matter of course.

  1. If you had a small real-time app that doesn’t require the scalability of Elixir and purely want to build as rapidly as possible, would you consider Laravel Reverb?

The only reasonable argument for considering Laravel in this context is if you are already productive and heavily invested in Laravel. On any other merit it will fall short for real-time features.

  1. Do you think there’s anything that either Reverb or Phoenix Channels does better or worse than the other?

Most folks are going to come up short when compared to channels. Extra infra (redis), slower (redis), worse scale (php/redis), more code (no native ipc/rpc/pubsub so redis must be used)

  1. Are there specific use cases where you think Reverb or Channels would be more suited?

Same answer as # 1

Hope that helps!

20 Likes

Started typing, but look at all the points I don’t have to make anymore. Awesome post.

EDIT: I’m honestly surprised at how far short other ecosystems realtime feature sets typically fall. Specifically ones that have been made since Phoenix and later LiveView have come out.

7 Likes

I was really happy when Chris cleared up the FUD around using PG2 over Redis last year and how it’s actually advantageous. It feels like this misconception is probably still prevalent, though. I think it would be great to get a note that PG2 is the recommended adapter in the docs (here) and its advantages. This is a little out of my wheelhouse otherwise I would create a draft. I could always try, I suppose, if it’s even desired.

1 Like

PG2 is the default adapter, so it’s not obvious to me why this misconception is held by some folks. The docs make it clear it’s the default no?

  • the default adapter that ships as part of Phoenix.PubSub

But let’s not get hung up on pubsub. My broader point that is that all messaging primitives are backed by distributed erlang, which unlocks superpowers when it comes to writing applications. It’s like if any instance of an object in your favorite OO lang had a globally addressed unique ID that allowed you to call methods rpc style on any instance from any node. It changes the way you write programs and melts away entire layers/deps/infra/paid services.

6 Likes

I didn’t mean to get hung up on any one thing, your post just reminded me of it.

I didn’t want to derail, but from reading what others were saying, I always got the idea to “just use redis in production” which you cleared up as false in your talk last year (or was it earlier this year?). I can only speculate as to how people get that idea. My guess is that “default” maybe comes off as “good enough for development” like certain things in Rails where “the default is :memory” when you’re supposed to swap that out for redis or something else in production. Again, just speculation as to why but definitely a sentiment I got. I can dig up examples. Though maybe it’s not as prevalent as I thought.

2 Likes

We have written about this quite some time ago here: Stateless vs stateful web apps - Dashbit Blog - comparing it to Rails but it is similar. It is exactly as you say: there is just so much work for the developer and much more to maintain when you can’t rely on the features the Erlang VM gives you.

6 Likes

As someone who has been running Rails apps for over a decade (most of them built before I came to Elixir) I can definitely attest to this. I have always loved the creation process using Ruby/Rails, and even getting things into production wasn’t too bad - but whenever you want to upgrade Ruby and Rails, or move servers, or upgrade your server’s OS as it’s reached EOL, it can just be a huge pain. You have to rely on so many things - just on the server there’s things like Passenger Fusion, Memcached/Redis, Sucker Punch/Sidekiq, Docker (if you’re using Discourse) etc.

I look forward to the day we can move everything over to Phoenix/Elixir/Erlang, with LiveView at RC1 that day comes ever closer! :003:

1 Like

Thank you for your answer, Chris. As a newbie to Phoenix and having very limited knowledge on this topic, I very much appreciate the thorough answer. It definitely helps a lot!

And thank you everyone for the additional feedback.

@josevalim Thank you for sharing the article. I just read it. :slight_smile:

@AstonJ Thanks for sharing your experience with Rails. It’s definitely useful insight to have. :pray:

3 Likes