Here is actually a good article comparing the JVM with the BEAM:
https://www.erlang-solutions.com/blog/optimising-for-concurr...--
And some of my own thoughts with a few more links:
The runtime system that Erlang runs on, called the BEAM, is special in that it is engineered for distributed systems and fault tolerance in a way that the JVM isn't. Everything runs in an isolated "process" (the Erlang term for their special green-thread type thing). Talking to a process on another node in the cluster is exactly the same as talking to another process on the _same_ node, so it scales in a way most languages don't. Message passing and the guarantees of processes means you simply never have to worry about mutexes or race conditions in the same way you do in almost any other language.
https://stackoverflow.com/questions/3760881/how-is-erlang-fa...
https://stackoverflow.com/questions/3172542/are-erlang-otp-m...
And as for Erlang vs. Elixir: Erlang is an old, somewhat unapproachable language with weird syntax and obtuse build tools. It's getting better, but it's fairly hard to use. Elixir is a modern language with a lot of nice things, that compiles to the same bytecode as Erlang, just like e.g. Scala or Kotlin for JVM bytecode. It adds powerful compile-time features like near-LISP-like macros that allow for powerful DSLs and overall contribute a lot towards a good developer experience.
Elixir is also awesome because of Phoenix, notably the most-loved web framework from the 2022 StackOverflow dev survey. Here's an excerpt from a recent talk by the original creator of Phoenix giving a demo of stuff that "just works" when using Elixir/Phoenix because of its concurrent nature, that would be a lot harder with any other language.
https://youtu.be/FADQAnq0RpA?t=1153
--
I can also give my own personal experience working with Elixir. I had never heard of it before I applied for a job at a company that used it in early 2021. I have now been at that company working in Elixir full-time for not quite 2.5 years. (I also have 5 years post-college software dev experience working in various other languages, most notably Java, Go, and Node.JS)
At first, functional programming is a paradigm shift and difficult to get basic tasks done. I had to learn to think a little bit differently, since the typical "for" loop in any other language is no longer available. But with stuff like streams in Java, you already are learning how to think functionally, so it's not really that different.
The runtime advantages of Elixir are great. Unfortunately it's never quite that simple, since you always have databases, SQS, Kafka, other services, etc. so you do still have to worry about some of the problems around race conditions and distributed systems that you would in another language.
However, it does make things within an Elixir service a lot more robust. For instance, in other languages you can have issues where a rogue regex or bug or whatever can cause runaway CPU consumption and either crash the node, or starve resources from other processes; well, this isn't as big of a deal on Elixir because the BEAM uses pre-emptive scheduling to prevent individual processes from causing big issues.
It also makes anything involving single-node concurrency easier. For instance, if you want multi-processing in Java or Go, you always have to worry about race conditions -- due to how processes and message passing are implemented on the BEAM, this is simply a non-issue. Plus, there are a lot of utilities in the Elixir standard library that make concurrency super easy to use.
The compile-time advantages of Elixir are a mixed bag. While I love having cool DSLs to describe my GraphQL schema and permissions, etc. these tend to lengthen compilation times. Yes, Elixir is a compiled language even though it is also a dynamic language. I mainly work in my company's monolithic codebase with about 800k lines of code, and compilation with even a simple change can sometimes take a full minute. A full re-compilation including dependencies is like 20 minutes. It's a bit much. Although, I should note that on a similar-sized Java project, I would expect similarly slow compile times. I think Go and Node.JS are better. The main issue here is that the Elixir compiler is implemented in Elixir and Erlang, which are dynamic languages... Imagine implementing a Java compiler in Python. You can only optimize it so far.
Last thing: I'm a really big fan of statically typed languages, yet I'm okay with Elixir even though it's dynamically typed. The reason is that there's not such a dependence on methods. In plain Javascript it's common to have a line of code like this: `myObject.update()` How are you supposed to know what code that is running? It's completely dependent on the runtime type of myObject. However, in Elixir, the same code would normally look like this: `Wimbles.update(myObject)` and so the majority of the time, you know exactly what code is running - it's the update function in the Wimbles module, which is not dependent on the runtime type of myObject.
Anyways, hope this is informative. Happy to answer more questions if desired.