Elixir has been making its presence known more and more around our office. A few of our developers have been touting the speed and wonders that lie within. At Collective Idea we encourage our team to learn by allowing professional development time and encouraging conferences. Last year for one of my conferences I decided to […]
Elixir has been making its presence known more and more around our office. A few of our developers have been touting the speed and wonders that lie within. At Collective Idea we encourage our team to learn by allowing professional development time and encouraging conferences.
Last year for one of my conferences I decided to attend ElixirConf without having much prior experience. The conference was a wonderful learning experience and exposed me to many of the features and capabilities of Elixir. It also exposed me to some incredible libraries and frameworks built on top of Elixir such as Phoenix, Nerves, and Absinthe.
I came away from the conference with a new understanding of the possibilities and a desire to learn more. Shortly after, an opportunity presented itself to build a new version of an outdated Ruby API. We debated a number of technology stacks but ultimately landed on doing a ‘proof of concept’ with Elixir.
We were hesitant to choose Elixir given it being relatively new but the Erlang VM running behind it has lots of history. We had a few key features we were looking for in a new technology stack and Elixir seemed like a great fit.
When you think about performance it’s usually in relation to raw numbers and benchmarks. Elixir is an incredible language and very fast but it can’t compete in raw numbers with the likes of machine-compiled languages like C/C++. When we first chose to use Elixir I was concerned with how raw performance would impact us. So far, we can’t be more pleased.
Elixir code runs inside the Erlang Virtual Machine which is essentially like an operating system running on top of the existing operating system. The Erlang Virtual Machine is in charge of managing the various processes of your application and making sure they perform efficiently and without major impact to the system. Things like garbage collection are done per process. IO and CPU usage are load balanced across the cores on your machine. This helps to keep the system running smoothly under heavy load and to utilize the whole machine.
These Erlang VM features have been made readily accessible to developers so building software that can utilize the whole machine becomes much more approachable in Elixir than in thread based languages. Even things like the test suite are run in parallel. Our test suite on this new project with 200 full-stack (but not browser) tests is usually around 4 seconds. We’re using CircleCI to spin up a virtual machine and run the tests for new GitHub Pull Requests. PR’s are usually tested and ready to merge before finishing our comments. This made working in and refactoring the codebase refreshing, but the real benefits start to materialize when you get into concurrency.
The API we were building had some requirements around real-time updates. Elixir, Phoenix, and Absinthe shine here. Instead of the typical REST API pulling for information, we had a shiny new toolbox full of options for web sockets. It feels incredible to finally have some workable new tools that make you think outside of the box with your tooling.
Elixir Processes are at the center and allow for a similar capability to operating system threads but are incredibly light and simple to work with. So light are processes that you can have tens or hundreds of thousands running on one system. Processes are managed by the Erlang scheduler and distributed to all the CPU cores on a machine for amazing concurrent and parallel performance.
If you haven’t been exposed to GraphQL yet you should take a look. It’s a wonderful specification for building structured API’s that return only the information a client needs. GraphQL queries are at the heart returning a structured and typed result. The tooling around GraphQL self documents the API for users. GraphQL also has
mutations for altering data and
subscriptions for real-time events.
The Absinthe toolkit is the perfect answer for implementing GraphQL with Elixir. It integrates beautifully into your Elixir project and has an incredible amount of features and flexibility. When you start getting deeper into Absinthe I highly recommend the book Craft GraphQL APIs in Elixir with Absinthe made by the authors to fill in any questions. GraphQL subscriptions are a perfect use of processes and web socket channels in Elixir / Phoenix.
One additional feature, given our need for realtime updates, was to have some intelligence in the system around who is online. Quietly hiding inside Phoenix is the Presence module providing exactly that. The Presence module makes wonderful use of web sockets, channels, and processes to enable real-time notifications of users coming and going from your services. The Presence functionality makes use of a built-in Phoenix PubSub server to handle user tracking in a lightweight way. Presence is a great example of a feature that is simple to add into your codebase when the underlying ecosystem supports it.
In the end, we could not be happier with our choice to use Elixir. The ‘proof of concept’ quickly turned into our production codebase. We’re loving the speed of development and server performance. Being exposed to new ways to solve old problems has empowered us to think outside of the box. Elixir fits in perfectly with modern features expected of web and mobile applications such as web sockets and GraphQL API’s. It’s ecosystem of Processes, Channels, GenServers, Presence, and more enable an incredible amount of new power for developers.
We’re excited about the future of Elixir and how we can harness it for making the next level of applications for our clients.
Source: Collective Idea