With only six weeks for my batch at the Recurse Center, I thought I wouldn't have a ton of time to sink deeply into a project. I figured that some chunk of time would be taken up by revising my resume and participating in the social side of RC. After attending a few workshops facilitated by the wonderful faculty, I also discovered I should lean into spending time doing something that was also enjoyable. It seems like a no-brainer but I had to shed my original mindset of being "productive" while in batch. You can only have so much fun doing leetcode problems...
Enter Elixir. I remember in circa 2017, a former co-worker of mine, Ben Hamill, attempted to convince the rest of the backend engineering team to write some of our webservices in Elixir. At the time, we were a polyglot shop and were mixing Go, Spring Boot, and Finagle web services with the massive Django monolith that ran MapMyFitness. We eventually coalesced on the JVM to smooth hiring and reduce some of the internal tooling we had to maintain, but that was the first I heard of Elixir. Looking back knowing what I know now about Elixir, maybe he was on to something -- the services Ben's team were building were working with a lot of streaming timeseries data from GPS and other sensors.
That year, 2017, was the last time I really had to learn a new programming language. I picked up TypeScript in 2023 but I was already familair enough with Node and JavaScript on the backend so I won't fully count that. I wrote a microservice in Go using some scaffolding a coworker had written and I also shoehorned some web services into Scala. My Scala chops at the time were... not sharp but at least I had familiarity with Maven. All of that is to say it's been a while since I had to fully immerse myself into something totally foreign.
These days, I reach for Python in most professional and personal settings. I find writing Python quite expressive and the language ships out of the box with most tools you need to solve most problems. With additional tools like requests, psycopg, and flask, you can be quite dangerous. I find pytest intuitive enough. The build tools have matured nicely over the past few years, and I lean mostly on pip-tools to do dependency tree-shaking and compile versionless requirements files for me. I recently learned about uv which seems to do a great job at solving some of the recurring issues I see with replicating Python development environments across teammembers.
I've also found a lot of joy in writing functional Python code. Functions are first class objects, mapping is nice, list comprehensions are good when not abused, lazy evaluation, dicts aren't terrible to work with, etc. etc. Add Pydantic models to make reasoning about objects easier and you have yourself a nice flexible workspace. I often preach to my teammates at work "let the language help you," and am pretty strict about adding new dependencies to Python projects, especially when it comes to AWS Lambda runtimes.
Elixir, from my initial exploration, seemed like a nice next step from the philosophies and style of programming I enjoy in Python. Both can be used for web development, which is my primary domain in software engineering, so it also seemed like a pragmatic choice. Features like immutability, pattern matching, and good concurrency primitives drew me in and finding a copy of Programming Elixir in the library at the Hub was enough to fully grab my attention for the second half of my batch.
Usually, when it comes to building software, I start with the problem I'm trying to solve and pick tools that seem well suited to solve said problem. I pretty much never pick a tool because "I like it." In the case of participating in the Recurse Center, the exercise of picking something to learn or work on for a month boiled down to how much I was going to enjoy it. To answer my original question, I'm still building my mental model of what Elixir, and Erlang, are great at. Sure, a highly concurrent, fault-tolerant, functional language that has its origins in telephony sounds useful. But what about my own use cases? What could/should I, in theory, use Elixir for? I'm keeping this questions in mind as I proceed with learning the language.
One place to start, as I've referenced in a previous blog post, is the origins of a tool. For a programming language, it's as good of a place to start as any. Going back to this talk from Eixir's creator, Jose Valim, it becomes quickly apparent that the Erlang VM is well suited to handle traffic patterns of modern day web architecture. However, Valim saw some potential to make writing code for the Erlang VM a bit more accessible/productive and extensible. The marriage of Ruby syntactic sugar and the design of Erlang creates a refreshing lens to look at problems I've become fairly familiar with.
Since Elixir is becoming increasingly popular for web servers, my first goal was to map the familiar Flask web server scaffolding to its equivalent in Elixir. Since setting that goal a few weeks ago, I think I've come quite far and learned a lot along the way. I read through the first ten chapters of Programming Elixir, taking care to do a lot of the exercises myself. I then chose to start doing Advent of Code with Elixir, something that proved to be fun for the first week, but less fun as many of the puzzles start requiring manipulations of grids. When I grew pretty tired of trying to cleverly unfold grids into a single array, I started exploring the Phoenix framework and everything underneath it. I stood up a small web server just with Plug and Cowboy to replicate a Flask app and have been impressed by how intuitive the Elixir tools feel, especially mix
as a build tool. Additionally, it feels refreshing to come to a language where there are fewer tools. At first glance, it seems like there exists more strongly vetted ways of doing things in Elixir.
This brings me to where I'm at now, and the path to understanding the next level of Elixir also feels like it's unfolding. Getting started with Plug and Cowboy is neat, but I haven't yet had to touch interacting with data stores with Ecto or scheduling jobs with Oban. Macros and metaprogramming are two powerful niceties of Elixir, and I haven't even scratched the surface of what they can do. The only introduction I've had to macros are the syntax of ExUnit and the many that are used in Phoenix applications. It all feels a lot to take in at once!
Also, while I've been exploring some modern LLM tooling at the Recurse Center, I can't help but feel like Elixir and the Erlang VM could potentially be powerful tools for ML workflows. As it turns out, there's a huge budding community of ML tooling emerging in Elixir as well with Nx. Livebooks look interesting as well. I'm sad my batch comes to an end after this week, I feel like I'm just getting started!
While I don't feel like Python tooling and things like Langchain are going away, I feel like one of the largest issues our industry is facing is scaling AI workflows down to run on smaller amounts of compute. You can only throw so many NVIDIA GPUs at a problem before you run into the current situation at OpenAI, where for every $1 they make, they spend $2. Neural nets can be made highly concurrent, and perhaps the Erlang VM is the right tool to train and run inference at smaller scale.
If you have any experience, tips, or resources when it comes to learning Elixir or any new programming language, feel free to reach out! Programming Elixir has been a great resource and I'm looking forward to moving on to Elixir in Action next.