Elixir is the productivity language of the Agentic era

I’m CTO of a scale-up called Zappi and have switched the company from Ruby to Elixir, meaning all new backend services are now Elixir. I had nudged a few teams to try it over the last few years, and all those projects have been successful. But I had held off making it a requirement because Elixir has a ramp up time that can be hard to accept under the pressure of urgent delivery. But I think AI changes that.

The point of this post is to articulate a feeling of Elixir being at an inflection point in terms of business value, and LLMs are a big part of it. Here’s why:

  • Syntactic quirks are much less of a problem when you’re pairing with an agent. Code readability is now much more important than knowing when to use keyword lists, maps or structs.
  • Old ideological battlegrounds like Phoenix Contexts fade into the background because you can breeze past that. Again, readability trumps the issue of having to make hundreds of decisions (decision fatigue) that are more stylistic at the early stages.
  • Claude is stupidly good at Elixir – arguably better than any other language (see Dashbit blog post).
  • The type system, formatting and warnings (or just mix precommit) give good quality feedback to the LLM allowing an agent to quickly recover – this will just get better. But the type system isn’t a gargantuan puzzle like it is in Rust – a lovely balance between quick to create and quick to fail.
  • I think (my gut) that the functional/immutable combo lends the LLMs to better default architecture (less slop).

Obviously, productivity in all languages is increased by Claude and friends. But I don’t think the benefits are equal. I think code writing fluency is now less important than code reading fluency (Ruby is quick to write, harder to read because of “where does this come from” etc). Go is verbose to read (to me), etc.

In the Dashbit blog post, José refers to “local reasoning” as a key hypothesis to how LLMs are able to create quality Elixir solutions. But the “local reasoning” argument applies to humans too, and I feel as the role of “judgement” becomes ever more important with AI, Elixir becomes ever more compelling.

Finally to the main point (and with apologies): I think the Elixir value prop has always been a bit hard for me to articulate to the average developer: what does “let it crash” mean to someone who hasn’t read details about OTP? Is it the best tool for ML or should we use Python? Liveview or React + REST?

But for me, the value proposition of Elixir is clear: Elixir is the productivity language of this new era. Choose it if you want to deliver fast and reliably.

Yes, there is resilience, concurrency, processes, types, Liveview, the BEAM, etc. Those are the common talking points (and real advantages), but I think there is an opportunity to reframe Elixir more simply in terms of productivity. It is a language in which a single engineer can deliver an extraordinary amount of value in an afternoon.

It is a productivity language for the Agentic era – easy for LLMs to write, easy for humans to read.

This is why I am now comfortable going all in on this language at Zappi. Optimising for productivity is a defensible no-brainer, and the productivity is real.

I hope this framing is useful to anyone considering Elixir!

29 Likes

Thanks for posting this! I’ve been trying to find a better way to advocate for Elixir, but it’s hard because of the perception that it’s difficult to find or train devs. Onboarding assistance seems like a great use-case for AI. :slight_smile:

Can’t speak for the rest, but I believe that for many of us Elixir has also been the productivity language of the pre-agentic era. Personally, it took me like a week when I first laid my eyes on it to know there was no going back.

14 Likes

Sub-topic flagged, 9 posts were split to a new thread: Ash with AI (split thread)

Encountering Elixir has been immensely changing for me pre-AI (6 or 7 years ago, I don’t recall exactly). Or maybe I was ready for a change, which made me encounter Elixir ? Anyway, since LLMs have eaten most of the public discourse about programming today, I hope a side-effect will be that new people will be brought to the BEAM for its specific properties as a runtime for agents, and that they will stay for what they discover :slight_smile:

4 Likes

I think those are all good points, and they do match my experience.

For me an important point is that Elixir is very good at connecting to and bringing in other languages when needed for libraries or speed. Thus you are not giving up those. I have had good experiences with Claude using Rustler and Zigler, and between Rust, Zig and C that solves a lot of concerns with library coverage and intense processing bits.

Let me also give a shout out and big thanks to Credo, Dialyzer and Sobelow. The quick feedback is very helpful, and at this point any issues are typically short and few. Having such automated quality checks is reassuring.

1 Like

I would have loved to use Elixir 5-7 years ago, but the companies I worked for, would not have used this, AI is the game changer for me, LLM LOVE Elixir!.

This articles and researches changed it for me

I am coming from java,golang,c++,javascript,python development worlds, because it’s the mainstream and you can get jobs for that in the age before of LLM, LLM I believe will change this, because the learning curve is lower, it’s much easier to add new libraries that exist in other langs/framework, meaning the world of programming is changing, instead of using the mainstream like before, AI-Human is the future and in this Elixir is the frontrunner, because all of Elixir developer friendly features, if you ask me new startups, new projects, will start consider Elixir more.

In my projects (Ruby, java, golang) in my company I see so much difference how LLM work with each one, in Ruby it feel so much easier, I do same tasks it took me 3-2 days in 20 minutes (I am talking about bugs/development/tests/debugging/etc.), in java/golang languages, it can take me 3-6 hours depends on feature, because the tools there are not the same level for developers as Ruby, the syntax and the runtime is tricker for LLM to understand, in my Elixir projects (private) it seem even easier for LLM to understand than even ruby, which is for me the killer reason. If you ask me the languagues of the future need to understand this issues. Elixir is the frontrunner in this.

5 Likes

Same. It was sometime in April 2016 so it’s almost 10 years ago now.

Everything just clicked. And I realized I’ve been doing programming very wrong up to that point. It was professionally and personally transformative.

5 Likes

I sincerely wish you’re right.

1 Like

I’ve been playing quite a bit lately with ChatGPT (CG) and Codex CLI (CC). Python has seemed like the Golden Path for scripting, because most LLMs have seen massive amounts of it. And, if I don’t have to write Python, I don’t mind having it in my projects. I don’t find (cleanly written) Python all that hard to read. (Bash and Lisp, not so much…)

However, I have some upcoming projects which definitely call for Elixir, so I’ve been wondering how well CG and CC would deal with them. I’d really appreciate any feedback folks might be able to give on this, particularly regarding best practices, pain points, etc.

Side Note…

Some folks here may recall the discussions of mix format from a few years ago. Dave Thomas (@PragDave) said (and I violently agreed with him :-) that in-line spacing could be very useful as a way to highlight parallel structure and generally make source code more readable.

In my case, I mostly use this to vertically align comments and create “mock tables” for case statements, data structure literals, etc. However, I’ve also used it to line up the equal signs in assignment statements and parts of successive statements which had the same internal form.

Anyway, both Dave and I were dismayed that the formatter had no way to allow this practice. (It’s a feature… :-/) To be clear, I understand the rationale: if programmers uses their own stylistic preferences, teams may get into bikeshedding arguments, have difficulty reading each other’s code, etc. Thus, I definitely agree with José about requiring PR code to be formatted in the “official” style.

However, as a largely solo programmer, none of this has been an issue for me, so I’ve always maintained my own “house style”. I’ve often speculated about creating tooling that would let me maintain multiple style conventions, but it has always seemed like Too Much Work™.

Fast forward to 2026 and my adoption of LLM-generated code. Since I want to be able to read the generated code without pain, I’d like it to use my preferred style. However, if I run code analysis and cleanup tools such as Ruff, they will merrily collapse my carefully applied spacing.

So, one quiet afternoon, I had CC create a tool chain which:

  • applied simple styling edits to its Python scripts,
  • made copies of the scripts and ran Ruff on them,
  • and edited the originals based on Ruff’s advice.

This works very smoothly, so I expect to extend it to incorporate more tools (e.g., Bandit, Black, Flake8, Pylint, Refurb, Vulture). Getting back to Elixir, I’ll certainly look into adopting the same approach regarding Credo, mix format, etc. (ducks!)

3 Likes

Same here (but with different formatting requirements, though).

This reminds me that I can now try having the LLM change how formatter works without spending too much time on that (hopefully).

Elixir remains unable to be taken seriously when its OLAP stack is so half hearted. Yes adbc, Explorer, but a python Polars expert very quickly starts eye-rolling when such obvious tasks as bigger-than-memory workflows seem to have been completely forgotten. Application of someone-else’s AI is great with NX stack, but trying to innovate within Elixir, the roots and culture as a website-creation ecosystem quickly become apparent. Let’s not forget that everything about AI workflows if you’re not just “taking” someone else’s stack (in this case python), starts with the ability to manipulate large multi-d data efficiently. And at this Elixir fails which is a real shame given such a robust foundation as the BEAM.

Nobody minds if Elixir doesn’t implement all of Python’s cruft, but what is necessary, is that the fundamentals be correct. So sure go all in with Claude, lash up some agents, copy-paste at will, but you’ll reach the limits fast if you’re doing anything serious.

Nothing can be best choice for everything for everybody all the time. For me that doesn’t take anything away from appreciating what it actually is very good for. And some specialization makes it easier to focus and shine in chosen fields. Python has it strengths and so do Elixir. As for AI stacks I regard both as orchestrators of Cuda/ Rust/ C++ stack of libraries.

I can assure you I do serious work with Claude, there is zero copy-paste, and I have yet to find any limits for my work.

3 Likes

So in response to your initial question, my personal experience is that Claude Opus 4.6 hardly makes any mistakes in Elixir now. I check most of the code and I very rarely need to intervene, even stylistically. I suspect the fact it is a small-ish language, immutable and functional plays a bit part. But I am even more sure that José’s idea of “local reasoning” (where you can easily reason about code because most of the stuff you need to care about is in the same file) is even more important (and side note: I think monkey patching, concerns, operator overloading and inheritance are the opposite of this).

We are one-shotting applications that would have taken us months before in Ruby/Python + React. My belief is that Elixir is hard to beat for the time-to-first-value case.

Where we need custom AI, we do fall back on Python. But 95% of our tech stack is Web+FrontEnd+Redis+Backend+API+DB.

2 Likes

At the possible risk of derailing the discussion, I’d like to talk about the use of other (supporting) languages in LLM-assisted development projects. FWIW, I’ve been using a form of spec-driven development, with:

  • Formalized English (FE) for high-level conventions, rules, specs, etc.
  • Markdown (with YAML metadata headers) for almost everything.
  • Python scripts for achieving and monitoring deterministic behavior
  • YAML for file headers and reference files (e.g., readable by scripts).

So, for example, each script has its own companion spec file (e.g., foo.py has _spex/foo.fe.md) and most directories have _{index,readme}.md files.

In most Elixir projects, much of the documentation for files tends to be kept in the file itself (props to José et al for this!). I’m not sure how this would fit in with spec files and such, but I imagine I’ll find out (:-).

1 Like

Curious to see examples, if you’re willing to share.

I’m quite willing to share. In fact, I’ve been working toward getting things in shape to push to GitHub. But finding an interesting but relatively small example could be a challenge. Hmmmm; here’s something from a small subproject.

To be clear, CC wrote most of the following Markdown, Python, and YAML text. I simply:

  • provided a short prompt describing the behavior
  • scanned and tweaked the MD, made suggestions, etc.
  • had CC try out the code and iterated until it “worked”.

TBH, I didn’t even inspect the Python code. However, the plan is to have it (mechanically) inspected, reformatted, etc.

That said, here is the YAML header from the subproject spec file:

---
title:       CC One-Off Execution Staging
path:        WB/core/convs/meta/cc_one_offs.fe.md

role:        convention
scope:       conventions
status:      active
---

Here is the start (~25%) of the spec’s Markdown content.

CC One-Off Execution Staging

Purpose

Define how CC should stage one-off generated execution artifacts so that runs are inspectable, auditable, and (perhaps) reusable.

Scope

This convention applies whenever CC generates and executes a non-trivial command, program, or patch artifact.

Examples include:

  • interpreted scripts (Awk, Perl, Python, sed, shell, etc.)
  • patch artifacts (.diff) applied with patch
  • compiled workflows (source + build/run commands)
  • multi-step one-off command sequences

Required Behavior

CC should not execute non-trivial generated logic only as inline terminal payload (e.g., heredoc-only execution).

CC should also not create or edit non-trivial one-off artifacts via heredoc payloads (e.g., cat <<EOF ... for script content). Compose/edit the artifact using staged files and normal file-edit workflows, then execute from the staged artifact.

Instead, CC should stage reusable artifacts under Big/one_offs/YYYY-MM-DD/.

Here are the header and spec for one of the working scripts.

---
title:       stage_one_off Spec
path:        WB/tools/CC/one_offs/_spex/stage_one_off.spec.fe.md

role:        specification
scope:       maintenance
status:      active
---

stage_one_off Spec

Purpose

Create a one-off script and paired spec under Big/one_offs/YYYY-MM-DD/ using HHMMaa naming.

Why

Avoids heredoc-only execution artifacts in terminal logs and preserves reusable code plus spec context.

Usage

script=WB/tools/CC/one_offs/stage_one_off.py

python3 $script \
  --title "scan for X" \
  --motivation "Need one-time analysis for Y" \
  --usage-notes "Adjust target path if needed" \
  --expected-results "Generates report file" \
  --evaluation "TBD after run"

Inputs

  • --title (required): short readable purpose.
  • --ext: extension for code artifact (py default).
  • Optional prose fields for motivation, usage notes, expected results,
    and evaluation.

Outputs

  • Big/one_offs/YYYY-MM-DD/HHMMaa.<ext>
  • Big/one_offs/YYYY-MM-DD/HHMMaa.spec.fe.md

Side Effects

  • Creates date bucket directory if missing.
  • Marks .py and .sh outputs executable.

Notes

  • HHMMaa slot selection avoids collisions in a single minute.
  • Intended replacement for ad hoc heredoc-only scripts.
1 Like

I think we are going towards, or at least opening up for, specification driven development.

My current approach is caveman like in comparison. I use skills for sharpening know-how for matters at hand, and I use plan mode. I always add to the plan to save it to file and use needed skills. Apart from that I usually only use two files. A key_findings.md that captures project specific issues, what has been tried, breakthroughs and so on. And a file_locations.md to keep Claude updated with locations of various data, files, code, results etc. Claude sometimes loose track of that after compaction and various mayhem follows, so that is to avoid that. After it is done I get Claude to make a technical report, but that is for documentation and easier picking up again in the future.

I’d also mention that Claude has limited understanding of project scope. So say for instance you ssh into a more powerful computer to do some heavy processing there. When done you tell Claude to tidy up and remove any files no longer needed in the project… Just don’t do that.

1 Like

I have the advantage (?) of being a retired geezer with a huge backlog of projects I could never do on my own. Also, none of what I’m doing has any privacy or proprietary concerns. So, this is sort of my model train set…

I haven’t gotten into playing with modes or models, but the CC and CG defaults work pretty well for my purposes. I use CG for idea exploration, high-level discussions, and research. I then use CC for spec hardening, implementation and testing, etc.

One experiment I’ve tried, with great success, is to have CC and CG sessions look over each other’s work. For example, have CG generate a spec, have CC critique it, then pass the analysis back to CG. Alternatively, have two CC sessions critique each other’s work. Not surprisingly, the sessions agree on most things, but the interchange can uncover corner cases, missed possibilities, etc.

However, this has required a lot of copying and pasting on my part, so I’m working on setting up better communication paths. The constraints (roughly) are that:

  • CG can’t access local files or a local web server.
  • CG can’t access any web resource that needs a login.
  • CC and CG sessions don’t share much information with each other.
  • Each session tends to start fresh, unless it’s specifically prompted.

However, the local file system and public repositories (eg, GitHub) seem to allow some interesting workarounds:

  • Use the local file system (and Git!) to maintain “system truth”.
  • Have CC instances record their activities as immutable files.
  • Maintain lots of metadata, cross-references, etc.
  • Push the entire system to a public repository.
  • Point CG to the repo and let it rummage around.
  • Have CG generate “Tasks” that can be handed back to CC.
  • Profit!

Skills look very tasty, but I haven’t tried using (let alone creating) any yet. One thing I really like about the emerging ecosystem is the possibility of exchanging skills, techniques, tooling, etc. If these can be captured in an LLM-agnostic manner, developers might be able to leverage each other’s work in very powerful ways. For example, there could be:

  • an LLM-friendly archive of Elixir-specific skills, tooling, etc.
  • an MCP server for hex(docs).pm
  • and a pony…
1 Like

Last year I thought I’d set up some sophisticated setup, and I gave it decent shot for about two months, but apart from the formal specifications I’m not sure that is for me. These days I focus on an exact prompt for planning in the beginning, and after that it is chat for the most part. That works surprisingly well.

I’ve also tried having two Claudes argue with each other with me as some hapless middleman. It was actually fairly effective as for some reason they came up with different angles and possible solutions.

I’ve found that skills really help with difficult topics, avoiding small errors, sticking to idiomatic ways and being aware of and able to implement non-obvious or rare solutions that exists out there.

Yes, the long term memory remains an issue. I use a key_findings file, and that works until it gets too big. Claude will typically butcher important bits if asked to shorten it so there I still do some manual editing. I hope this is more of a temporary issue though. I expect larger context available in the future.

Last Friday I needed to make two small custom neural models for different tasks. I told Claude I wanted it done in Rust, what data was available for training and to optimize the model capacity accordingly, the input data types and structure, what I wanted as output, and the success criteria. Then I asked to get three different architectures able to solve the issue, presented with training done, and setup ready to test on the held off data. A few hours later they were done and ready, and after testing I had several options that surpassed the requirements. Some years ago I would have been locked to some Python libraries for days to just make one.

I think this is utterly amazing, and I find myself doing things and testing options which l would never even have considered before. And we are likely still just in the very feebly beginnings.

The ability to be able to share and build up major skill sets is really interesting. Another side of this is that language itself matters less. If I want something with a web UI and some heavy processing the Claude plan will typically suggest Phoenix Liveview for UI, Rust for the heavy processing, and Rustler. (And it usually works as planned). If I had made skills and shown preferences for Go and Python earlier it would probably made that work instead.

Once in a while Claude makes some outbursts. I’ve been informed that ‘I’m very frustrating’. (Probably true if you try to be lazy I wont let you). And my favorite when I had the bright idea to put Claude in charge of setting up an old Jetson Orin. After about two hours there was this unprompted: “Dependency hell!” (So true! That is why Claude got the job!)

This turned into a bit of rambling brain droppings, but well, I’ve typed it so I’m pressing the button anyway!

1 Like