Elixir and Phoenix: The Future of Web APIs and Apps?

Posted on by in Development, Elixir

phoenix-elixir

Buzz has been building up around Elixir (and Phoenix) in the development community over the last year. We’re pretty excited about them too and want to share the reasons why they’ve piqued our interest and what we’ve learned so far.

We decided to kick the tires by rewriting one of our in-house web applications using Elixir and Phoenix so that we could answer the questions that are most front of mind:

  • How productive is the stack?
  • Are there any emergent benefits?
  • Are there any significant gotchas?
  • What are the performance characteristics?
  • What’s the community like?

What’s important?

First, let’s talk a little bit about what we’re looking for in any tech stack and why. Ultimately, we want to build using tech that’s highly productive and doesn’t make it difficult to adapt or grow as products mature and become more sophisticated. That is, we want to be able to be productive in the short-, medium- and long-term. We define productivity as being able to get features in front of users quickly. It’s influenced by the language, the frameworks and libraries, the development toolchain, and the services that make development and deployment easier. We also want to be a part of a community that’s welcoming, inclusive, supportive and generally positive.

Why is productivity so important to us?

We’re in the business of building products in such a way that tightens the feedback loop, so that we’re validating assumptions and course correcting early and as often as necessary. We love tech, but what we love more is building the right product, and that almost never happens on the first swing. That’s why productivity and quick iteration are so important. Practically every decision we make is made with this in mind.

It’s this quest for productivity that drove us away from Java EJBs to the lighter, faster, better Java stack of Spring, Hibernate, and Tomcat around 2005. Then it drove us to Ruby on Rails around 2008, which is still our go-to for most products. It was the reason for using Node.js on products that require near real-time distribution of messages across many clients. And it inspires ongoing experimentation and evaluation of any new, promising tech.

How might Elixir and Phoenix fit into this evolution?

The hypothesis we’re testing is that Elixir and Phoenix will be as productive — maybe more — as other stacks we have used, while giving us better performance, stability and scalability out-of-the-box. No better way to find out than to try it…

Elixir and Phoenix (in the tiniest nutshell)

Haven’t heard of Elixir or Phoenix? Here’s what you need to know: Elixir is about 4 years old. It’s a new functional language designed for productivity and maintainability that runs on the Erlang VM. The Erlang VM is time tested (more than 20 years old), very fast and has awesome concurrency and inter-process communication (called OTP). Phoenix is a modern web framework that makes building APIs and web applications easy. Since it’s built with Elixir and runs on that awesome Erlang VM, it’s fast as hell and has excellent support for handling very large numbers of simultaneous users. More information is a Google search away.

What Have We Learned?

We learned a lot by rewriting one of our own applications in Elixir and Phoenix. The application is a project- and people-tracking tool. It shows who’s working on what, what skills each person has, when people are taking vacations, and rotations between projects. It supports real-time updates and collaboration with numerous simultaneous users. We use it everyday to help run our business.

As the product owner, I learned that smart full-stack Ruby developers can pick Elixir and Phoenix up quickly and get real work done without that much ramp-up. This rewrite took between 5-6 developer-weeks total. We treated it like a real project and didn’t skimp on code quality, tests, loading assets from a CDN, database bootstrapping (for easy first-time development), writing efficient queries in Ecto, or anything else.

All of the developers really enjoyed working in Elixir and with Phoenix. Here’s what they had to say about it…

Elixir has been my first time working with functional programming. I’d say that the functional paradigm and immutable data are the biggest benefit of building a Phoenix application. Coming from OO, it definitely takes some time to get used to, but for me it makes the code easier to reason about and reduces some of the cognitive load of trying to remember what is/isn’t mutable. That’s usually what people say about functional languages, but I experienced it in practice. -Alex

I really enjoy being able to specify contracts in my function definitions with pattern matching. Like being able to say, “this function should absolutely accept only these parameters.” I can delegate all my worries about error handling to the supervisors. Along with that I feel like I can express myself in simpler terms in Elixir. Especially with pipelining data transformations. I can write out each step and it’s clear what should be happening. Overall I just feel empowered to solve hard problems with Elixir. I don’t know if that’s because of the concurrency and supervisors, or syntax, or all of the tooling that’s already built in to Erlang. But the stuff I struggle with in Ruby and JS just doesn’t get in my way with Elixir. -Chris

Takeaways

Phoenix is productive, but isn’t as productive as Rails… yet. There are good reasons for this, most prominently, our lack of experience with Elixir and the relative newness of the open source ecosystem (i.e. fewer libraries). Having said that, our team was still very productive. I can see the gap closing quickly. We’re helping close the gap by contributing to the language and framework, and through new projects like Wallaby.

Phoenix performs better out of the box. A rather large JSON request was taking about 1.5-2.0s against our Rails backend (no caching). That same request (same h/w, database queries and data) takes about 400ms with Phoenix. The standard deviation was much lower with Phoenix too. We didn’t go deep on the benchmarking this time around, but maybe we will and share our findings in another post.

Channels are easy to use and fast. We migrated from Pusher (a great service!) to Channels, which removed an external service, reducing cost and simplifying things operationally without increasing app complexity. The migration was painless and Channels are solid.

Between low latency and Channels, the application went from sluggish to extremely responsive… without having to introduce page, fragment, or “Russian doll” caching. Everyone who uses the application commented on how the app “works much better” now. Interestingly, the only thing that changed was the responsiveness. Goes to show that high latency makes an application feel broken, not just slow.

The Erlang VM makes much better use of resources. Our application went from using just shy of 1 GB across 2 dynos to a single dyno using less than 100 MB. That single dyno is notably faster and can handle higher concurrency (about 10x).

Elixir/Erlang is less fiddly than Ruby or Node.js from an ops standpoint. Erlang/Elixir doesn’t have an GIL (like MRI Ruby does) and a single (operating system) process makes use of all available cores (unlike Node.js). Additionally, there are no long, unpredictable GC pauses due to how the Erlang VM works. You can even deploy new code to a running VM without having to restart the process (how cool is that?!).

Still evaluating…

We’re not done evaluating as there are some things you can’t answer with a short project. Here are some of the things we hope will be true:

Productivity will continue to improve as the community and platform mature. Our hope is that Elixir and Phoenix match or beat the productivity we’ve seen with Ruby on Rails over the years.

Phoenix (without caching) will perform better than Rails (with caching). We already know this is true on a small app, and we can’t wait to see how it pans out on a large one. We don’t expect to completely avoid caching with Phoenix, but it would be nice to avoid having to do it aggressively and early, as we have had to on our Rails projects to get reasonable performance and latency. Rails makes it “easy,” but it’s still time consuming and hard to get right. It also creates friction that reduces productivity.

“Cost per active 1000 users” will be much lower than with other platforms. We really want to see what scaling looks like for a mid-to-high traffic application. We’ve seen others’ benchmarks and they look good, but nothing beats first-hand experience.

It will be easy to maintain a large, growing Phoenix application. Small apps are easy to keep clean and simple, even elegant. What happens after 6 months or a year of development? It is easy to keep the code well factored, create good abstractions, and manage technical debt? Stay tuned for that in a future post.

Phoenix applications will be more stable and less bug prone given the functional/immutable nature of Elixir. This will be hard to measure, but I think we’ll be able to make a reasonable judgement call after a few months.

Other Important Questions

Is it a safe bet? Will this tech be around in a few years?

We can’t predict the future, but the signs certainly suggest it will be. When you look at the number of conferences, meetups, newsletters and other signals, you see something that has reached escape velocity and is picking up speed. There are big products that leverage Elixir, including Bleacher Report and Pinterest. And there are plenty built on Erlang, including WhatsApp and parts of the Heroku platform.

Will I be able to hire developers?

There are certainly fewer Elixir developers out there than just about any other stack, which at first may sound like a problem, but may not be. There are also significantly fewer companies competing for those people, which makes it easier to stand out compared to those competing with you over talent. We’ve also seen a trend in senior Ruby developers wanting to cross over to Elixir, rather than build yet another Rails app. Elixir is a shiny new thing with real promise, which helps attract very enthusiastic developers.

Can I use the services I know and love, like GitHub, Heroku, CircleCI, Code Climate, New Relic, etc?

Mostly, with a few caveats. We’re using GitHub, Heroku and CircleCI and they all work great. CircleCI needs a couple of additions to the circle.yml, but it’s nothing unusual. New Relic doesn’t support Elixir/Phoenix yet, but there’s the Erlang Observer and Exometer (see measuring your phoenix app). Code Climate doesn’t work out of the box, but if you’re adventurous, there are some projects you can probably get working.

All of this is to say, we didn’t find it hard to get started and stay productive… the things we rely on most heavily basically just worked.

Conclusion

We’re bullish on Elixir and Phoenix and are excited to see what it’s like to build more apps and live with them for a while. We’re about to start our next Phoenix project — a web app and mobile API — and will keep contributing to the open source ecosystem. Who knows where we’ll be in a year? Maybe half (most?) of our projects will be Phoenix projects? Can’t wait to find out!

Suggested Reading


Feedback

  Comments: 18


  1. Thanks for the write up! I’ve been playing around with Elixir (coming from a Ruby background) and am excited about its future.


  2. Great article Christian!

    That kind of well-detailed review of using Elixir and Phoenix is something very important to help with adoption.

    Thanks!

  3. Roman Heinrich


    Hey, love to hear some real life stories about Elixir usage in the wild.

    Wallaby looks like a great project, I’d love to give it a spin sometime in the future!

  4. Craig Watermam


    What a great review (both on the pros and cons) — I’ve just started pushing apps (RESTful apis) with Elixir/Phoenix and I have to say it’s been great all throughout the process.

    And having just noticed Wallaby come up in the Elixir Radar, I’ve gotta say you guys are really helping out the ecosystem a lot with your content *and* tools. Thanks!


  5. Thanks for the article. What are your thoughts on the use of Channels vs Node.js?

    • Christian Nelson


      Khaled,

      The closest thing to Channels in Node.js would be socket.io (maybe there’s something newer?).

      They’re pretty similar in some ways: channels, messages, multiplexing, websockets with fallback(s) when necessary. The main difference I see is that Elixir, running on the Erlang VM, can make complete use of all cores/threads on a machine, which allows it to handle more connections and messages out of the box. With Node.js, you have to run X processes, where X is the number of cores or hyper-threads, depending on the CPU architecture. Once you have more than 1 process, you then have to pair it up with Redis pubsub so that the other processes get the messages. It’s all doable, but it’s kinda a pain in the rump.

      The future is more cores, not really faster ones. Elixir (Erlang) and Phoenix are simply in a much better position for that world than Node.js is.


    • Thr’ees nothing like the relief of finding what you’re looking for.


  6. Good overview, Christian, and interesting to hear about your team’s experience with Elixir/Phoenix. I’ve been experimenting some on my own, and I’ve really been liking this stack as an alternative to Ruby on Rails. I’m bullish as well. Would love to hear about further experiments and benchmarks.

  7. Foonathan Barson


    How’s your Elixir stuff going, saw any disadvantages yet? (thinking of investing time in Elixir, but not sure yet). Does it give the same feel as Ruby does? (tried simple things, and liked it. But small app differs from complex very much). Is it worth it in general?


  8. Thanks for putting this together–very informative and interesting read!

    On a totally unrelated side note, perhaps consider some tweaks to the typography. The thin font & light color is rather hard to read, especially on a 4k laptop screen–even with 20/20 vision :-). I’ve found that using rems for the font size, instead of pixels, solves this problem nicely.

    Cheers!


  9. Regarding integration with New Relic, a feature request was recently opened here:

    https://discuss.newrelic.com/t/request-elixir-plug-phoenix-agent/38501

    Chime in if you’d like to see support for Elixir added!

  10. Christian Gabriel


    Thanks for this good article


  11. Thank you for such a wonderful article dear. i am using elixir for hair growth from long and its really effective.


  12. Nice write up. Looking forward to a future follow up post.


  13. Very insightful article and I’ve enjoyed reading the rest of your Elixir posts.

    I’m really interested the statement that people felt it worked better when the only change was performance. Could this have been due to actually fixing subtle bugs during the re-write or was the Ruby version so slow that timeouts occurred? If not, then this is a really interesting finding and I’d love to see this measured in other places.

    P.S. there’s a bit of comment spam on this post.


  14. Wouldn’t it be making more sense via simple transition to jruby and running your app with something like torquebox to gain entire server box utilization (moreover, with clustering out-of-the-box!)? I’m curious if decreasing hardware costs outperformed expenses of re-implementing the app with elixir…


  15. A really great platform to work, I am using these from the last few months, but found they are great.
    https://www.logoglaze.com/website-development/

Your feedback