"Also, I've read some comments where people mention "we don't need redis", "we don't need workers" everything is so much easier. That was our thinking at first. But then you realize on deployments you will lose your cache, or your background jobs, etc. So you have to persist them either in mnesia or in the database. At that point you're just reinventing your crappy undocumented and untested version of delayed_job... Most of what you get from elixir in terms of redundancy, high availability, etc you can have that anyway from kubernetes, heroku or any PaaS.... you will need more than 1 server anyway, so..."

I used Erlang for 5-6 years in a production environment in a deployment that wasn't the world's biggest, but did seriously need clustering because we needed more than one machine to handle the load, not just redundancy. This comment leads to my core observation about the entire ecosystem for anyone considering using anything in the Erlang ecosystem.

Erlang started in the late 1990s. Joe Armstrong was brilliant, and I would imagine was also surrounded by some other very smart people whose names I do not know. Despite what I'm about to say, let nothing I say be construed as disrespect for either the language or the people making it.

Let me set some context here. C++ ruled the day, and still looked to inevitably replace all C. Python, Perl, and the entire dynamic scripting language category had just been invented. Java was in the news, but not on your computer yet. Haskell... pre-monadic IO... had just been standardized somewhere in here. Threading was possible but was every bit the nightmare it has been presented as, and you had to be careful spawning more than single-digit threads because of the resource consumption. Open source was just beginning to be A Thing... that is, it had existed in its embryonic form for decades, of course, but it was just beginning to cohere into the Linux world we know now. Machines were still measured in the hundreds of megahertz and the single-digit megabytes of RAM.

Erlang was a far more radical departure from anything else in this era than it is today. There was a lot of academic work on this stuff, and there was a lot of very specialized high-end work on multiprocessing, but it wasn't being done by "mere mortals" and it wasn't very simple. Erlang's designers looked out into the world, and what they saw was a huge jungle, where what maps we had had huge regions that just said "Here There Be Dragons". And they started in, hacking and slashing and slicing their way through, guided by a few intuitions and a whole lot of engineering firepower.

And they largely succeeded in creating a settlement in the wilderness. They grew and managed to pave over the hack & slash paths into roads, built a community, built a pretty incredible VM, built an ecosystem around them. Let this accomplishment not be underestimated; this is a land that had eaten many others in that era.

However, sitting here in 2021, this is no longer a wilderness. Much of the area has been razed, highways driven through it, McDonald's by every exit, and millions of people living here in various bustling metropolises.

And I think what we've found is that where Erlang plopped itself down is OK... but not more than that.

As a consequence of its isolation, Erlang bundles a lot of things into itself that just didn't exist back in the day. It bundles in messaging passing and a network-aware message bus, almost literally decades before anyone else even thought of a "message bus" as a distinct product segment. (i.e., they existed, you could find academic discussion and some early passes at it, but it wasn't really a distinct category yet.) It has a threading environment. It has these "supervision trees" idea which are cool. It has immutability at a time where Haskell was even crazier than it is now. It has a mechanisms for bundling and distributing applications. It has this entire alternate-reality ecosystem in it. But...

... in 2021, none of these are best-of-breed anymore. Many of them are deeply quirky. Immutability is cool, but we only needed to not be able to pass mutable references on the message bus, not be fully immutable within an Erlang process. I believe Elixir fixes this one. A modern message bus going between processes gives you this whether you like it or not because it also can't carry mutable references between OS processes and systems. Having a message bus integrate into the language is a big mistake, because it makes it hard to hook up anything but Erlang nodes to Erlang. (I say "hard" and not "impossible" because I know it can be done, but it's hard.) A modern message bus like Kafka or the dozen other choices doesn't impose an implementation language on you, nor does it impose that implementation language being the only one. Process restarting is a necessity for production-grade systems, but we've settled to a large degree on OS-level handling for restarts, and within a system, there are easier ways to accomplish the goal than bring in the entire Erlang supervision setup. Mnesia, a clustered DB was a neat idea, but in 2021 is so poorly featured and unreliable it doesn't even qualify as one anymore; nobody in their right mind would bring up an Erlang cluster just to back some other language's code to Mnesia as a database. Pattern matching is cool, but not cool enough to justify all the other issues that come with it, and proper use of other language functionality is often good enough anyhow. (I don't tend to miss it; I tend to properly use some form of polymorphism instead. Trivial pattern matching is replaced by this, and to be honest, non-trivial pattern matching is probably a code smell if not an antipattern; if you're reaching three levels down into a data structure, you know too much about that data structure!) Modern Erlang performance is meh; it used to have the clear advantage when dealing with lots of sockets but now there's a lot of things that can comforably exceed it. Its type system is an annoyance even by dynamically-typed standards, if you like static types than just stay away. (They will cite Dialyzer, but it isn't anything remotely resembling a replacement.) And if I reviewed the docs I could find a few more of these, plus I find there's a lot of cases where Erlang has solutions to problems only Erlang has in the first place, e.g., "gen_server" is neat, but the entire gen_server set up, with its initialization phase and its three proscribed ways to call it and the need for an explicit "gen_server" module type are largely the creation of Erlang in the first place... in other languages you generally get the functionality packed up differently but it's all there without having to exactly match what Erlang does.

So, in 2021, the problem is that going into the Erlang ecosystem tends to lock you into a whole package of things that vary from "not best of breed but mostly OK" to "significantly inferior to the modern alternatives". All it really has is very nice integration of its not-best-of-breed stuff, but even that kinda becomes a trap after a while, like when you realize you need a real database after all, then maybe you have to integrate with another message bus so you can integrate with non-Erlang code, and, you know, a couple more cycles around that loop and you'll really regret having chosen Erlang.

One thing that I think it has going for it, and why it's probably still got a cult following today, is that if you're a relatively new developer, or not experienced in network programming, it is a heck of a trip when you get into it, because the tutorial will introduce you to half-a-dozen ideas you've never seen before. Cross-server message buses? Amazing! A network database with an easy API? Amazing! Spawn a million processes on a commodity box? Amazing! I think this explains a lot of the appreciation it gets today. But no longer are any of those things unique. It's just that the normal developer lifecycle will tend to encounter those, one at a time, over the course of years, instead of having them all thrown at you in one amazing, mind-blowing language introduction.

But in 2021, you can do not just "better" than Erlang for all of them, you can do much better. Except that whatever you put together will be something you had to put together, and it won't be quite as nicely integrated. But it will allow for multiple languages, it'll allow you to better integrate with the direction modern ops is going, it'll scale better both internal to your language and in terms of performance, and you'll be better able to hire for it.

The Erlang ecosystem was brilliant and far ahead of its time. I honor it as an incredible pioneer and recommend, even after everything I said, that anybody thinking of writing some incredible new language spend some time in the Erlang ecosystem to see some of what is possible with that sort of integration. But I can't in good conscience recommend it, in either its Erlang flavor or its Elixir flavor (or its Lisp flavor or anything else) to a modern developer. Everything Erlang does is much better done now by other things, minus the language/ecosystem lockin. This is not because Erlang lost, it is because it to a large degree won. It blazed a trail, and we all now agree, it was a trail very worth blazing. But the next waves of settlers & builders ultimately have created something better.