How to pick a programming language in 2026, and where I landed
GitHub Stars Are the Wrong Instrument
For a long time the logic seemed airtight. The language with the most code on GitHub would produce the best training data. Better training data would produce better models. Better models would produce better results for developers in that language, which would attract more developers, which would generate more code. A flywheel. I believed it. Most people still do.
It’s the wrong instrument. Not slightly wrong. Wrong in the way a compass is wrong when you’re navigating by terrain.
Fluent and Wrong Is Still Wrong
I gave an agent a task last year in Ruby. It came back fast. The code was well-formatted, confident, idiomatic-looking. It was also wrong in a specific way that took me a minute to place. The patterns were pre-2015. Things the Ruby community had collectively decided were mistakes and quietly moved past. The agent didn’t know. It had learned from volume, and volume doesn’t weight recency or quality. It just counts.
Fluent is not the same as correct. Confident is not the same as current. The agent had absorbed years of Ruby’s accumulated second-guessing and handed it back to me polished.
That was the moment I stopped thinking about training data as a volume problem.
The Four Things That Actually Matter
Now when I think about language choice, I think about four things: the problem space, the operational characteristics, the abstractions the language gives you, and the quality and consistency of the training data available.
Not stars. Not job postings. Not which language the framework you like is written in. Those are rear-view mirror metrics. They tell you where a language has been, not what an agent can do with it today.
🎯 Join Groxio's Newsletter
Weekly lessons on Elixir, system design, and AI-assisted development — plus stories from our training and mentoring sessions.
We respect your privacy. No spam, unsubscribe anytime.
Some Problems Belong to Python and Julia
I want to be honest here before I make my case. Scientific computing, genomics, numerical work: the Python and Julia ecosystems own that territory and I’m not disputing it. Nx exists and it’s genuinely good, but I’m not trying to outrun NumPy. That’s not the work I do.
The work I do is agents, web applications, distributed systems, and IoT. For that stack, the calculation looks different than most people expect.
Elixir’s Operational Story Is Already Written
From the very beginning, Elixir’s selling points were throughput without Kubernetes and self-healing processes. Think about the ability to let something crash without state leaks or cascade failure. These features have always been central arguments to operations staffs. Now they’re selling points for anyone running agents in production.
Agents are reduction engines. They call tools, wait for responses, handle failures, retry. That loop has crash surfaces everywhere. The tool call times out. The external API returns something unexpected. The context grows until something gives. OTP was designed for exactly this shape of problem, forty years before anyone called it agentic. The GenServer is an agentic loop. The supervisor tree is a crash recovery system. Let it crash is not a philosophy of despair. It’s an engineering decision that happens to be perfectly suited to systems you can’t fully predict.
I have run Elixir systems on hardware I wouldn’t trust with a Python process. IoT devices with intermittent connectivity, distributed nodes with no guarantee of message delivery, web applications under load spikes I didn’t plan for. The operational story isn’t aspirational. It’s written.
The Abstractions Hold the Shape
When an agent writes code, it needs something to conform to. A shape that already exists. Without that shape, it invents one, and the one it invents is a blend of everything it has seen, weighted by frequency rather than quality.
Elixir gives the agent real shapes. The GenServer is a process with a clear interface: handle_call, handle_cast, handle_info. The behaviour is a contract: a module that promises to implement a set of functions, giving you inversion of control without ceremony. LiveView gives you rich interactive web without the JavaScript SPA overhead, with a clear model for state and events that an agent can follow without wandering.
Ash goes further. Its design philosophy is “model your domain, derive the rest.” You declare your resources, your actions, your domain logic, and the infrastructure follows. Igniter makes that generation repeatable. When an agent works inside an Ash resource, it has a grammar to follow, not a blank page. It’s a track record.
A consistent foundation produces more consistent output. That’s not an accident of implementation. It’s the design.
Consistency Beats Volume
José Valim made this case directly. In a paper published at dashbit.co, he argues that Elixir’s characteristics produce better agent output than languages with more training data but less consistency. Functional. Immutable. Pattern-matched. One idiomatic way to do most things. The AutoCodeBench study backs this empirically. Elixir outperforms what its training data volume alone would predict.
Here is my suspicion, not yet proven: the signal-to-noise ratio in the training data matters more than the raw volume. A language with a short history has fewer dead ends in it. The bad patterns didn’t have time to accumulate. The good patterns consolidated faster. The books and documentation are good, and they produce concentrated, high-quality signal. The agent learns from that differently than it learns from a million Stack Overflow answers arguing about four competing approaches from four different eras.
Python has more training data than any language alive. It also has more ways to do the same thing than any language I know. That trade-off is real, and almost nobody talks about it.
One idiomatic way to do things. Short history. Good documentation. These are not glamorous criteria. But they predict a great deal about what comes back when you hand a task to an agent.
Choose for the Agent Too, Not Just Yourself
The criteria for language choice haven’t been replaced. They’ve been extended. You still care about the ecosystem, the libraries, the hiring pool. You still care about whether the language fits the way you think.
But there’s a new question sitting alongside those: what can an agent reliably build in this language? How consistent is the output? How well does the structure hold the shape when a non-human is filling it in?
For scientific computing, the answer points to Python and Julia. For the applications I build, agents, web, distributed systems, IoT, I know where I land. The operational story is written. The abstractions hold. The training data is consistent rather than merely large. And the benchmarks, when someone finally ran them, pointed the same direction my experience had been pointing for two years.
You’re choosing a language for yourself and for the agent working alongside you. Both of them have to be able to do something useful with it.
If you want to work with someone building on these foundations, Groxio is at grox.io.
🛠 Train Teams to Make Better AI Architecture Decisions
This post is from Bruce Tate's series on what the AI coding crisis is doing to engineering teams — and what it takes to train through it instead of around it. Groxio runs private training and ongoing advisory for engineering teams using AI with Elixir, Phoenix, OTP, LiveView, Ecto, Ash, and Postgres. We start with a diagnostic conversation about where your language choices, your architecture decisions, and your codebase actually are.
— Bruce