Rails World 2026 opened with DHH retiring the pencil and closed with Aaron Patterson explaining the C++ "as-if rule". The internet scored it as a feud. It was a narrower and more useful disagreement, about who keeps the promise that the code does what it says, and a working Rails shop has to pick a side of it by Monday.

Rails World 2026 had two keynotes, and the internet has decided they were a fight.
On the Wednesday morning in Austin, David Heinemeier Hansson told about a thousand Rails developers that “writing code by hand is no longer an economically productive enterprise for the vast majority of programmers working at the vast majority of companies”, that 37signals had gone “pencils down”, and that the right response was to “take the white pill. Take the optimism pill.” The black pill, he added, “is for […] losers. Don’t be a loser.”
On the Thursday afternoon, Aaron Patterson closed the conference by announcing his own Linux distribution (“it installs in 100 milliseconds”), taking a show of hands on “how many of you like receiving slop grenades”, and then spending forty minutes on stack frames, Ractors and the ZJIT compiler. He finished on a slide that read “Get in, loser. We’re going programming.”
r/rails called it a diss. The top post the next day was titled “Aaron Patterson… wow” and opened “This guy just hilariously dissed DHH in the closing session”. Global Nerdy called the opening keynote “the most confusing funeral I’ve ever experienced” and the closing one the wake that “brought the corpse back to life”. Fireship put DHH on a thumbnail and compared the talk to “the Pope showing up on Easter to talk about the benefits of atheism”.
We watched both talks end to end from the captions, and we want to be precise, because the disagreement is real but it is much smaller than the coverage, and the small version is the one your team actually has to settle.
Start with the context the clips leave out. Patterson has closed Rails conferences for years, and he roasts the opening keynote every time. Richard Schneeman put it plainly under the Reddit thread: “this is a long standing tradition. That Aaron gets the closing spot and will leave a large portion of his talk with space open to insert jokes after he watches Dave’s keynote.”
Then look at what each man says about AI when the other is not in the room. Patterson, on stage: “I am an AI optimist. I use AI every single day to write code.” On a podcast in August he called it “the bee’s knees” for finding his way around Shopify’s huge codebases, and said he does not mind contributors using it: “if you used AI and you understand everything it did, great.” DHH, for his part, did not tell Lex Fridman in August that he stopped reading. Describing the latest Omarchy release, he said: “I’ve reviewed the shape of all of it. I’ve reviewed the individual lines of anything that’s critical in the model layer of the system, and I’ve not looked at a bunch of the UI code.”
So both of them use agents all day. Both of them read some of the output and skip some of it. Neither of them is an AI sceptic. What separates them is one sentence, and it is worth reading slowly.
Before we side with anyone, the best case for the opening keynote, because most of it is right.
The Kodak Brownie story is a good story. Portrait painting did not die in 1900; the job of rendering reality precisely stopped paying, and the painters moved to things a camera could not do. His practical asks were excellent: ship a CLI so a customer can “bring my own butler”, and stop bolting chatbots onto your product. The native-apps point is fair too. A small team maintaining six native clients was absurd two years ago and is plausible now, and he cited Shopify’s rewritten native Shop app as proof.
His best moment was a confession. In the spring, 37signals had designers vibe-code features into Basecamp 5, and “taken together, 20 or 30 of them, it left the architecture looking a little like a Swiss cheese”. He drew the conclusion that the models were about to get better, which is partly true. On the panel with Matz later that week he said the explosion of new software will mean more work for programmers, and that “it’s not going to happen if you hold on to the pencil so tight that you can’t imagine the calculator helping you out”. We agree with that sentence completely. On the same panel he also said he now has “an agent who will explain my Rust code to me in Ruby”, which is a form of reading, and we will come back to it.
Where he goes further is here: “Rust is amazing if you never, ever, ever have to look at it yourself.” And: “I don’t know any Rust at all. I consider that a feature.” And the framing that makes it sound safe: “I evaluate the Rust box as a black box on the outside, as any business owner in history who’s ever commissioned a group of programmers to do anything for them.”
Hold on to that last line. It is the whole argument, and it is the line Patterson answered.
The closing keynote is a performance talk with a thesis hidden in it. Patterson opens with the phrase “the purpose of a system is what it does” and refines it: the purpose of a system is what it does “for those that are observing”. Then he introduces the C++ as-if rule: a compiler may apply “any optimizing transformation to a program” provided the change makes “no change in the observable behavior of the program as specified by the standard”.
The next forty minutes are a tour of what it costs to keep that promise. Ruby 4.0 inlines
initialize into the new call site, deletes a stack frame nobody looks at, and gets allocations
he measured as 70% faster. Ractors add a new observer, a second thread looking at the same memoised
instance variable, and suddenly an old pattern is a race. ZJIT makes big bets that you will not
redefine +, and keeps the promise with patch points that rewrite the machine code the moment you
do. Every optimisation, he says, has two sides: the thing that gets deleted, and whoever might notice.
Then the landing. People say AI is “just our next compiler”, and you do not read your compiler’s machine code, so why read the agent’s? His answer:
“That’s because the compiler made a promise to you. […] Now, your AI has not made this promise to you. There is no as-if rule for your English. So, I am not going to concede my destiny to AI. I’m going to keep reading my code, and I hope that you will, too.”
And, for the pill talk: “I didn’t have to take any pills to be an optimist.”
This is the paragraph we would put on a slide. A compiler can be a black box because two things stand behind it: a written standard that says what “the same behaviour” means, and a toolchain whose whole job is to keep that promise, including deoptimising at runtime when a bet goes wrong. An agent has neither. The only standard its output is held to is whatever you wrote down (tests, types, contracts, invariants you monitor), and the only enforcer is whoever reads the part the standard does not cover.
DHH’s business-owner analogy has the same shape. The business owner who commissioned programmers was never reading the code, true. They were relying on a person who could be asked why, who carried the consequences, and who read it on their behalf. Remove that person and the black box is sealed from both sides.
Patterson did not win the argument with the analogy. He won it with the second half of his talk, which he said he wrote “all day yesterday” and which most of the clips skip.
In May, RubyGems.org was flooded with junk gems in what was later called the GemStuffer campaign.
Patterson read the first write-up and shrugged, because the malicious script was not in an
extconf.rb and he could not see how it would ever run. In September researchers contacted him claiming that
agents at OpenAI (as Reuters and the Wall Street Journal later reported) had used those gems to exploit a caching bug on RubyGems.org, the one
reported and fixed in July. On his blog he wrote: “I thought the claims they were making were
completely outlandish until I actually read the code in these ‘GemStuffer’ gems.”
Reading the code is how he found the chain: a .yardopts file that made YARD load script.rb,
RubyDoc.info processing every newly published gem inside a container that still had network access,
a request that tried to harvest a cached API key, and a push of the next gem to start the loop again.
He called it a Rube Goldberg machine. The RubyGems.org team fixed it, and as far as anyone knows
nobody was harmed. The detail that matters for this argument is that a person with deep context found
the mechanism by reading code nobody was supposed to need to read.
That is also where his August podcast confession lands. “I have personally fallen into this trap with AI,” he said: it did the right thing, great, do it again, “so, eventually I start reviewing it less and less.” The trap is trust built on a streak, which is exactly how you trust a colleague, except the agent does not remember the streak and does not carry the consequences.
The sentiment was lopsided and worth reporting honestly. On r/rails the most upvoted threads of the week were hostile to the opening keynote: “DHH is completely crazy” (about 240 points and 300 comments), “Get DHH out of Rails”, “Is DHH just.. straight out lying?”. The top comment under the first one: “Imagine paying for a ticket to attend a conference to see a keynote about abandoning both your profession and the project the conference is about.” A good share of that anger is about politics and tone, and we leave it there.
There was a real minority on his side. “I think the community should take DHH’s comments more seriously and stop calling him crazy,” wrote one Rails developer since version 2, and another asked why everyone was “getting so freaking mad” when “it’s so clear where the puck is going”. Robby Russell, who spoke at the conference, posted a field report that “the vibe here is far from doom and gloom” and that “most of us are still employed as menders”.
The comment we keep coming back to was not about Rails at all. On r/ExperiencedDevs, the same day, a thread on keeping quality up under agents drew about 450 points, and its top answer said that “coding was our ‘thinking’ time, not our production time”. That is Patterson’s point in one line. The reading was never overhead. It is where the model of the system lived.
One fact from the Rails Foundation’s own site belongs in the middle of this. DHH mentioned the agent evals saturating a first benchmark at 95%. The harder benchmark now published at rubyonrails.org/ai asks models to ship 20 real feature tickets from 37signals’ Fizzy app, and the best result listed is 53.3%. That is remarkable progress and it is also roughly a coin flip on a real ticket, graded by a harness someone had to write.
We are a small Rails shop, and our position has not moved since we started writing this playbook: agents are allowed to act, inside a gate a person owns. So we take DHH’s economics and Patterson’s epistemology, and we do not think that is a fudge.
DHH is right that typing is no longer the job. Nobody on our side is defending hand-chiselling controllers; our agents write most of our diffs, and we would be lying to say otherwise. He is right that the CLI is the new front door, and right that small teams can now attempt things that used to need a department.
Patterson is right about what the job became. If there is no as-if rule for English, the working engineer’s job is to write one, and to read everything the rule does not cover. That is a concrete job with a concrete output:
The interesting thing is that DHH already runs this system. “Reviewed the shape of all of it”, “the individual lines of anything that’s critical in the model layer”, not the UI: that is a read policy with three tiers, and an agent that explains the Rust back to him in Ruby is a reader he chose to keep. The keynote simply did not mention either, and a thousand people went home with the headline instead of the policy.
The RubyGems chain would have sat in the right-hand column of most teams’ mental model. A documentation tool. A container. A cache. Every piece looked like something you judge by behaviour, and the behaviour looked fine. That is why the left-hand column has to be defined by what the code can touch, and never by how boring it looks.
Write your read policy down in one page, with the three tiers and who owns each. Put the left-hand column in your AGENTS.md so the agent flags when it touches it. Count, for one week, how many changes landed in each tier and how long a person spent on each. If the left-hand column is getting less reading time than it did last quarter, you have Patterson’s streak problem, and you found it before the incident did.
The limit, stated fairly. Compilers were not trusted on day one either. Programmers read the assembly their Fortran compilers emitted for years, and the as-if rule was written down after the tools earned it. It is possible that agents get a standard of their own (verified specs, property tests generated from requirements, runtime checks that roll back) and that in five years reading generated code looks as quaint as reading object files. DHH may be early rather than wrong, which is his usual record.
We also have a stake here. A shop that reviews code for a living has a motive to say reading matters. Discount us accordingly, and then look at who found the RubyGems exploit, and how.
Until someone ships the as-if rule for English, the promise that the code does what it says is kept by a person or by nobody. Make sure it is a person you employ.
Support automation, AI phone agents, n8n back-office work, and the engineering loop itself — always behind a gate you control.