Skip to content
All articles

Of course DHH lets AI write his code

DHH swore he'd retire before letting AI write his code. Now he does. It's not a U-turn: Rails was a coding agent two decades before coding agents existed.

The fuss

Last week, DHH, the creator of Ruby on Rails, said he isn't writing code by hand anymore. He's letting AI write it.

The reaction was loud, and understandable. About a year ago, he was one of the most vocal skeptics in our industry. He said he would never let AI write his code, and that if it ever came to that, he would rather retire.

A lot of the community read last week's news as a surprising U-turn. To me, it made total sense. In fact, if you look at what Rails has always been, it was almost inevitable.

Rails was a coding agent before coding agents

Rails was born with one obsession: speed of development. It achieved that through Convention over Configuration. Follow the conventions, and the framework makes hundreds of decisions for you.

It stacked abstraction on abstraction:

  • Ruby itself is a high-level language, and one of the closest a programming language gets to natural language. 3.days.ago and user.posts.where(published: true) read almost like English.
  • Rails implemented a huge amount of logic for us. MVC and RESTful routing came by default. Active Record turned tables into objects. Migrations, validations, mailers, background jobs: all conventional, all ready.
  • Generators shipped from the very first versions. rails generate scaffold Post title:string body:text gave you a model, a migration, a controller, views, routes and tests in seconds.

Think about what that last one really is. You describe what you want in something close to plain language, and working code comes out the other end. That's what coding agents do today. Rails did it, within a narrow but very useful scope, two decades ago.

The famous "build a blog in 15 minutes" demo wasn't about typing fast. It was about not having to type most of the code at all.

Why the switch happened now

This is exactly why DHH's skepticism a year ago was reasonable.

If you already work in one of the most productive stacks ever built, the bar for a new tool is very high. A little over a year ago, coding agents didn't clear it. They took real effort to steer, and often produced code that was verbose, inconsistent, or just wrong. For a Rails developer, the trade was bad: more time reviewing and fixing than you'd spend writing idiomatic Rails yourself.

That has changed. Recent models and agent harnesses are far better at following conventions, reading an existing codebase, running tests, and iterating on their own output. The developer experience is now genuinely different, and genuinely faster.

When a tool gets good enough to beat an already highly productive framework, moving to it isn't a betrayal of that framework's values. It's the same value, speed of development, taken one step further.

Just another layer of abstraction

The history of software is a history of climbing abstraction layers:

  1. From binary and machine code to assembly.
  2. From assembly to low-level languages like C.
  3. From low-level languages to high-level ones like Ruby, Python and JavaScript.
  4. From hand-written SQL and complex database plumbing to conventional frameworks and ORMs.
  5. And now, from writing code to describing intent to LLMs and coding agents.

Every step was met with the same worries. "Real programmers write assembly." "Frameworks hide too much." "You won't understand what's happening underneath." Every time, the industry moved up anyway, because the gain in productivity was too big to ignore.

AI is the next rung on that ladder. Not magic, not the end of programming. A new level of abstraction.

The skills don't go away. They stack.

Here's the part that often gets lost in the hype. Rails never made developers unnecessary. A scaffold could give you a working CRUD in seconds, but knowing what to build, how to model the domain, and when to break the conventions was still on you. Anyone who has inherited a Rails app built entirely from scaffolds, by someone who never really learned the framework, knows how that story ends. AI is the same, only at a much larger scale.

I find it useful to think about this as a stack. We're used to talking about a tech stack: database, backend, frontend, infrastructure. Each layer relies on the one beneath it. Software engineers working with AI now need a skills stack that works the same way. There's a foundation of traditional engineering skills, and a new layer of AI-specific skills built on top of it. Take away the foundation, and the top layer has nothing to stand on.

The foundation matters more, not less

The foundation is everything we've always needed. None of it became less important when agents started writing code. Most of it became more important, because an agent amplifies whatever judgment is steering it, good or bad.

Start with domain modeling. An agent knows a lot about code in general and nothing about your business. It doesn't know that an "order" in your company can be split across three warehouses, or that a "member" and a "user" are not the same thing. If you don't understand the problem well enough to name things right, the agent will happily name them wrong, and every file it generates afterwards will carry that mistake forward.

Then software architecture. When code was expensive to write, a bad architectural decision spread slowly, one pull request at a time. Now an agent can generate a week's worth of code in an afternoon, and a bad decision spreads just as fast. Boundaries, dependencies, data flow, where state lives: these used to be things you could fix along the way. Now they decide whether the agent's output compounds into a product or into a mess. And an agent won't weigh those trade-offs for you. It will pick something that works today.

Reading code may be the skill that grew the most. Most of us now review far more code than we write, and that code is written confidently, even when it's wrong. An agent never says "I'm not sure about this part." Spotting the subtle bug, the missing authorization check, or the N+1 query hidden inside a clean-looking method is on you. That ability doesn't come from prompting. It comes from years of writing, breaking and fixing code yourself.

Testing changed role too. Tests are no longer just a safety net. They're how you tell the agent what "done" means, and how you find out, quickly, that it isn't. An engineer who knows what to test, and at which level, gets far more out of an agent than one who lets the agent test its own assumptions.

Debugging hasn't gone anywhere either. When something breaks in production at 2 a.m., an agent can help you search logs and suggest fixes, but someone still has to understand how the system actually behaves under load, with real data, across services. Agents are good at fixing the symptom in front of them. Finding the cause needs a mental model of the whole system, and that mental model is yours to build.

Finally, security, performance and maintainability: the things that separate a demo from a product. Agents optimize for "it works right now." They don't lie awake worrying about injection attacks, a query that is fine with a thousand rows and falls over at ten million, or the engineer who has to change this code in two years. Caring about those things is still a human job.

There's a quieter point underneath all of this. Knowing what good code looks like, what experienced engineers call taste, is what lets you steer an agent at all. You can't recognize a bad solution if you've never learned what a good one looks like. That's why experience isn't losing value in the age of AI. It's becoming leverage.

The new layer on top

On top of that foundation sits a new set of skills. Prompt engineering is the most visible, but it's the thinnest part. Clear communication of intent matters, but it's only the start.

Context engineering is where things get serious. An agent is only as good as what it can see: the relevant parts of the codebase, the conventions, the docs, the examples of "this is how we do it here." Deciding what goes into that context, and what stays out, is really an exercise in understanding your own system. You can't curate context for a codebase you don't understand.

Harness engineering is the environment the agent works in: the tools it can call, the commands it can run, the permissions it has, the tests and linters that give it feedback. That's the old DevOps and tooling mindset applied to a new kind of collaborator.

Spec-driven development brings back something many teams quietly abandoned: writing down what you want before building it. A good spec, with clear requirements and acceptance criteria, is the difference between an agent that delivers and an agent that wanders. Writing a good spec requires the same domain understanding and product sense it always did.

Then there's decomposition and verification: breaking work into tasks small enough for an agent to finish and for you to check, and building the tests, evals and review habits that tell you whether the result is actually right. As the work grows, orchestration joins them. Running several agents or sessions on the same codebase without them stepping on each other is really coordination, the same thing a tech lead does with a team.

Notice the pattern: every one of these new skills is an old skill wearing new clothes. Context engineering is knowing your system. Spec-driven development is requirements and domain modeling. Harness engineering is tooling and DevOps. Verification is testing. Orchestration is technical leadership. The new layer only works because of the foundation beneath it.

Engineers vs. vibe coders

This is where the line between software engineers and vibe coders becomes clear.

A vibe coder works only at the top layer. They prompt, accept what comes out, and judge the result by whether it seems to work. To be fair, that's a perfectly valid way to build a prototype, a weekend project, or an internal tool nobody depends on. I'm not against it. The problems start when that code meets real users, real data and real scale. With no mental model of the system, there's no way to debug it, secure it, or change it without breaking something else. Every new prompt is a roll of the dice.

A software engineer uses exactly the same tools, but owns the result. They know why the code is shaped the way it is, what it will cost to change, and where it will fail. The difference isn't the tool. It's judgment and accountability.

When the cost of writing code drops close to zero, the value moves somewhere else: to deciding what code should exist, and knowing whether it's correct. That's the scarce skill now, and it's built on exactly the fundamentals some people are rushing to call obsolete.

No, we're not becoming obsolete

Some people took DHH's statement as proof of something darker. If even the creator of Rails isn't writing code anymore, the argument goes, programmers are done.

I read it the opposite way. DHH didn't retire. He's still building software, still making the architectural calls, still deciding what good code looks like. What changed is how the code gets typed, not who is responsible for it. The person with the strongest opinions about how software should be written just showed us that those opinions are still needed. They're what the AI gets steered by.

History points the same way. Compilers didn't end programming; they made it possible for far more people to program. High-level languages and frameworks like Rails didn't shrink the industry; they made software cheap enough that everyone wanted more of it. Each time the cost of building software dropped, demand for software grew.

That doesn't mean nothing changes. The part of the job that was mostly typing boilerplate is going away, but Rails generators were already eating that part twenty years ago. Roles will shift, some tasks will disappear, and engineers who refuse to learn the new layer will have a harder time. That's been true of every shift in our industry. What doesn't become obsolete is the ability to understand a problem, design a system, and take responsibility for whether it works.

Same philosophy, new tool

DHH didn't abandon the Rails philosophy. He followed it.

Rails always asked: what's the fastest way to get from an idea to working software, without sacrificing quality? For twenty years, the answer was conventions, generators, and a beautiful language. Today, the answer includes AI.

The developers who thrive won't be the ones who refuse the new layer, or the ones who blindly trust it. They'll be the ones who bring solid engineering fundamentals to it, and learn the new skills it demands.

What about you: has AI changed how you write code this past year, or are you still where DHH was twelve months ago?