Derek Haynes


Elixir: the new wave or an elegant niche?

Like a man down on his luck and coming across an old-fashioned church revival tent, I was primed to be baptized.

The concise, clear language syntax. The productivity. A charismatic, foreign leader. He even drives race cars — how exotic!

I came across Ruby on Rails when I was most vulnerable — fresh off a failed J2EE project in 2005 — and choosing productivity over performance was a commandant I was happy to abide by.

Over the last 12 years, Ruby hasn’t let me down. I haven’t found a language that motivates me to create more than Ruby. And the tradeoffs? Performance, threading, concurrency, etc? I found ways around them (or isolated myself from solving problems that needed them).

In short, I’m happily married to Ruby. Why then, do I suddenly have wandering eyes for a new language?

Enter Elixir: the tradeoff-free language

Last year in a conversation with an employee @ Thoughbot, I asked what they are most excited about in the coming years. They answered with one word: Elixir. The story was compelling.

Elixir is a language that seems to lack tradeoffs. Its Ruby-inspired syntax is easy on the eyes. It can do things with concurrency — mind boggling things to a Ruby dev like me— that open up a different approach to building web apps. All this new-age pretty code syntax and concurrency is built on top of the Erlang VM, which delivers “nine nines” availability (that’s 32 ms of downtime in 1 year) for telecom providers like Ericsson, T-Mobile, and Nortel.

Arguing against Elixir? It’s really hard. It’d be like losing a courtship and bearing your soul to the girl like this:

ME: What do you see in that guy? Yes, he looks like a JCrew model, can sing like John Legend, and is fun to hang with. But, come on — guys like that don’t have a future beyond high school.
GIRL: You know he’s going to Harvard, right?

The lack of tradeoffs with Elixir makes me uncomfortable. Humans are used to making tradeoffs. Ruby on Rails represented a clear tradeoff. What’s the Elixir tradeoff, beyond its youth?

Am I missing the Elixir bus at the station?

I’m set in my ways as a developer. For better or worse, I haven’t flip-flopped between different languages, keyboard layouts, operating systems, and code editors. But, Elixir has my attention. I’ve started building apps with it. I’m enjoying it.

My wandering eyes are turning into action. For the first time in a decade, I’m wondering: is a bus heading quickly out of the station that I don’t want to miss?

To answer this question, I’ve put a point/counterpoint (like the Onion, but not as funny) below. There are many comparisons with Ruby and Ruby on Rails because:

  1. I started with Rails prior to 1.0 and I see a lot of similarities in momentum.
  2. Ruby took off because of Rails, and Phoenix is a Rails-like framework on Elixir.
  3. Rails was a game-changer that evolved before my eyes.

Finally, to clarify: this is not a discussion on whether Elixir is better than Ruby. I’m debating whether Elixir represents a new wave of web app development similar to what Ruby on Rails triggered. A new wave is a significantly larger challenge.

Yes, Elixir ushers in a new wave of web apps.

Elixir makes hard problems approachable to small teams.

Ruby on Rails empowered small teams that focused on the user experience. These small teams could build beautiful CRUD apps in record time (think early incarnations of Basecamp, AirBnB, Dribbble, GoodReads, and ZenDesk).

In 2017, 90% of my time is spent outside the fantastic CRUD pieces Rails provides. Elixir and Phoenix (the dominant Elixir web framework) solve today’s hard problems in elegant fashion:

  1. Do work across more services, in less time, in every request

A single web request may gather data from several sources: a relational database, an external API, an internal micro service, a NoSQL database. Rendering the output quickly is not just based on the raw speed of the language (while Elixir is way faster than Ruby, Go and Java have Elixir beat), but how easily developers can perform work concurrently.

Doing concurrency in Erlang or Elixir versus other languages is a bit like doing branches in Git vs Subversion. In Subversion it was very complicated to do — and I never did it. In Git it is a lot easier and I do it all the time.

From Elixir — The next big language for the web

For example, lets say I want to:

  1. Fetch a list of open issues from the GitHub API.
  2. Fetch a list of Git repo committers I’ve stored internally in a database.

These calls can be executed independently of each other. Why wait for one to complete before doing the other?

github_issues_task = Task.async(fn -> fetch_issues(repo) end)
users_task = Task.async(fn -> users_in_db(repo) end)
github_issues      = Task.await(github_issues_task)
users = Task.await(users_task)

Elixir is asynchronous and non-blocking to its core. There are certainly other languages that offer concurrency, but Elixir makes concurrency easy.

2. Snappy, realtime, bi-directional updates with every user

Elixir and Phoenix can scale to support millions of websocket connections on a single (beefy) server. ActionCable, which added websocket support to Rails 5, just isn’t in the same league. With Elixir/Phoenix, most apps could reasonably provide a websocket connection to every user. This makes building quick-responding, single-page app experiences approachable to every app, regardless of size.

3. Fewer moving parts

When we write Rails applications, our Rails app depends on a lot of other pieces.

Nathan Long in Why Elixir and Phoenix?

A production Rails app requires several dependencies:

  1. An app server like Puma or Unicorn. A Rails app cannot spin up multiple requests.
  2. A background job framework like Sidekiq since long-running work in a web request will block. This also adds another dependency, Redis, to store job information.
  3. Another service (Monit, God) to monitor that processes are restarted when they fail.
  4. Cron for running scheduled tasks.

Implementing these pieces frequently requires input from both developer and DevOps teams — there’s more coordination and friction. Elixir — where processes are as lightweight to use as objects in Ruby — allows you to perform all of the above without adding additional services to setup and monitor.

Putting it all together…

Web apps that can do more work per-request, communicate back-and-forth with every user efficiently, and have fewer separate systems to worry about are the next wave of apps.

Elixir is approachable

Keystroke-to-keystroke, Elixir is incredibly similar to Ruby. Here’s me filtering an Array in Ruby:

[1,6,10].select { |number| number > 5}
=> [6,10]

…and the same over a List in Elixir:

Enum.filter([1,6,10], fn(number) -> number > 5 end)
=> [6,10]

Looks the same, doesn’t it? Sure, Elixir is a functional language and Ruby is not, but line-by-line, it’s as approachable as Ruby.

Like Ruby, Elixir will pull developers from multiple languages

Elixir needs to pull developers outside of Ruby (its current base) to become more than a niche. It will.

Smart companies like Pinterest are migrating from Java with great success. Elixir easily outperforms NodeJS in one of its selling points — websockets — and has a far more sophisticated concurrency model.

In short, many of the arguments against Elixir come down to:

  1. It’s too hard convincing your boss to let you build apps in Elixir
  2. The community is too small
  3. The number of libraries available is too small

Sound familar? Those are the same arguments against every language and framework — Rails included — when they started.

No. Elixir is just a niche language.

To go beyond a niche, you need to be 10x better. That is hard today: from Closure to Elm to Rust to Go, there’s too many specialized options for a new language to emerge as a standard.

Yes, CRUD is done, but you can get close to what Elixir provides with existing languages and frameworks.

Why learn a new language and framework when you can just assemble pieces for concurrency and real-time communication when you need it? Embrace the flexibility we have today for combining services — there’s no need for a monolith:

  • Very few web endpoints require concurrency. For those high-volume, critical ones that do, Elixir makes an excellent choice. But, you don’t need to migrate your entire app for a couple exceptional endpoints.
  • Need real-time websockets? Use a service like Pusher or Ably.
  • It’s OK to have dependencies. Puma, Sidekiq, Redis: these are widely-used, well-maintained, and finely-tuned services.

Existing languages will fix their weaknesses

As Rails gained popularity, other languages quickly developed their own Rails-flavored frameworks. Same with scripting languages on top of the JVM. Ruby too knows it has a problem and is working to fix it.

Inertia may be rewarded: stand pat, watch Elixir grow, and then watch your favorite language pick off the best parts.

Elixir’s selling points aren’t communicated to non-developers

Rails had a clear “10x better” argument with productivity: it was 10x faster to build apps with it than frameworks like J2EE.

Productivity is important to everyone, not just developers. This meant the push for Rails would come from not just developers, but from managers, executives, and clients as well.

Elixir and Phoenix’s selling points aren’t as clear to the non-developer crowd. To be a new wave, it needs to be easy to sell Elixir from multiple sides, not just developer evangelists.

Just tell me already!

Sadly for those of you that read this far, I can’t tell you if Elixir represents a new wave. I’ve just added one more decision to your life. I’m sorry about that.

However, I’d keep a close eye on web sockets. Elixir has a huge advantage if developers come up with a way to leverage these across every app in a mind-blowing way.

Finally, at my day job, my co-workers and I are about to begin an Elixir experiment. I’ll share the good and bad on that journey right here on Medium, so simply follow me for the story.

More by Derek Haynes

Topics of interest

More Related Stories