What went wrong?

Rust vs Elixir, with 50 agents

After this, you’ll understand Why the language I bet on for AI-written code lost a two-month bakeoff to Elixir: Rust was fine, but its build tooling assumes one person with a warm cache, and 50 agents in fresh checkouts with dozens of PRs in CI break that assumption. What to ask about your own stack before your team becomes a few people and a lot of agents.

In January I wrote that languages like Rust would matter more as AI writes more of our code. The more the compiler can verify, the less a human has to. I believed it enough to build Pilecat, the platform my agent squads run on, in Rust.

In September I froze the Rust code and rebuilt the platform in Elixir.

This isn't a benchmark. It's a battle wound, and I think the lesson generalizes to any team that is about to become a few people and a lot of agents. Rust the language was fine. The tooling around it was built for a world where one person sits at one machine, and that is not the world my agents live in.

How the bakeoff happened

It didn't start as a bakeoff. It started as a verification idea.

For about two months I ran two backends for the same product: one in Rust, one in Elixir, each with its own squad of agents. Both had to pass the same suite of outer specs, tests that talk to the server the way a customer would and never look at the implementation. The point was a second opinion. When two implementations disagree, either one has a bug or the spec never said, and both are worth knowing.

It worked as intended. The specs caught real bugs in both, including one where the server accepted a token type it should have rejected. It also came with a tax I underestimated. To keep the two from drifting, the squads ended up mirroring 46 database migrations by hand and sharing a single database function so the two couldn't disagree about state transitions. By mid-September, the Rust squad had 203 commits and the Elixir squad had 195. Almost a tie in effort, on the same product.

That near tie is what made the comparison fair. Same agents, same specs, same amount of work. The difference showed up somewhere I wasn't looking.

Rust's problem was the build, not the language

The agents wrote good Rust. It was lower level than a web server really needs, but it was fast and it was correct as far as the compiler could tell.

That last part has an asterisk. The server ran roughly 1,370 database queries written as plain strings, so the compiler never checked the part of the code that most often broke. The guarantees I chose Rust for covered less of the real risk than I thought. The outer specs did the actual catching, in both languages.

The real cost was the build. Rust's tooling assumes a warm cache: the first compile is slow, and every compile after it reuses that work. That's a great deal for one developer on one laptop.

My agents don't work like that. Each one works in its own fresh copy of the repository so they don't trip over each other, and a fresh copy has no warm cache. Every agent paid the full compile, every time. A single checkout's build folder reached 23 GB, each agent copy added a few more, and at one point my laptop held 47 GB of Rust build artifacts. Run 30 to 40 agents on one machine and you are moving 100 to 200 GB of cache around just to get started.

CI took the worst of it. With dozens of pull requests open at once, CI stops being a step in the pipeline and becomes the factory floor. Every change runs the full suite, and every run starts cold. Our median CI run was 15 minutes.

So we treated it as an infrastructure problem. One agent shipped nine CI pull requests: shared compile caches, a faster linker, pre-built dependency snapshots, test sharding. We ran 64 self-hosted runners, enough that waiting in the queue wasn't the bottleneck. The best run we ever got was just under four minutes, because the critical path was a single Rust build that no amount of parallelism could split. The budget was two minutes, and the goal was one. We never met either.

At agent scale, a 15-minute CI means your agents spend most of the day waiting, and waiting agents still cost money.

Elixir held up where it mattered

The Elixir backend's entire build output was about 35 MB. On the same CI job it was already faster in July, before anyone had tuned anything.

It still verifies. Recent Elixir versions infer types across the whole codebase as part of compilation, and we treat every warning as a failure. We deliberately skipped the slower, optional type checker because it would have eaten the build budget. Tests and outer specs carry the rest.

The bigger surprise was the runtime. Elixir runs on the Erlang VM, which was built to keep telephone switches running while handling enormous numbers of small, independent conversations. An agent platform has the same shape: many agents, each with its own inbox, connecting and disconnecting, some of them crashing. "One of them died, restart it cleanly" was a solved problem in Erlang long before anyone was building agents.

When we reviewed the two months of history, every Elixir complaint was environmental: a dependency lock mismatch, two tests fighting over the same port, a fixture missing its signing key. Nobody, human or agent, filed a complaint about Elixir build times.

I picked the wrong winner first

Running two backends doubles the work, and in mid-September I decided we couldn't afford it. I kept Rust, the one I thought of as the real implementation, and retired Elixir.

Eleven days later I reversed the decision. I froze Rust, started a fresh repository and a fresh schema with zero rows carried over, and had the squads rebuild the platform in Elixir, with one small Go binary for the part that runs on each machine. The rewrite hit its first milestone two days later. It replaced a 79,000-line Rust server with about a third of the code, and it now carries my squads, around 100 agents.

For leaders, that's the second lesson. A rewrite like this used to be a year-long, bet-the-company decision, which is why teams lived with the wrong stack for a decade. With agents it took a long weekend. Changing your mind has become cheap. Staying on a stack that fights your agents has not.

Caching built for humans misleads agents

One more curiosity, because it surprised me. After the move, Go's test cache started reporting tests as passed without running them, because nothing it tracked had changed. A human developer would never notice; that cache exists to save them a few seconds. With agents relying on green checks to decide what's done, a cached "pass" is a false statement. We had to turn it off.

It's the same lesson in a different language. Most developer tooling optimizes for one person's warm loop. When the developer is 50 agents in fresh copies, those optimizations either stop helping or start lying.

What still hurts

CI is better, but it isn't under a minute. Dozens of concurrent pull requests put pressure on any CI, whatever the language, and right now our limit is the hardware on one CI machine, not the compiler. It's also early: Elixir will show me its own problems at a scale I haven't reached yet.

What I'd ask your team

If your engineers are about to run dozens of agents each, look at your stack from the agents' side.

Rust is a great language, and I'd still pick it for some jobs. For a platform where agents build everything from scratch all day, the answer for me was Elixir.