Is Vibe Coding the New Rails?
Remember how magical Rails felt in the early days? So does Vibe Coding. But after two decades in software, I’ve learned where that magic tends to break.

This post is pretty technical. I tried to make it accessible, but it’s still too nerdy. Sorry!
I love Ruby on Rails. It’s the tech stack I’ve spent most of my 22+ years tech career on.
Many of Rails’s promises and temptations, back when it was created, remind me of those of AI and Vibe Coding (coding with heavy assistance from AI with little direct interference). So I want to do an exploration of Rails and Vibe Coding’s parallels and differences.
And, hopefully, learn a bit from the past.
The promise of 2005 Rails
In 2005, David Heinemeier Hansson (DHH), the creator of Ruby on Rails, presented his iconic demo “How to build a blog engine in 15 minutes using Ruby on Rails.”
I was incredibly impressed with Rails’s productivity and the simplicity it brought for Web Development, which at the time was dominated by Java (J2EE), PHP pages, and CGI.
On one hand, Rails automated many of our boring tasks and boilerplates through automation. On the other hand, many of Rails’s features were often described as “magic”, with both positive and negative connotations.
Some of the later criticism applied to Rails was that while it was great for greenfield applications, it soon turned into code that was hard to maintain: runtime errors, hard to debug magic and monkeypatching, poor interpreter and vm (ruby), slow tests, bloated memory.
Guess what today automates boring tasks, seems like magic, and has a reputation for being good for greenfield but being hard to maintain?
That’s right: Vibe Coding.
So is Vibe Coding the new Rails?
To explore parallels with Vibe Coding, I’d like to describe a bit how Rails has worked in my professional experience: what it enabled, what it hid, and what it demanded from me as my projects grew.
Rails was magic, at first
My first Rails job was to rewrite a PHP web app and web server in Rails.
I was working on a big Java web application at the time, and the big company I was at was clear that they wouldn’t use Rails.
I remember one of my first tasks was to implement a sign-up flow, and how I did it in a day, thinking “this would have taken me weeks in my previous job.”
We rewrote the PHP web app and server in Rails in no time, and the promises Rails made, for the most part, held up at first.
Then, we started using Rails in ways it wasn’t intended, and the problems began.
Rails magic backfiring
We made the mistake of using ActiveRecord, Rails’s database library, on a stateful server, and we also made the mistake of trying to use threads, even while avoiding Rails’s non-thread-safe parts. It didn’t work.
We ran into deadlocks, leaking sockets, leaking threads, leaking threadpools, leaking connections, and so many leaking abstractions.
We eventually plugged many problems, but we never truly solved them. The work was nothing like the 15 minute blog demo. Instead, it felt like trying to keep a straw house upright in a whirlwind – every time the wind blew, something fell apart.
Eventually, I joined a startup as engineer #1 and got to work on a brand-new greenfield app.
Rails made me into a better engineer
I had never been so productive. Ruby wasn’t just for Rails – it was an all-purpose language used for infrastructure, one-off processes, web-apps, configuration management, automation, etc.
To this day I believe Ruby and Rails are fantastic if they are the only tools you have to bend a computer to your will without AI assistance.
We added an incredible amount of value with minimal software engineering investment thanks to our technology choice.
Rails made me over reliant on it
I think we made a mistake in using Ruby on Rails for everything just because it was mostly good at everything.
We used Ruby instead of Ansible for infrastructure configuration management – a decision we went back and forth on.
We even used Ruby for some Windows client code, despite its painful compatibility and issues – another decision we kept re-litigating.
When you have a great hammer, everything does actually look like a nail. Despite the common saying implying otherwise, you can get a lot of stuff done in the real world by swinging a hammer.
But you’ll also leave a wake of destruction in the process, and it won’t be sustainable long-term.
Rails testing culture
Rails really implemented a lot of the best practices we have today on automated testing. Maybe there’s some disagreement here, but I think the culture of TDD and thorough coverage of automated testing for web apps came from the Rails community. It certainly was for me.
This set of automated tests was really critical because it helped us be confident that we weren’t breaking functionality when making changes, and helped us iterate more quickly in functionality, while not being overly reliant on manual QA.
But as our test suite grew, so did our problems.
Rails testing maintainability
In that job, eventually we had code so complicated that my Engineers would tongue-in-cheek call it “read-only code” because it was so hard to change, we knew any minor change could break things in really unexpected ways. The whole set of code was eventually fully rewritten in a different language. A thorough test suite didn’t help.
In fact, the test suite was too slow, and optimizing it was a constant challenge. Tests were also brittle, in part because of the Rails magic with databases and transactions, threads, loading data in and out, and third-party libraries. Some tests only worked 1 out of every 3 times, others worked at specific times in the day. Only the best engineers could debug some of these issues.
Eventually, this structure that sustained the maintainability became unmaintainable itself, and what seemed like great assurance at a small scale only created pain at a large scale.
This theme of dream at first but nightmare at scale is a common theme of my experience with Rails, and I think, for similar reasons, of vibe coding.
Lessons learned from 2 decades of developer magic
Rails was a leap compared to its CGI, PHP, and J2EE predecessors. Magic, automation, power, flexibility, and tests gave us unprecedented productivity.
But these powers also tied us into some new corners, often leading us to quickly and unwittingly dig ourselves into a hole we couldn’t climb out of.
Rails fell short when:
- The app scaled too big
- Time turned magic into tech debt
- We ventured away from the golden path
The bigger the code, the worse the problems. Complexity scales exponentially in a tangled code base, test slowness and brittleness become unmanageable, and what was easy decreases at the speed of growth.
The more time passes, the worse things get. What seemed great today seemed terrible 6 months later. Things require constant upkeep, and code is virtually impossible to throw away. Cost of ownership eventually takes 100% of total coding investment, nullifying the time available for new things.
The further out from the golden path, the worse it behaves. Memory leaks are fine on Passenger due to process restarts, but terrible on long-running processes. ActiveRecord shines in CRUDs but flails in data-heavy loads, magic is amazing until you have to debug it, and then you wish everything was accessible.
When reflecting on my current tastes for software development, I think my recommendations for avoiding Rails’s pitfalls are similar to the ones I have for Vibe Coding.
Avoiding Rails and Vibe Coding’s pitfalls
Rails is not the best tool for every job – no tool is. Neither is Vibe Coding. It’s not the answer to every programming problem.
To avoid the pitfalls of scale, long-term maintainability, and lack of reliability off the golden path, you need tools that optimize for this.
These tools will have the following characteristics:
- They are fast: At a small scale, almost nothing matters for performance. At a large scale, almost everything does. Performance, latency, and feedback loops become critical.
- They offer guarantees: Humans don’t scale with complexity. Compilers, static types, linters, automatic tests, and other computer-assisted verification matters.
- They are simple and explicit: The more moving parts your system has, the more clarity you need. Favor tools that are explicit and obvious over ones that are magical.
In short, I don’t know what’s the future of Vibe Coding as a discipline, but I think in order for it to succeed in the long term, it’s gonna be used with these 3 characteristics:
- Fast compilers and languages, to support its huge scale
- With numerous guarantees, to support our inability to verify them
- Simple and explicit, to keep them understandable by us
And I don’t think we’ve found a Vibe Coding programming language, runtime, and workflow that truly nails all three – yet.