top | item 18838115

Would you still pick Elixir in 2019?

317 points| kristerv | 7 years ago |github.com

240 comments

order
[+] artellectual|7 years ago|reply
I’ve been programming in elixir for about 2 years now. I have to say it’s hard to go back to something like Ruby or JavaScript.

In elixir you really get the full power of multi core and support for distributed computing out of the box.

Code that would have been beyond my pay grade or wouldn’t even imagine to write in Ruby or JavaScript is now easily reasoned about and maintained in projects. I can write succinct code that is easy to read, is fast, able to take advantage of multiple cores, less error prone, which I can scale to multiple machines easily.

The erlang scheduler is so damn powerful and it feels amazing to be able to execute your code on multiple machines with a simple distributed task which is built in as a standard functionality of the language.

I’ll end this note saying that, look at the problem you are trying to solve. If you need multi core and distributed features (which is generally more common than you think) elixir is truly your friend.

I can say without a shadow of a doubt the project I’m building right now would not be progressing as fast as it is if I picked anything other than Elixir. You get a lot of bang for your buck when it comes to productivity in the domain that elixir solves for.

[+] chmln|7 years ago|reply
This went past me as the post is filled with a lot of claims with no reasoning to back those up. It is not a critical evaluation of the language, but rather sounds like a "fanboy" piece, for the lack of a better term.

> Memory efficiency is much better than most other languages (with the exception of Rust, but Elixir is miles better at Error handling than Rust, which is a more practical feature IMO

How exactly are arbitrary runtime exceptions better? Any elixir function you call has the potential to crash. Meanwhile with Rust, your function returns a `Result` if it can error, and callers are then forced to handle those by the compiler, either via pattern matching or ergonomic error propagation.

Rust has runtime panics, but those are for rare unrecoverable errors and are not at all used for conventional error handling, reserved usually for C FFI, graphics code, etc.

[+] josevalim|7 years ago|reply
I am not sure I would say one is better than the other, but they are very different.

As you said, in Rust you are forced to handle errors by the compiler. In Elixir, you actually don't. In fact, we even encourage you to [write assertive code](http://blog.plataformatec.com.br/2014/09/writing-assertive-c...). This is also commonly referred as "let it crash". In a nutshell, if there is an unexpected scenario in your code, you let it crash and let that part of the system restart itself.

This works because we write code in tiny isolated processes, in a way that, if one of those processes crash, they won't affect other parts of the system. This means you are encouraged to crash and let supervisors restart the failed processes back. I have written more about this in another comment: https://news.ycombinator.com/item?id=18840401

I also think looking at Erlang's history can be really interesting and educational. The Erlang VM was designed to build concurrent, distributed, fault-tolerant systems. When designing the system, the only certainty is that there would be failures (hello network!) so instead trying to catch all failures upfront, they decided to focus on a system that can self-heal.

I personally think that Erlang and Elixir could benefit from static types. However, this is much easier said than done. The systems built with those languages tend to be very dynamic, by even providing things such as hot code swapping, and only somewhat recently we have started to really explore the concepts required to type processes. But a more humble type system could start with the functional parts of the language, especially because I think that other techniques of model checking can be more interesting than type systems for the process part.

[+] nelsonic|7 years ago|reply
@chmin thanks for the great feedback! ;-)

I did not write the post for general consumption, more as a reply to the question from the person as indicated in the first paragraph of the thread ... I really did not expect it to end up on HN. ¯\_(ツ)_/¯

100% Agree that there is a lack of "critical evaluation" and it borders on "fanboy" ... It's not a scientific or statistical analysis because I did not find any data I could use to make a an argument either way.

My experience with Elixir, JavaScript, Ruby, Java, PHP, etc. is based on doing the work in several companies big and small and I don't consider myself an "expert" in any of these languages. I have felt the pain of having to maintain/debug several large codebases with incomprehensible/impenetrable and untested code over the years and I find Elixir to be the most approachable of the languages I am fluent with.

I wish there was an objective way of assessing the day-to-day experience of living with a language ... have you come across such a measure that isn't based on the opinions of, as you say, "fanboy" users?

You appear to have superior knowledge/experience of Rust. Have you written any tutorials or blog posts sharing that knowledge? I would love to read your work. Is this you: https://github.com/chmln ? If it is, https://github.com/chmln/asciimath-rs looks cool! (nice work! :-)

[+] davidw|7 years ago|reply
Erlang's error handling is... kind of different and takes a while to really grok and work well with. It's not so much about individual functions, as how the system as a whole recovers from failure.
[+] crimsonalucard|7 years ago|reply
Most people (especially from type unsafe languages) haven't figured out that the Option type with pattern matching actually eliminates a whole class of runtime errors. They just see the match operator and types in general as a syntactical nuisance.

   fileString = checkFile("sample.txt")
   if(fileString == null){
        //handle error
   }

If I showed the above pattern to typical javascript, python, ruby or elixir programmers at any company, 99% of them won't be able to identify why this pattern is bad, they see it as a necessity and rely on the programmers skill to catch that potential null (or exception depending on the implementation).

In fact, you dear reader, might be one of those programmers. You might be reading this post and not understanding why the above code is an unsafe and a bad style. To you, I say that there are actually compilers that automatically prove and force you to handle that potential null not as a logic error but more as if it was a syntax error.

That guy who advocates unit tests at your company doesn't understand that unit tests only verify your program is correct for a test case. These compilers provide PROOF that your program is correct and can eliminate the majority of the tests you typically write.

The code above is unsafe not because of the developer, it is unsafe because of the nature of the (made up) programming language.

In elixir, python and javascript you will inevitably have to follow this unsafe pattern.

[+] arvidkahl|7 years ago|reply
I've been working with Elixir in a single-developer production system for over a year now. I'm running it in Docker containers on Kubernetes, in the cloud.

It has been extremely stable, scaling has been a non-issue. Error reporting has become easier and easier, now that companies like Sentry and AppSignal have integrations for Elixir.

Elixir is VERY fault-tolerant. DB connection crashing? Ah well, reconnects immediately, while still serving the static parts of the application. PDF generation wonky? Same thing. Incredibly fast on static assets, still very fast for anything else.

I've had nothing but fun with the language and the platform. And the Phoenix Framework is just icing on the cake. I've been fortunate to have been to many community events, and meeting (among so many others) José and Chris at conferences has made me very confident that this piece of software has a bright future. The Elixir slack is also VERY helpful, with maintainers of most important libraries being super responsive.

I would not start another (side or production) project with anything else than Elixir.

[+] hombre_fatal|7 years ago|reply
> Elixir is VERY fault-tolerant. DB connection crashing? Ah well, reconnects immediately, while still serving the static parts of the application. PDF generation wonky? Same thing.

I still don't understand this.

I don't think I've ever built a web server in any language where this wasn't true unless I specifically wanted hard failure.

The amount of fault tolerance would be a per-app design goal rather than something that seems to be a language feature. I've worked in apps in all languages that range from any failure being a hard failure to being impossible to crash, and this is due to business requirement.

For example, regarding your examples, just about every web server I can think of will automatically turn uncaught exceptions into 500 responses unless you opt otherwise.

[+] jwr|7 years ago|reply
Elixir is a great tool for some applications, but one should always think carefully about what is the right tool for the job at hand. Elixir is not the only language that helps enormously with concurrent programming. Specifically, Clojure is very comparable in this regard, although it gives the programmer much more freedom. And then it has Clojurescript, which makes writing hybrid server/client apps much easier.

I've written large applications in Clojure/Clojurescript and I've seen/reviewed reasonably large code bases in Elixir, and while I would agree that Elixir is a very good solution for many problems, it is not a tool for everything.

[+] symboltoproc|7 years ago|reply
The JavaScript Fatigue argument is not good. There's simply no data that backs it and nobody is forced to use new libraries only because they use JavaScript.

I've seen third party dependencies churn on Elixir as well (packages that are no longer maintained or alternatives that are better) - I think it's an inherent problem with using dependencies and has nothing to do with the programming language in which those dependencies are written.

> As a developer I just want to get on with my work, not have to read another Hackernoon post on how everything from last week is obsolete because XYZ framework

My recommendation is that you don't read Hackernoon. This seems like a very ineffective way to level up your developer skills.

Edit: I agree that Elixir is very nice and would pick it over JavaScript for backend heavy applications without thinking. I just don't think this argument makes any sense in that context.

[+] forty|7 years ago|reply
> nobody is forced to use new libraries only because they use JavaScript.

It's not completely true IMO for 2 reasons: 1- the nodejs standard lib is quite poor compared to say, Java's, Scala's or python's, so you generally need quite a lot of modules to do anything 2- the npm ecosystem is much more amateur. To do anything you have a ton of poorly supported by hobbyists or not supported at all modules. This can force you to change modules/libs regularly. This is to be compared to the Java ecosystem for example, were more people are working together to build well supported/high quality libs (Apache libraries for example)

[+] no_wizard|7 years ago|reply
I’m not calling out JS or elixir communities by any means here. I just want to mention that a big part of the “JavaScript Fatigue” is the amount of overlapping libraries that all do the same thing and it isn’t always straightforward to figure out which one is better - and this happens with so many packages it would be impossible to do it with all of them. Just look up “isArray” (which I wish where just not showing up in libs at this point. It’s a built in in both node and the browser now) and you get 102 packages that are very similar but will clearly vary in implementation and quality.

Where as something like the Python community or Rust community (where I have had more experience) I have always found that even if there are packages that do the same thing, there usually aren’t nearly as many duplicates and often times the community has done a better job communicating the value of many of the packages. There is just less confusion around the whole thing

I have also found there to be relatively little overlap between the big packages, in my experience

[+] IloveHN84|7 years ago|reply
"backend" and "JavaScript" quite don't fit together in the same phrase.

I would never work on backend with JavaScript or any other interpreted language, due to error proness.

[+] phtrivier|7 years ago|reply
Elixir has great things "of his own":

* the syntax is well though-of (`with`, destructuring, `|>` are powerful

* message passing has great use-cases

And then it has problems that are not necessarily "elixir-y", but are there nonetheless:

* it's hard to model an application around the Actor model. It's very easy to abuse it.

* it's hard to maintain / refactor a large application without help from the compiler before run-time

* it's hard to maintain an application in a language with a young ecosystem and no "seamless" integration with a better established one (ports are not seamless.)

Quite frankly, I'm looking forward to writing a backend in Rust, to have a point of comparison.

[+] guscost|7 years ago|reply
Thanks for these notes. I’m suspicious of unconditional praise for any technology, and a lot of the goodwill for Elixir seems like it’s biased by the intention to promote adoption of the language, or like it’s from people who haven’t encountered or paid attention to its problematic aspects. Seeing fundamental problems listed like this does more to convince me that it is a real and serious technology (one with a compelling set of strengths, no less).

As for Rust, do try it out. Haskell-esque type checking, the “anti-OO” interpretation of C-style conventions, and memory safety without garbage collection are a seriously potent set of features, but it can be frustrating when you find out yet again that your whole day of R&D leads somewhere incompatible with its philosophy, and is therefore a dead end. I’m building a Rust webservice framework as a hobby/learning project, but it wouldn’t be my first choice for a production API under active development. On the other hand I’m not aware of a better choice for an embedded daemon process or a stable microservice.

[+] thedoops|7 years ago|reply
I've found CQRS and DDD designs fit well with OTP and elixir. The actor model with pattern matching ends up cutting away a lot of the classical OOP DDD details.

The issue I see is carryover from other ecosystems taking paradigms that aren't necessary and don't fit into libraries and patterns. It feels like there are still conventions to settle on.

[+] hota_mazi|7 years ago|reply
The fact that it's dynamically typed is also often overlooked, while it's at the top of my deal breaker list.

The programming world is strongly moving toward statically typed languages, because today, there's pretty much zero reasons to use a dynamically typed language.

[+] rapsey|7 years ago|reply
Rust is much much less mature for writing backends.
[+] pjmlp|7 years ago|reply
`|>` comes from F#.
[+] sb8244|7 years ago|reply
I've been fortunate to work with a CTO that sees the value in Elixir and also letting us push forward with it. It has been excellent. At this point we have about 20 engineers who have chosen to work in it close to full time for their services.

It's hard to pick one big draw, but I'd say the biggest for me is that everything I wanted to do in rails has been possible in Elixir and then additional functionality not easily possible in rails is trivial in Elixir. I often consider the distribution techniques as "enhancers" as you could work around them with global locks and data stores, but you don't need to.

I'm very bullish on Elixir and I'm curious to see where it will go. Looking forward to giving my talk about bringing Elixir into production (from a human and technical standpoint) at Lonestar Elixir conference.

[+] mrspeaker|7 years ago|reply
Could someone give a more concise reason for using Elixir? I have a "rule of 3" for checking out things - the third time I hear it mentioned and it seems interesting, then I'll go check it out.

Elixir is past 3 times - so I will check it out for sure! - but this article didn't seem to actually say anything (seemed more like a PR piece that was trying not to be technical, and the main argument appeared to be "well, it's not javascript!").

The part that actually talked about Elixir listed some Pros that didn't seem that unique. What's the "killer feature" of Elixir - or is it just a combination of "good features"?

[+] latch|7 years ago|reply
It's the synergy between the language, the runtime and the standard library to deliver the actor model.

Elixir "threads" are called "processes". It's a bit confusing at first, but there's a good reason for it. So from hereon in, when I say "process" think "thread".

Elixir processes, like OS processes, are fully isolated from each other. If Process A has data than Process B wants, Process A has to ask it (send it a message) and can only get a copy of the data (like real OS processes, hence why the name makes sense). The advantage to this is that data ownership is explicit, race conditions are eliminated, and code is less coupled (A can't have a reference to an object that points to B that points to C..., that anyone anywhere in the code can mutate).

At a high level, this allows you to get many of the benefits of microservices, without the high cost (deployment complexity, service discovery, lower performance).

We run an analytics on live sports which does various transformation on a stream of play by play data. There are very distinct features: boxscores, lineups, scores, time alignment, broadcast information...For each live game we start a process for each of these features. When a play by play event comes it, we pass that to each worker of the appropriate game, and each worker does its own thing.

The workers are isolated. Not just the physical code, but at runtime. This makes them easier to test, refactor and grasp.

There's some interaction between the workers. For example our boxscore worker needs to know the score at a given time. So it sends a message to the score worker for that game: {:get, time}. The score worker replies with the score. There's no need for explicit locking. A process handles a message at a time. There's no chance that the boxscore worker changes the score worker's data (it can change the copy of the data that it got, but that change is only on the copy).

Really, it's most of the benefits of microservices (and I mean, being able to have true MICROservices, not just rebranded SOA) with few of the downsides.

[+] bicx|7 years ago|reply
I think the real killer feature of Elixir is that it is a friendly, Ruby-like language that gives you access to the underlying power of Erlang/OTP on the Beam VM.

OTP (Open Telecom Platform) is a set of tools, libraries, and middleware that was built around Erlang. This has been in development since the 90s, and was originally developed by Ericsson for the telecom industry to handle massive numbers of concurrent connections without a single point of failure (I may be butchering this story, but this was the end result). OTP includes things like extremely lightweight processes, process supervision to quickly restart based on your desired behavior, multiple native real-time datastore options (both in-memory and/or persistent), hot deployments with no downtime, an extensive standard library, and other cool things that have stood the test of time. All of this just comes with the base Erlang/OTP installation.

Elixir essentially introduces a modern ecosystem around the Erlang/OTP system.

[+] andy_ppp|7 years ago|reply
I would say it's about developer happiness while coding and that all the decisions made by Jose and the core team tend to have been the correct decision. So taking Phoenix as an example you look at the framework and every time they find a problem i.e. Presence instead of saying that's a difficult problem and moving on they fix said problem in a really scalable way [1].

The same could be said for things like data processing with Flow [2] or even things like Ecto (semi official database wrapper) or even third party libraries like say ex_money [3].

Then you start looking at the packages and language and see that there are rarely thousands of bugs or that the infrastructure (mix, hex, docs etc.) is really nice to use and that the language is really stable, yet still provides you with useful but clear abstractions. Or that you can spin off processes and tasks inline without too much worry, or that you can use 20+ years of Erlang libs transparently, or that it's immutable and has the best concurrency primitives of any system available, or that it allow you to supervise processes and let them crash if needed without bringing down your app, or that you can transparently get multi machine out of the box, or that message passing is build in as the default way to scale the system. Or pattern matching or |> or the amazing community.

[1] https://phoenixframework.org/blog/the-road-to-2-million-webs... and https://dockyard.com/blog/2016/03/25/what-makes-phoenix-pres...

[2] https://www.youtube.com/watch?v=XPlXNUXmcgE

[3] https://github.com/kipcole9/money

[+] fcbrooklyn|7 years ago|reply
The real "killer feature" is the Erlang VM (the BEAM). Thanks to a combination of exceptionally lightweight "processes" (not true OS processes, a construct of the VM), which share nothing, can only interact through message passing, and which can be supervised by other processes, it's possible to build incredibly robust systems.

Elixir makes the Erlang VM much more pleasant to use in my opinion (plenty of Erlangers will disagree with this, ymmv). It provides a developer-friendly, modern ecosystem, with doc support, testing support, a great macro language for building DSLs, package management, etc, but underlying it all is a battle-tested VM, that has been under active development for 30 years.

[+] dlkinney|7 years ago|reply
It is an ergonomic language built on top of a stable, performant, proven runtime with a lot of features built-in.

It's a nice ecosystem with a good culture in a language that promotes pretty good programming practices.

The only major downsides (if they even are for you) are that it's dynamic--not good for number crunching, though you can connect to compiled binaries--and is not strongly typed--which can lead to runtime bugs.

That said, part of the philosophy is to enable fast failure without taking down the whole application. In communications, it's not considered the end of the world to drop or fail on one connection, so it works well for web services, chat, etc.

[+] pmontra|7 years ago|reply
Killer feature: pattern matching mixed with destructuring.

Bonus: parallelism almost for free.

If only GenServers had a sensible interface instead of semi random handle_* functions that obfuscate what a given GenServer is implementing.

[+] johnchristopher|7 years ago|reply
I am not into Python so I assumed it was the python db thingie.
[+] faitswulff|7 years ago|reply
If the erratically emphasized text bothers anyone else, you can get rid of it by running the following JS in console:

    document.querySelectorAll('em').forEach(el => el.replaceWith(new Text(el.innerText)))
[+] nickjj|7 years ago|reply
Sure.

I am building a quite involved video learning platform as we speak with Elixir and Phoenix. No regrets so far, and if anything as time goes on, I'm becoming more and more happy with the decision.

The community is really great and there's a lot of quality libraries available. Not just libraries, but entire production systems too. For example https://changelog.com/ is written with Elixir / Phoenix and their platform is open source'd at https://github.com/thechangelog/changelog.com. There's so much good stuff in that repo to learn from.

Also the Elixir Slack channel has 20,000+ people in it and the official forums at https://elixirforum.com/ are very active.

[+] bnchrch|7 years ago|reply
I've been using Elixir to build applications for production use for 3 years now my summary is I and my whole team can (in contrast to languages I've used in the past):

- Ship faster

- Write simple, readable, reliable and fast code

- Scale easier and with less resources

- Onboard and train new hires into the code base quicker

I know I'm making it out to be a panacea which to be clear it isn't as the deployment story still has some final pieces for the core team to work through but I will say I'll continue to use it to build in the future

[+] bicx|7 years ago|reply
I use Elixir daily for the past 8 months, and I love it. For my personal projects, I use a great Heroku-like service called Gigalixir (https://gigalixir.com/). No restarts or connection limits for the free tier, and it runs on your choice of Google Cloud or AWS behind the scenes. Elixir doesn't have as many easy cloud deployment options as, say, JS, so this service is really helpful.
[+] _asummers|7 years ago|reply
Yep. Would bet on it again. It's proven itself to me and my employer, and has increased developer productivity and joy dramatically. Bad code looks bad, good design emerges organically, and macros let you hide the plumbing where needed, and optimize things away at compile time. Not even mentioning the wonderful world of OTP.
[+] plainOldText|7 years ago|reply
Yes! And most likely in 2020 as well.

I've been programming intensively in Elixir for the past two years and it's a wonderfully productive language, which allows one to write elegant systems that leverage the multi-core architecture of today's machines effectively.

In addition, the networking capabilities and fault tolerance of the VM make writing systems which spawn machines and services a breeze; not the mention the ecosystem only gets better by the day.

So yeah, Elixir is one of my main tools when I want to get things done elegantly and productively. And if for some reason I need to speed things up a bit here and there, I just add a little rust into the mix. [1]

[1] https://github.com/hansihe/rustler

[+] hadsed|7 years ago|reply
What sort of work have you been doing with it?
[+] nixpulvis|7 years ago|reply
Tangent: It's proposed that Elixir has better error handling than Rust... but this doesn't sit well with me, and I know the Rust community is in flux here as well. I personally like not having exceptions. It's very easy to trace where an error is coming from when it's a value like anything else. Yea it might be a bit more typing... this is the conflict. Rust does have an issue with the boilerplate involved with writing error types, but there are already attempts at fixing this as a crate: https://github.com/rust-lang-nursery/failure
[+] thedoops|7 years ago|reply
Different tools for different jobs. Rust is more of a systems language for close to metal performance and memory safety. Elixir is memory safe from a functional perspective utilizing the actor model. Elixir is good for real time concurrency and higher level systems.
[+] qaq|7 years ago|reply
? OTP and Supervisers give you powerful tools for building fault tolerant apps but at the lang level it would be hard to argue that Elixir has better error handling
[+] bsaul|7 years ago|reply
Question : How does OTP work together with things like kubernetes in the real world ? Designing around actors with OTP spawning and respawning part of the actor tree, while at the same time provisionning / deprovisionning VMs if load is going up or down, sounds like either a dream if it works well, or a nightmare if there's just a single glitch somewhere.
[+] whalesalad|7 years ago|reply
This post is killing me. I’ve been really really loving Elixir and for a while was fighting the “everything looks like a nail” syndrome once I learned it.

But now I have a contract that would really benefit from the runtime. That being said the existing environment has a lot of python expertise and I don’t have enough production Elixir experience to have confidence in myself to deliver something of the right caliber.

It’s a damn shame. This system has to process hundreds of thousands of API calls for workloads against a half dozen third parties that all have different rate limits and failure modes. It’s the perfect job for Elixir. It needs to be as fast as possible while isolating failures to the smallest unit possible.

[+] cuddlecake|7 years ago|reply
I love Elixir.

It's the first language I genuinely enjoy reading and writing even in my private life.

If I wonder about the internals of a library I use, I can just look into the code and kind of understand what's happening. Never had that with JS or anything.

I'm just a genuine fanboy.

Only drawback I feel is: Some libraries that would have been quite developed in JS are not that well developed in Elixir. Some libraries are quite dead and it's hard to find alternatives (mostly obscure stuff)

But on the other hand, it often seems manageable to just write it yourself, or fork it and move on.

[+] neathack|7 years ago|reply
I have never used Elixir, so maybe it's a great language, maybe not. But I have to question the reasoning of the post simply going by the comments about other languages in the "Conclusions" sections — some of which I did use extensively.

Really, Go "is the choice if you need to 'sell it' to a 'Boss'" and the imperative programming style leads to more complexity? And Python/Django can only be used if you "don't need anything 'real time' and just want RESTful 'CRUD'".

I get it, you guys like Elixir, but painting the world using such broad strokes doesn't really sound like "kaizen learning culture" to me, but more like "Negative Nancy".

[+] StreamBright|7 years ago|reply
Elixir just really nice. I gave it a shot again and it is super smooth experience nowadays. Distillery, mix, iex <3 Also most of the libraries I care about are 2.0+ and now this:

https://github.com/aws-samples/aws-lambda-elixir-runtime

The only downside is that the out of the box performance is subpar for http services but it is still acceptable.

[+] _asummers|7 years ago|reply
Cowboy measures its latency in microseconds, what bottlenecks are you running into specifically?
[+] heurist|7 years ago|reply
Our team has had great success with Elixir over the last year and ported core node services to it over the last few months. We are very happy with the results. There are some things we haven't been able to do with it, like intensive data processing (for which Python is still used), but if those libraries existed we would switch our Python services ASAP and be an entirely elixir backend.