Sorry, you still have to think: lessons from the AI rewrites of Campfire
Translated by a model; the original is in Russian.
Rails creator David Heinemeier Hansson (DHH) decided to rewrite the Campfire Once messenger from Rails to Rust — or rather, he had an AI agent do it, since he can't stand reading or writing Rust himself. Versions in Elixir and Go followed. Piotr Sarnacki sees this as a valuable experiment: what happens when an experienced programmer leans on AI agents without looking at the code.
A vague prompt is a coin flip
The takeaway is discouraging for anyone hoping to stop reading code. The real issue isn't bugs but the fact that many decisions have no single correct answer. Keep backwards compatibility? Favour latency or throughput? Is losing notifications after a crash acceptable? If your prompt isn't specific, the model silently answers these for you.
Hence the divergence. The Rust version doesn't keep full backwards compatibility: it drops the CSRF token to make caching easier and replaces Redis with in-process queues. The Elixir version stays much closer to the original. That difference is language-independent — and already renders the comparison meaningless.
You really should read the code
In the Elixir version a single sequential process handles every SQL query, even concurrent reads. But the Rust version is no model citizen either: some database operations run synchronously. Rust's async runtime schedules cooperatively — if a task doesn't yield, others on the same thread wait. A blocking query, or a sync lock held for 10ms, stalls everything. The author's verdict: no, coding is not "solved."
Benchmarks are slop too
Zach Daniels measured notification delivery under load: Rust managed a 1% success rate. But both tests were closed-loop (a client sends a message only after a response). Sarnacki reran it with a constant arrival rate: at 100 POSTs/s Rust delivered ~14% of events, Elixir ~60%. Yet Rust produced no HTTP errors, whereas Elixir timed out on ~23% of requests, with delivery latency reaching 180 seconds.
The Rust losses come from a tokio::sync::broadcast channel capped at 256; an overwhelmed receiver gets a Lagged error. Elixir's GenServer mailboxes are unbounded by default. Raising the capacity to 16384 pushes delivery to ~90% — but latency jumps from 11s to over 130s. The author calls that worse: sometimes it's better to "fail fast" and disconnect a lagging client than to serve it agonizingly slowly. Elixir, meanwhile, hit 1.8GB of memory at 100 req/s — so, drop messages or get OOM-killed?
The point
Programming is all about trade-offs. Elixir is good at concurrency but no silver bullet. You still have to think critically: don't draw sweeping conclusions from a single metric, know when a system should fail, and remember that good benchmarks are hard to write.
Source: Hacker News
Comments
Sign in, to comment.