Once a sufficiently good proposal was made, generics were adopted.
Of course, in some sense fault tolerance and scaling are two sides of the same coin. They're both measures of availability. They're just different approaches to that.
What Go achieves that Erlang doesn't is the ability to "pick up and play". What Erlang achieves that Go doesn't is a pathological commitment to the system whole never going down.
On the other hand, Erlang has been out for ages and has largely failed to attract much adoption, so it doesn’t seem like the market finds it to be “optimal” either. Not that popularity is everything, but over time a language better languages should increase their market share, especially if your language got its start during an era where the competition was C and C++ and Java.
> And I know it's an old thing, but the fact that Go was once adamantly against generics...
Erlang not only lacks generics, but it lacks any static type system at all…
If one wanted, they could put ecosystem tooling here as well (e.g. `gofmt` saving everyone time and mental health).
Also, to clarify, I'm not arguing that Erlang > Go, I don't (purposefully) use either, though I have to read Go sometimes.
And most software does apparently not need what it offers.
Having learned both Go and Elixir, I found Elixir easier to learn and a lot more enjoyable to work with. I'm not alone in this opinion. According to Stack Overflow's 2025 "admired" languages, Elixir scored 65.9% compared with Go's 56.5%; Phoenix was the most admired web framework of 2025 at 79% and has held that spot for the past three years.
In practice, this is why many such languages have JIT's (unless targeting a subset or an type-information enhanced superset like TS), there was a seminal OOPSLA paper in 1995 by Agesen and Hölsze (who worked on the JVM Hotspot compiler) that compared JIT's to AOT compilation in practice (the Agesen CPA algorithm isn't perfect but it's pretty good for the time and others have probed that it's an undecidable problem).
That said, they also had a historically bad performance story due to misjudgments in development direction, the interpreter was default and they twice tried to make "HPC JIT's", ie.. complex JIT's that tried to be "perfect" and focused on numerical code gains, they'd be good for optimizing a matrix kernel, yet fairly useless or even negative on more common code patterns.
OTP 24,25 and 26 took learnings from the JS runtimes and also added compiler hints (since they already had binary precompiled modules).
What still saves the OTP runtime is that many basic operations that would suck without a good performance story is handled by built-in functions, so like Python most practical programs works well enough even if the runtime is behind.
This poster summarized it well: https://news.ycombinator.com/item?id=49864334