"but I don't know understand why that has to come at the expense of being terrible at everything else."

A great deal of it is certainly just resource poverty compared to the JVM or the various JS runtimes. It may have some nice high-powered resources dedicated to it, but I'm still very comfortable with pron's assessment that the JVM has literally 100x more resources poured into it.

There are also some decisions that I would consider suboptimal for performance in the original Erlang specification though:

1. It extensively uses linked lists as a data structure. It was very fashionable in functional programming at the time, but the performance impact has in relative terms gotten worse as CPUs continue to speed up relative to RAM. Erlang does recover some of this vs. other functional programming languages in that the process model tends to keep the linked list components closer together together in RAM because they'll stay in the process' arena rather than being spread arbitrarily out over RAM, so walking a linked list a couple times is at least very likely to fit well into L1, but this is still going to be a pervasive loss of performance.

2. Haskell has done a lot of work in how to reconcile immutability with performance, and I'd still say there's a penalty there. Erlang hasn't, and a lot of it wouldn't apply (Erlang is strict), so you're still getting ~1980s/1990s+whatever optimizations we could add performance on a lot of the immutable stuff. It does do some of the obvious optimizations like rewriting obvious recursive algorithms to use mutability internally, but in general you're still going to pay some penalty here.

3. This one may be a bit controversial, so let me first say I deeply respect Erlang as a design, consider it to have been very far ahead of its time, and that given the general understandings of programming language theory at the time, that Erlang is a staggering accomplishment. That said, with the benefit of decades of hindsight on the design, the Erlang type system is deeply suboptimal. From what I can see, the primary purpose of the design is to ensure that you can't pass references between processes so that there's no way to modify a process' memory from another. The way it accomplished this is with a type system that has no references in it. But because this matter wasn't as well understood then as it is now, it also overcompensated with making everything immutable, removing all ability to have custom user types, and yet at the same time, having a fully dynamic type system in which there is only one type: "Erlang term". It's not necessary to kill all custom user types; you can just kill the things that make them unable to be passed across the network, which isn't everything. You don't need to make things immutable, you just need to ensure that references can't be passed. You don't need to make everything dynamically typed so that you don't have to synchronize definitions of those types; there are other ways that this can be dealt with. There's just a lot of these little things where one could finesse the result but the Erlang design hits it with a sledgehammer.

There's a case to be made for that, too. A lot of the finessing would be a lot more complicated (e.g., Rust does a lot better job with managing mutability than Erlang, but look at the complication in the type system as a result; it doesn't come for free.) As language design goes, there's a lot of room for debate.

But in terms of the performance impact, Erlang ends up with the worst aspects of dynamic typing on performance, and with not all that many of the benefits of dynamic typing. (You get some. There's more dynamism than initially meets the eye in Erlang. For instance, where you say lists:append(L1, L2), lists and append are just atoms. You can say L = lists, A = append, and then run L:A(L1, L2), and do conditionals on that, etc. It took me a long time to learn that. But you still miss out on a lot of the dynamism of dynamic languages, and even what there is is often harder to manage. And also, you pay in the performance for this, too.)

An Erlang written for the modern era, but tuned a lot more for performance, isn't Go. But Go is probably close enough to inhibit success for any such effort; I observe that languages tend to inhibit the creation of things very close to where they are, but not the same. (Bizarrely, it seems to be easier to create something that is essentially a clone of a current language from a programming language theory perspective with an opinionated syntax gloss on it than to create a language that is mostly like another but with a couple of important PLT changes. I don't think I fully understand why this is, but the observation seems pretty solid. So, "Go + full process isolation" is unlikely to attract enough support to succeed, even though I'd personally love to see it.)