shanesveller

shanesveller

On "Why Elixir?"

This relates to a discussion thread we’ve had at work back in July and I’ve gisted my answer for that here. It contains more of my positive sentiments about Elixir/BEAM, and there’s a decent amount of those, but it’s semi-off-topic.


For the thread at hand: I’ve stopped working with Elixir outside of my day job, and mostly stopped promoting it to others or participating in user communities in my spare time. I no longer feel the drive I once had to help others be successful with the language.

I feel that there are too many papercuts compared to what I personally value in software development, and most of them are inflexible aspects of the experience of working with Elixir. I began learning Elixir in mid-2013 and have worked with it professionally in some capacity or another since 2016, and full-time as my primary focus since late 2018. I still work with it daily and have no plans to change that for the foreseeable future.

Most of what I am feeling jaded about falls under one of these larger topics, and I’m possibly going to ruffle some feathers and/or summon some pedants to tell me how I’m mistaken:

  • I want an efficient, sustainable, and graceful on-ramp to deploying software. Otherwise, what’s the point? I know this part of the domain extremely well, care about it very/too much, and have invested many hours in making it better personally and professionally, but it basically only gets us to the same table-stakes that any other language enjoys. Runtime vs compile-time configuration continues to be a massive attention/energy sink and teaching hurdle. Teaching good instincts for Elixir deployment has not gotten any easier than it was in 2018, IMO.

    More personally, I don’t live in a BEAM-only world and I can’t tolerate niche features and tools that can’t be standardized with the other languages I write/deploy. I don’t value hot upgrades and I assert that most businesses don’t need them, only pursue them from vanity.

  • I increasingly value provably correct software, which for me means an actual type system to go with your good testing practices. Dialyzer is an insufficient tool here because it is so easy to ignore/misinterpret/bypass. It has non-zero value but the ROI on its usage is very poor even as a willing participant. I can count on my hands the number of meaningful bugs it has caught at my professional roles, although they were often extremely nefarious and would never have been caught by tests.

  • It’s hard for me to pin this part down past half-baked sentiments, but I feel that Elixir is a language that is reasonably good for experts but far too flexible, vague and undirected for neophytes. There is not enough guardrails in the core tooling, and few idioms being prescribed from first-party sources. As many people try to claim about C, it’s easily possible to write very clean, well-designed and effective code in Elixir. However, the language gives you plenty of rope to hang yourself with if you are not working with or at that expert-level experience. I’m not arguing for something like Golang, where someone with two weeks of experience and someone with 15 years of development experience write similar code because they have no other choice. I don’t know what I am arguing for here, but I feel a lack. rustc and clippy do absolute wonders here as pedagogical tools.

  • We still don’t have much adoption by mainstream companies and providers - it is a night and day difference when comparing to a language that is used more broadly. Our library ecosystem often feels like this XKCD comic, and our language tooling (i.e. elixir-ls) are maintained by underappreciated and diligent volunteers who are spread way too thin. I don’t think more than a handful of people are paid to work on this space, and I still encounter areas a few times a year where I would have no choice but to write an integration library myself.

    ExAWS is still looking for maintainers last I saw, despite it probably being extremely crucial to many businesses, and AFAICT Elixir is basically the ghost of a dream within FAANG, Dropbox, Spotify, etc… I don’t chase these companies out of me-too attitudes or vanity, but I feel quite powerfully that they generally disregard Elixir as a realistic choice for serious projects and so we are excluded from the kinds of contributions that their additional engineering power could make, to the benefit of us all.

  • There are some use-cases that we are quasi-permanently not suitable for. Some of those happen to be areas of work that I really want to participate in. We are very good for web development and for network daemons, and Nerves is very compelling for embedded, but Elixir is a poor fit for desktop software, CLI applications, game development, machine-learning or other compute-heavy tasks, or FFI coming from other languages.

  • There is some noticeable brain-drain occurring, especially towards Rust and WASM. Losing the active participation of some of the folks who have moved on really set us back, IMO.

  • Fairly minor in the list above, but I think we made deals with devils in courting the amount of Blockchain/Crypto orgs that are present in the community. I personally find that approach unconscionably wasteful ecologically and also almost universally solving the wrong problem technically.

My gist above has more (not particularly refined) thoughts here as well. If I sound like a hater, I had a lot of good to say about Elixir too. I am undoubtedly a pessimist and a cynic, though.

I don’t think libraries of end-user macros or other non-breaking changes are the way out for most of my problems. I also don’t think some ill-defined “craftsmanship” movement about professionalism is what’s missing either. My problems aren’t because the community isn’t comprised of talented folks.

I wish projects like Gleam, Hamler, and whatever Facebook is cooking up the absolute very best, but I don’t think I am likely to stick around long enough to see their dreams fully realized. They would probably resolve a lot of my frustrations if they can deliver on the premise.

My current front-runner as a replacement is Rust. That’s probably fairly obvious from some of my phrasing above.

Most Liked

sasajuric

sasajuric

Author of Elixir In Action

You raised some valid points, and I can see how various issues combined can lead to frustration. I’ve been using BEAM languages for the past decade, and while I’m in general a happy user, I agree that there’s a lot of room for improvement :slight_smile:

In particular, I think that the lack of strong typing is a big deficiency, and I’m hoping that some of the ongoing initiatives will address this. If projects such as Gleam reach enough maturity I could see myself migrating to them, at least partially.

I also agree that ecosystem is far from perfect, in terms of size, as well as support. It is indeed worrying that some of the prominent libraries are developed as a private effort of a few individuals, with lot of the work probably done outside of working hours.

All that being said, I’m still in general a very happy user of BEAM languages, and I believe that they are by far the most suitable options for building fault-tolerant soft real-time backends of any size and complexity. Projects such as WhatsApp have demonstrated that BEAM can take us very far, but at the same time, in my experience BEAM languages, especially Elixir, excel at building small scale simpler systems. I’ve worked on a couple of such systems which were implemented completely in a single BEAM language, as a single project, running as a single standalone OS process in production, requiring no external dependency at all. One interesting example was a proprietary CI server, a sort of hard-coded Circle/Travis/Jenkins, which had to deal with all of the standard CI challenges, such as monitoring changes in a remote repo, running multiple concurrent builds, managing load and concurrency, dealing with docker containers, caching, running scheduled jobs, persisting state, etc. All of that was implemented as a single standalone Elixir OTP app, using nothing else on the side. I’m not aware of any other technology that would allow me to reduce the operational complexity so much.

As a smaller-scale example of the kind of simplification we can get with BEAM, take a look at my site_encrypt library, which I’ve also showcased in this blog post. Again, I’m not certain that such level of operational simplification can be achieved outside of BEAM, at least not with the similar set of guarantees.

It’s probably impossible to asses objectively, but I personally believe that these benefits are much more important than the downsides I’ve experienced. For example, when I was building a CI, I needed to interact with GitHub graphql API, and had to implement the client from scratch. It took me about a day to research the docs and get a working prototype, and then a few more days to write a proper solution. In a richer ecosystem I might be able to find a library and solve this in a matter of an hour or so. This seems like a radical time overhead, but in the grand scheme of things it was insignificant, because the bulk of the time was spent on the essential domain logic where no library could help me. Such has been my general experience in the past decade of working with BEAM. Sure, I occasionally had to reimplement some wheel manually, such as a basic client for an external service. But usually most of the work was spent on the actual domain logic, and so this occasional overhead didn’t add up to anything significant.

In the end, it comes down to how each of us values given pros & cons, and it depends on what are the challenges we’re trying to solve. For example, I agree that BEAM is not a good fit for some domains, such as GUI apps, CLIs, fast numerical processing, etc, and I usually advise people to look for something else for such domains. But, like @josevalim, I’m not sure that any language/runtime will be a good at everything. I believe that BEAM is a great fit for fault-tolerant soft real-time systems precisely because this is the thing it focuses on.

In any case, while I may disagree with some of your points, I still think you raised valid concerns, and that’s always a good thing.

One final minor comment to the point from your gist:

Umbrellas as a project structure are an extremely permeable form of “isolation” and in my mind provide neutral or negative value to one’s architecture. Elixir has no concept of module-level privacy or hierarchy, only public and private functions

I share your sentiments about umbrellas, and I’ve never used them myself. The boundary project is my attempt to tackle this issue in a different way. Feedback is welcome :slight_smile:

josevalim

josevalim

Creator of Elixir

This summarizes it perfectly. We are not saying “we don’t need redis”, we are rather saying that redis is not a strong requirement from day one as seen elsewhere. As a platform, Erlang/OTP gives the ability to reduce operational complexity in some cases, and to accept this complexity as a starting point because “that’s the way everyone does things” or because “we already have so much complexity anyway” would be a mistake. Of course there are still many situations were Redis is useful, and it is productive to everyone to double-check when that’s actually the case.

I also dispute the perception these operational tools are ignored by the community. There is Redix (maintained by an Elixir Core Member). Tristan, myself, and others have written about k8s+Erlang and there is bonny for k8s control. brod (from Klarna) and broadway_kafka for Kafka, etc. Phoenix includes a Dockerfile in its official deployment guides and it will ship with a Dockerfile generator in the next release. Of course we don’t support everything under the sun but we definitely recognize that they are necessary for a wide range of applications and systems.

Sometimes it feels we are trapped in this three-year old rhetoric that “Elixir/Erlang does not like k8s/Docker/etc” while a large chunk of the community has moved on to recognize and accept its pros and cons.

sasajuric

sasajuric

Author of Elixir In Action

So supposedly making a REST request is complicated and requires advanced technical expertise, but dealing with nginx, sidekiq (which requires running an external worker), and redis isn’t? I’m gonna have a very hard time accepting that :slight_smile:

The (admittedly not fully realized) potential of BEAM is the fact that you need to only learn the programming language and that can take you very far. This reduces the amount of technologies that needs to be mastered, and simplifies the life for everyone on the team. But beyond that, less external technologies reduce the disconnect between dev, test, and prod. Perhaps I was on wrong teams, but none of us usually ran nginx or sidekiq locally. This led to occasional production bugs b/c the stuff not running locally or on CI is the stuff untested.

In contrast, Phoenix can handle many of the reverse proxy features you mentioned. It is used equally on all machines (dev, staging, prod), requires minimum extra operational overhead, and is easily testable.

If you want to obtain an SSL certificate via Let’s Encrypt, take a look at site_encrypt. You can get it working in a matter of minutes and it won’t require installing anything else on the side. And you use the language you normally use to work with it, so no need to learn a special flavour of yaml, ini, or anything like that. That language is compiled, so syntax errors are immediately detected during compilation, while semantic errors (e.g. misspelling of the domain name) can be detected in tests. Since the interface is a programming language, there’s a lot of flexibility (like e.g. fetching input parameters from OS env or some secure store), and the stuff works equally well in local dev and test without requiring anything running on the side. Since site_encrypt periodically renews the certificate it runs a periodic job without requiring any extra OS process or external component. Using vanilla OTP supervision tree, the job scheduler binds itself to the Phoenix endpoint, so if the endpoint is stopped, the job will be stopped too, thus avoiding running a certification that is bound to fail. For more details see this post on site_encrypt and this post on periodic jobs.

Compared to using nginx + certbot this gives me simpler usage, simpler operation (less moving parts), reduced dev/prod mismatch, better testability, and more flexibility. To me these are the very important benefits, and this is where I see a huge potential of BEAM. I’ve had enough first hand practical evidence of it to be convinced. I’ve also had the pleasure of working on systems powered by a bunch of moving parts, and I don’t feel like going back to that :slight_smile:

Just to be clear I don’t hesitate to use external components where it makes more sense. I agree that external database is frequently needed (though oddly enough I managed to get away without it on a few occasions), but other than that I think that many projects can do just fine without needing reverse proxies, redises, external message queues, cronjobs, & such. I’m not saying that these tools are bad per se, but I prefer exploring more lightweight built-in options and move to these tools only when there’s justified need.

Where Next?

Popular in Discussions Top

owaisqayum
I have a sample string sentence = "Hello, world ... 123 *** ^%&*())^% %%:>" From this string, I want to only keep the integers, ...
New
mmport80
I have put far too much effort into Dialyzer over the last year or so - and basically - I doubt it’s worth the effort. It’s not as easy ...
New
nburkley
AWS re:Invent is on at the moment with some interesting announcements. One new feature in particular is the Lambda Runtime API for AWS La...
New
AlexMcConnell
The reason that Rails is as popular as it is is because it’s very easy for relatively inexperienced developers to get a lot of work done....
588 19568 166
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31142 143
New
tmbb
This is a post to discuss the new Phoenix LiveView functionality. From Chris’s talk, it appears that they generate all HTML on the serve...
342 18146 126
New
New
jer
I’ve been using umbrellas for a while, and generally started off (on greenfield projects at least) by isolating subapps based on clearly ...
New
hazardfn
I suppose this question is effectively hackney vs. ibrowse but we are at a point in our project where we have to make a choice between th...
New
scouten
I’m looking for a host for the server part of a small (personal) side project that I’m working on. It’s currently written in Node.js and ...
New

Other popular topics Top

mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43622 214
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31142 143
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New

We're in Beta

About us Mission Statement