I'm bullish on Elixir and I agree that ExUnit deserves to be singled out.

Whether you consider Elixir fast or slow probably depends on what you're coming from and what you're doing. Personally, I wish the performance story would significantly improve.

But, the reason I think Elixir should be your goto language comes down to process isolation and the ecosystem around it (the synergy of the runtime, libraries and language). If you're doing a pure web app, you might not fully leverage it. But, for anything that involves long-lived in-process data (like a workflow/pipeline, or persistent connections), the way to approach this in Elixir (with supervisors, processes, message passing and pattern matching) tends to result in highly cohesive and maintainable code. Message passing is a pretty effective antidote to coupling.

I just finished writing code that had to take a stream of unordered time-based data and dedupe it over a small window. I'm not overly pleased with the final result, but it's completely isolated from the much larger app it sits in, easy to refactor/rewrite, with no risk of someone taking a shortcut and just accessing some internal detail, and testable.

I feel like I wrote a microservice, but without any of the challenges of a separate app.

So, just to speak about the BEAM, which is the part of Elixir I am familiar with, I don't think any BEAM language will ever be a good goto language. The BEAM isn't good at general purpose computing. It's not particularly efficient at performing calculations or using memory. It's good at reliably performing as you increase memory pressure on your system (via message passing). You can scale a business to a decent size on a smaller number of fatter nodes (high RAM machines). Connections will keep pouring in and you'll get a consistent ms.

That said, you'll run into issues once you hit a certain level of scale. I've had to make patches to the BEAM just to keep us scaling, and I've never seen someone get away with stock dist. You pretty much have to rewrite pieces of OTP.

Now is Elixir ok for a CRUD app serving 10G of traffic? Of course... but this is also the age in which every language has a solution to the C10K(, C100K, and more in many cases) problem, and there are compelling reasons to write your CRUD app in Go and get better library support, static types up front (trust me, you want a static type system), and lower latency.

Personally, I'm bullish about Rust. With async/await landing, it stands a good chance of providing the same focus on safety and reliability while being infinity more flexible at what it can effectively. It's a better general purpose language. Also, the actor model (and CSP as well) aren't the end all be all of concurrency patterns. Rust only provides the building block (futures) so it's much easier to choose the concurrent pattern that fits best for your problem. You can sting a future using the actor model, so it's still an option, but you aren't limited to it.

Until someone re-implements the process isolation and other battle-hardened distributed systems characteristics of BEAM/OTP in a rust stack, it certainly seems like embedding Rust as NIFs into erlang/elixir seems like a nice option to make up for the perf deficiencies you mention (though doesn't cover the memory concerns.)

I have not tried doing it, but I'd imagine the safety guarantees of Rust are a nice thing to have to reduce the risks involved around NIF callouts. I believe Discord recently posted that they are doing this, and I'm interested in hearing about their results.

edit: Google is my friend. https://github.com/hansihe/rustler

I think they're being reimplemented in Kubernetes. Kubernetes provides scale-ability, fault tolerance, and the pieces you need to build robust distributed systems. There's no need for this from the language itself. It's actually disadvantageous to mix Erlang and Kubernetes, because Erlang really wants a stable set of node names.

It's not a good fit for the way in which we're doing fault tolerance in the cloud. Erlang focuses on not crashing the BEAM, by letting processes crash while allowing graceful degradation of service. Supervisors are akin to Kubernetes deployments. Processes are pods. The pods themselves should be designed to crash gracefully.

BEAM on Kubernetes is certainly possible: https://github.com/bitwalker/libcluster just not by default