Elixir is, at its heart, a language based upon the idea of extensible design – it’s no surprise, then, that there’s a bevy of additional frameworks designed to provide more extensibility, more capability, and more efficiency. Today, we’re going to take a look at some of those frameworks, and look at what they do. Some are large, others are small – but all of the frameworks on this list are, at the very least, worth consideration.
Phoenix’s main ethos is the mixture of proven tools and approaches with more forward-thinking implementations – due to this, it’s become a pretty popular language both within modern development circles and more traditional ones. One of the most interesting features Phoenix offers is Channels.
In essence, Channels turns the traditional web interaction paradigm on its head. Traditionally, when a user visits a web page, the content is called from a server, and the communication is then “static”. Channels create a “channel” for continuous communication, creating a connection between the client and the server that can update data actively.
For this (and many other reasons), Phoenix is a great option for modern, interactive, and dynamic APIs.
2 – Nerves
Nerves offers a simple but powerful argument – why abstract anything away from the software at all? Why not handle everything in a single, strong, effective package? Nerves is quite literally a framework, aiming to integrate network communication, discovery, and more in a simple, packaged application.
Nerves is still a relatively young framework, but the core offering is certainly alluring. API developers are often faced with an overwhelming amount of libraries, integrations, and external microservices to tie into. Often, this overwhelming option of choices can lead to a sort of panic blindness and stall the overall development, if not make the underlying codebase that much more confusing.
Accordingly, Nerves is a great choice for any Elixir API needing a full complement of systems in their framework.
3 – Sugar
In contrast to other options that focus on providing anything and everything you could need to get an API up and running in Elixir, Sugar focuses on modularity. From this modularity, a good amount of customizability is enabled, allowing for a great range of options in terms of both function and configuration.
One of the main benefits of Sugar is the fact that, when you can add and subtract anything you want, you gain a tremendous amount of speed. Given that APIs often live or die by two core metrics, availability and speed, being able to craft a lean and “as needed” API codebase is extremely valuable.
4 – Hedwig
Hedwig is an interesting framework to discuss in this context, largely because it’s a highly specific framework – its specific function is as a console adapter to enable bots in Elixir-based.
While this might seem overly specific in comparison to the more generalist approaches of other frameworks in this list, there’s certainly something to be said for how complex this type of interaction can be. The reward for implementing this type of solution more than makes up for any added complexity, though – being able to respond to questions from live users with links to documentation, for example, is a great communication paradigm that is directly enabled by a framework like this.
5 – Plug
Plug is often the first suggestion when it comes to connecting Elixir applications in any meaningful way, and for good reason – it’s highly effective and efficient. Plug uses, interestingly enough, “plugs” to receive a connection of some sort, transform that request, and pass it along. In essence, Plug is more like a protocol between components and adapters than a massive, complex framework, but what it does, it does well.
It should be noted that one of the major draws for Plug is that it’s an official part of Elixir. While it’s not by default part of the core Elixir package, it is part of the overall project. This means that as long as Elixir is maintained, the chances that Plug is maintained is pretty good.
6 – Trot
Trot is an attempt at making Plug easier to use, and thus, aims to make your Elixir (and Cowboy) applications easier to code. While it mostly succeeds in doing this, its value really depends on your specific use case.
The caveat that underlines all of this is that your need for Trot depends on your level of use for Plug. In a simple use case, where only one our two Plugs are utilized, Trot may seem an overly complex layer with little efficiency gains to be had. In more complex situations, though, Trot can result in huge gains in both esse of coding and ease of use due to how they handle routing and multiple Plugs feeding into one another.
This creates a sort of interesting use pathway – if you use Plug in complex ways, Trot is definitely worth some consideration.
7 – Placid
Placid is more a toolkit than a framework, but with so many tools on offer, it functionally fills that role rather well. Placid has built-in Configuration, Handlers, CORS, Request Parsing, Routing, and more, and is designed to serve as a RESTful collection of tools to enable high flexibility, extensibility, and usability.
One of the big points highlighted throughout Placid’s documentation is the idea of leveraging this toolset to deliver fault-tolerance. This is a very common use case, especially around both its Routing and Request Parsing systems. For this reason, Placid is a relatively common recommendation for those looking to build fault-tolerant HTTP APIs on Elixir.
8 – Kitto
Kitto is a very specific, single-purpose framework designed to create dashboards. That being said, it does this really well, and is certainly a value-adding addition.
Interestingly, one of the best use cases for this sort of application is not the forward-facing dashboard you might expect, where social content is synchronized and shared – instead, this sort of dashboard could bring a lot of value to a development team wanting to version, show waterfall development processes, etc. For this reason, Kitto should be seen as a framework both enabling public sharing and team development, both as a social and development tool.
9 – Maru
Maru bills itself as a REST-like API framework, and specifically calls out several existing and common frameworks (including Phoenix) as complementing solutions. Maru is best defined as a Domain-Specific Language – it offers a wide range of options for versioning, process response, and more. Of note, it doesn’t handle database connections, plug wrappers, etc. For that reason, Maru is a complement, not a replacement, for other options on this list.
10 – Flowex
Flowex is a framework that allows for a different kind of development altogether – the creators of Flowex detail this purpose as being “a set of abstractions built on top Elixir GenStage” which allows developers to utilize both the Flow-Based Programming (FBP) and Railway Oriented Programming (ROP) approaches. While these two approaches could themselves justify an entire piece, we’ll summarize them briefly here.
In essence, both these development paths expect developers to pay time and attention to the reality that there is no perfect use scenario – users won’t always use the processes properly, environments won’t always be stable, and failure is something that should be supported, not abstracted away with a simple error code. The approach then is to define specific processes (“black box process” in FBP and railway pathing logic or “stations” in ROP), and ensure that use cases are pushed along pre-defined paths rather than to pre-defined endpoints.
This allows for much greater flexibility in Elixir packages, and specifically codes a sort of “failure pathing” into Elixir proper.
11 – Raxx
Raxx bills itself as a “specification of a pure interface for webservers and frameworks”, and it certainly reflects this in its approach. The entire idea of Raxx is to mirror the underlying HTTP transformation flow and server interaction scheme in order to make for a “pure” and simple interactive experience. First, the positive of such an approach – Raxx is efficient and highly specific as to what it does, how it does it, and how quickly it does it. Accordingly, Raxx is a great option for someone looking to optimize their transformation flow in a very transparent way.
Of course, there is a significant negative – simplicity in approach typically means limitations to overall complexity. Raxx acknowledges this in its documentation, suggesting that two common use cases – large responses for transformations, such as an HD video as a response, and single requests resulting in multiple responses (such as WebSockets and server-sent events) – are not appropriate for Raxx APIs. For that reason, Raxx should be considered a great option, but one with specific requirements dictating its adoption.
12 – Weber
Weber is a framework strong with the idea of flexibility. Boasting highly flexible routing, WebSockets support, and project generation methods, it was (at least for a time) a very popular and strong option for Elixir-based developers.
The main problem with Weber is that it’s not actively maintained. While some forks and secondary extensions do exist for Weber, its popularity has waned over time – more aged codebases are harder to integrate, and quickly fall out of use as the web changes and morphs. That being said, it’s not uncommon to still see in the wild, and as such, it bears mentioning in this list.
13 – Anubis
Anubis really only does one thing – it allows for the creation of CLI applications in Elixir through the use of a simple, streamlined library. That being said, Anubis does this particular thing very well, and suggests several use cases for implementation. Chief amongst these is the ability to export the application as a whole into a clean, efficient, and transportable script which can be simply invoked to do just about anything a traditional CLI might do.
Elixir is a powerful language, and with the frameworks discussed in this piece, it only becomes more powerful. With such a wide variety of options, Elixir can be a good choice for almost any project or modern application. What do you think about the frameworks featured here? Did we miss any significant frameworks? What do you think about single-purpose or “limited scope” frameworks that do one thing, but do it well? Let us know in the comments below!