* No mutation support means that for some CPU-heavy tasks, it's not as performant as languages that allow mutation. Some optimized algorithms that rely on mutation can't be expressed directly in Elixir or Erlang, and instead need to be linked in through a foreign function interface.
* It's not on the JVM so we don't get to piggyback on the thousands of dev-years of VM optimization and ecosystem around it.
* It isn't invented at, supported at, and marketed by a FAANG-type company. Money moves mountains and Ericsson doesn't spend as much on Erlang/BEAM as, say, Google spends on Go.
* Comparison across types is not a runtime exception, so you need to guard against crap like `nil > 1 == true` yourself.
* Erlang standard library, which is idiomatic to use from Elixir in the same way of using Java classes from Clojure, is a bit of a junk drawer of tools. There's good stuff, but you may have to dig for it.
* Elixir still hasn't nailed the balance between creating small, independent pieces of code ("applications" in Erlang-speak) and wrangling them so they can be used as dependencies from monorepos, multi-repos, etc. Umbrella projects were an attempt, I don't like them.
* There is an impedance mismatch between Erlang/Elixir's configuration system and 12 Factor® ENV-style configs. (Full disclosure, I wrote a library for this: https://github.com/appcues/config_smuggler)
* The built-in Elixir code formatter removes trailing commas from multiline lists. I mean, come on!