1. It is much easier to trace things through the entire Phoenix stack than it is in Rails. It is also much easier to add things to the Phoenix stack using plugs.
2. Elixir is concurrent, whereas Ruby is not, so when performing long-running processes, you can just do them in Elixir/Phoenix without having to rely on workarounds like Sidekiq, Resque, RabbitMQ, etc.
3. Writing multi-threaded applications is much easier in Elixir than many (if not all) OO languages.
4. Pattern-matching for variables and functions, and binary pattern-matching for parsing text.
5. Mix.
6. BEAM, OTP, and supervision trees.
"When we want to have more control, i.e. persistence on disk, a workers pool, retries, among other things, there are several popular solutions:
Oban: a robust PostgreSQL-based queue backend process system. It has a UI in its pro version Exq: a Redis-based Resque and Sidekiq compliant processing library. It has an open source UI exq_ui verk: same as Exq. Is is compatible with Resque and Sidekiq job definitions"
https://sipsandbits.com/2020/08/07/do-we-need-background-job...
So basically sounds to me like Elixir is doing pretty much the same thing as Ruby. We usually do want more control and disk persistence, so...
edit: > BEAM, OTP, concurrency, this whole thing is solved with the current fashion of devops teams and kubernetes.
This is a hilarious statement which I hope is satire
I do agree with you that's not a huge win compared with Rails, but it is nice to have. I think you'd have to look more at something like "lots of concurrent, long-lived connections" for the real wins over Rails for the BEAM ecosystem. I mean, you can do that in Ruby if you want to, but it's going to be cleaner and simpler with Elixir/Erlang.
> Queue Control — Queues can be started, stopped, paused, resumed and scaled independently at runtime locally or across all running nodes (even in environments like Heroku, without distributed Erlang).
The advantages of BEAM and OTP are that I can spawn new concurrent processes throughout a cluster and then use the actor model to send direct messages to those processes from any other processes, regardless of where the sender and receiver happen to be. I can also easily configure Behaviours so they automatically run on either a single node or every node in the cluster, depending on what they are doing.
In both cases, if a node goes down, Elixir will automatically restart any affected processes on another node. When a process has an issue, I can surgically handle that issue at the individual process level. Kubernetes doesn't handle problems that granularly.
One advantage of Kubernetes is autoscaling. OTP and BEAM don't do that.
By using libcluster, you can combine Kubernetes and BEAM/OTP and get the best of both worlds.