Some Reflections on using Elixir in Production at a Small Startup

Ani Ravi,ElixirProgramming Languages

If you've read my previous blog posts, you know that I'm generally biased toward languages that have strong static analysis tools, so less stuff gets put in production that isn't verified by a compiler. However, it's almost inevitable in your programming journey nowadays that you will work in some language with almost no static analysis tooling, at least at most young companies. As much as I love tools that can make programming more sane, it's also the case that programming tools still have a lot of room for improvement, to help aid programmers rather than needing to spend too much time type-wrangling or dealing with unclear errors. I've been using Elixir for some time now, and used to have a more negative opinion of it starting out, primarily because dealing with constant runtime errors was super annoying (still is) and it felt slow to build new features when having to keep all the information in my head. While there are some shortcomings in terms of things I like having in a language, some of Elixir's tools are great.

Most people often talk about how networking tooling in Elixir is awesome, since communicating between processes and external servers is basically "built-in", so network clustering in Elixir (especially for building things like chat apps) is much simpler than in other languages. However, I think Elixir's "killer app" is Ecto (opens in a new tab), Elixir's database access library, primarily used with PostgreSQL. Ecto is pretty powerful, relies heavily on macros, and makes composing SQL (especially dynamic queries where you chain query fragments together in different situations) really easy. We make use of these aspects of Ecto heavily in production. As much as I love statically-typed languages, I don't know how to make SQL as fluid, maintainable, and as easy-to-use as Ecto does in Elixir. It's actually one of the biggest reasons why we haven't seriously looked at any other backend languages for our Elixir codebase - Ecto is just that much easier to use and makes writing new features that much faster (if anyone knows how I can get composable queries, reusable query fragments, helpers to write things like joins, and raw SQL-level performance from a language like Haskell or Rust, please let me know)!

Ecto combined with Absinthe (opens in a new tab) (Elixir's premier GraphQL server library) is a really good combination to get you started - it reduces the amount of code you have to write significantly for doing data access and the performance is good enough. Ecto schemas maintain the associations between different tables, and Absinthe + Ecto can figure out how to query a good amount of data simply by using dataloader and not having to handwrite a lot of joins or other queries. Many of Elixir's most popular libraries make use of macros and DSLs to express ideas in non-standard Elixir syntax (like the two aforementioned libraries), and while it may make things a little harder to understand at the beginning of your journey with Elixir, every engineer I've worked with figures it out quickly.

Elixir is still growing but still a fairly young ecosystem, and so there's ever more tools/libraries (opens in a new tab) being developed. It has just enough of the tracing, logging, API, security, DB, and websocket tooling that you need to build a serious app in production. It also has some insane features like being able to directly call or run your production code, and hot code reloading modules in your production process.

Every set of tools comes with tradeoffs, and different tradeoffs will affect you in different ways at different stages of your product. It's worthwhile to have periods of reflection to re-evaluate whether you're using the best tools available to you to solve the problems ahead, and thinking through how much effort it would take to change tools if needed. Elixir is mostly a simple language to learn, and can get you started fairly quickly if that's what you're looking for. It's also a decent gateway into some functional programming ideas, but if you're looking for tooling that dives headfirst into FP ideas, I would look at other languages instead. I'm not sure when or if Elixir's usage will dwindle for our product in favor of other tools, but for now, it's taken us quite far!

Ani Ravi