Elixir & Phoenix for Your Next Web Application

Have you heard of Elixir and Phoenix? In this article, I will help you understand what they are and what makes them unique. I am going to go over some principles and concepts of Elixir to show you why it’s intriguing and why you should consider choosing Elixir and Phoenix for your web application. I will also cover the best ways for adopting this new technology into your organization and development team.

Why Elixir and Phoenix?

Erlang was designed within Ericsson. It’s over 25 years old and was designed for building telephone switches. From the beginning, the assumption was that it would have to deal with massive loads while maintaining uptimes in the range of 99.999% (or better). Its scalability and fault tolerance explains that great uptime. It leads to a clean, easily maintained code base - and many popular applications are already taking advantage of all the benefits with great success.

Why Elixir and Phoenix (numbers)?

  • WhatsApp: Has about 900 million users but employs only 50 engineers
  • Bleacher Report: Has gone from needing 150 servers to just 5 with ability to handle 8 times the traffic, thanks to its decision to move from Ruby on Rails monolith to Elixir Phoenix (after reaching a point when they could no longer scale it).

Quick Overview of Elixir

Elixir is a dynamic, functional language designed for building scalable and maintainable applications. It leverages the Erlang VM, known for running low-latency, distributed, and fault-tolerant systems. Elixir applications are very easy to scale; all code runs inside lightweight threads of execution (called processes) that are completely isolated and exchange information via messages. Since all threads are isolated and independent, the apps are highly fault tolerant. In any production app, things will go wrong. With Elixir, the individual threads fail gracefully and restart themselves, if necessary, without affecting the rest of the app. Elixir also provides Supervisors, which describe how to restart parts of the system if things go wrong.

Quick Overview of Phoenix

Phoenix is a web-development framework written in Elixir that implements the server-side MVC pattern. If you are familiar with web frameworks like Ruby on Rails or Python's Django, you will notice similarities between their concepts and components. Elixir’s lightweight threads make Phoenix a perfect framework for highly concurrent apps. With a real-time streaming technology called Channels, it allows an engineer to easily develop interactive experiences across browsers, native mobile apps, and embedded devices.

Development Benefits

  • Fast & light
  • Amazing concurrency (very easy to create a new processes - with amazing performance)
  • Allows you to quickly write concise code
  • Forces you to deliver simple solutions (simpler is easier to test, review, conceptualize, maintain, and extend/refactor/improve)
  • Easy to set up sockets and channels that allow you to create reactive applications


Here is an example code for setting up your custom channels on the backend:

defmodule HelloPhoenix.Endpoint do
  use Phoenix.Endpoint, otp_app: :hello_phoenix

  socket "/socket", HelloPhoenix.UserSocket
  ...
end

defmodule HelloPhoenix.UserSocket do
  use Phoenix.Socket

  ## Channels
  channel "room:*", HelloPhoenix.RoomChannel
  ...
end

defmodule HelloPhoenix.RoomChannel do
  use Phoenix.Channel

  def join("room:lobby", _message, socket) do
    {:ok, socket}
  end
  def join("room:" <> _private_room_id, _params, _socket) do
    {:error, %{reason: "unauthorized"}}
  end
end


And here is how you can easily connect to the channels in your ReactJS frontend app:

export class PhoenixChat extends React.Component {
  ...
  componentDidMount() {
    this.uuid = localStorage.phoenix_chat_uuid
    const params = { uuid: this.uuid }
    this.socket = new Socket("ws://localhost:4000/socket", { params })
    this.socket.connect()
    this.configureChannels(this.uuid)
  }

  configureChannels(room) {
    this.channel = this.socket.channel(`room:${room}`)
    this.channel.join()
      .receive("ok", ({ messages }) => {
        this.setState({
          messages: messages || []
        })
      })
      .receive("error", () => {
        console.log(`Unable to join the ${room} chat room.`)
      })
    this.channel.on("message", payload => {
      this.setState({
        messages: this.state.messages.concat([payload])
      })
    })
  }
  ...
}



To take full advantage of Elixir’s performance and concurrency, you need to use multiple processes/threads and have them do the work in parallel.


In Elixir, you can easily start a new lightweight thread to handle a request or process the data:


spawn fn ->
  message 
  |> Ricochetbot.WeatherFetcher.get_forecast
  |> Ricochetbot.SlackSender.sendmsg
end



Everything inside the “spawn” will run in a separate thread. You can also set up your threads to communicate with each other by sending and receiving messages.

Is It Right for Me?

Phoenix is ideal for highly concurrent apps; i.e. apps that have a lot of things happening at the same time. For example, a popular messaging app might have a few million people using it at any given time, and each of those users will expect to receive real-time updates when a message is sent or received. If you need your app to do a lot of number crunching or machine learning, then there are languages other than Elixir/Erlang that will probably be a better fit for you. For example, R, Java, or Python are better suited for large-scale computation. That said, for a small hackathon-type app, Phoenix is probably overkill. A self-contained JavaScript framework such as Meteor.js is hard to beat for this type of app. This is not to say that Phoenix does not perform well for apps that do not demand concurrency. Its fault tolerance alone makes it ideal for most environments. You lose very little in the way of developer efficiency for a final product that is significantly better.

How to Adopt Elixir and Phoenix into Your Organization?

Your Javascript and Ruby developers should be able to learn it quickly, and they will enjoy it! Start with small apps. If you are thinking about completely converting your existing application into Elixir and Phoenix (like Bleacher Report did), start small to check if it’s right for you. You can implement/convert only some functionalities or routes of your app and then keep converting more and more over time. Follow and join Elixir’s fast-growing community and browse through popular existing packages that can help you get your app up and running very quickly.


If you need help or have questions, please feel free to drop us a line at hello@projectricochet.com. We’d love to hear from you!


Resources


Project Ricochet is a full-service digital agency specializing in Open Source.

Is there something we can help you or your team out with?