DEV Community

Cover image for Long Live Rails
Ben Halpern
Ben Halpern Subscriber Community Curator

Posted on AI-assisted

Long Live Rails

When DHH took the stage at Rails World 2026 and talked openly about going "pencils down" on hand-typing code—and about just how much Rust he and 37signals are shipping now—a predictable subset of the internet treated it like a concession speech.

Even the creator of Ruby on Rails, who joked in the same breath that reading Rust is like "pouring acid in my eyes," was raving about 30x to 100x speedups, minuscule binaries, and sub-millisecond startups once AI agents handle the borrow checker. If he is reaching for Rust, what does that say about Ruby and Rails?

I think that reaction gets the story completely backwards.

Over the past month on Forem (the Rails monolith that powers DEV), we have been gradually replacing dozens of our own internal Ruby modules with Rust. As I wrote in Our Looping Factory Cut DEV Page Load Time by 75% and Counting, one of the autonomous workflows running continuously against our codebase is a dedicated rust-loop that ports CPU-bound and allocation-heavy Ruby hot paths into an in-process Rust extension (gems/forem_native) via magnus and rb-sys.

Far from making me question Rails, watching this happen in production has made me appreciate Rails more than ever. The fact that dropping Rust into a Rails codebase is this accessible is a feature, not a bug.

Rust inside the monolith is a superpower

There used to be an unspoken cliff in dynamic web frameworks: Ruby got you to product-market fit with unmatched developer happiness, and then the day your string parsing, feed scoring, or serialization paths started choking the garbage collector, someone pitched splitting off a Go or Rust microservice. Suddenly one cohesive application became two deployments, a network hop, duplicate auth assumptions, and an operational tax you paid forever.

Today, that cliff is mostly gone—both ergonomically and architecturally.

Inside Forem, we split gems/forem_native into a pure-Rust forem_core crate (with zero Ruby dependencies) and a ~15-line-per-function magnus wrapper that borrows Ruby string buffers in place with zero serialization or memory copies. Our rust-loop—monitored alongside eight other maintenance loops in the control panel I described in Ask More of Your UI—has steadily moved hot leaf and pipeline modules over to Rust:

  • Markdown pre-processing, frontmatter normalization, and reading-time tokenization (~54x faster with zero Ruby heap allocations).
  • Home feed ranking and dynamic pgvector SQL expression assembly (~20x faster with 97% fewer Ruby objects allocated).
  • HTML sanitization, inline SVG icon rendering, @username mention parsing, URL normalization, Public Suffix subdomain routing, constant-time CSRF/JWT verification, and 51-pattern secret scrubbing on agent transcripts.
  • Entire pure-Ruby dependencies (gemoji, emoji_regex, wcag_color_contrast) deleted outright from our Gemfile.

And yet nobody cloning Forem needs cargo installed to run bin/dev. Tiny (~300 KB) precompiled platform binaries load in under a millisecond on macOS and Linux, our Containerfile compiles a stripped shared library in a multi-stage builder with zero Rust toolchain left in the production image, and every ported function is locked down by RSpec differential specs testing 1,000+ randomized inputs against the legacy Ruby reference.

In Design for Churn, I argued that AI-era codebases behave less like static buildings and more like gardens: when rewriting implementation code gets cheap, your real investment goes into the perennial beds—the schemas, routing, boundaries, and contracts that hold steady while the annuals inside them turn over. (It is the same principle we used when bringing System One models like Jev into our AI stack: keep the policy and domain structure clean in Ruby, and swap in specialized engines underneath.)

Rails is the perennial bed. As @techie_raj captured well in Your Rails App Is Already AI-Ready. You Just Don't Know It., twenty years of shared conventions—config/routes.rb, app/services/, declarative Active Record scopes, self-describing background jobs—gave Rails a legibility that both new hires and coding agents navigate effortlessly. And as @ttebify noted in Rust is amazing, as long as I’m not the one writing it, strict compilers give agents a tight, unforgiving feedback loop for low-level compute. Pairing Rails' high-level coherence with Rust's bare-metal leaves isn't abandoning Rails—it's Rails doing what it has always done best: orchestrating the whole system cleanly while getting out of the way when native speed matters.

Making the intuitive thing first-class

If you want a concrete example of why Rails keeps winning over the long arc, look at this gem of an addition landing in Rails 8.2 (already backported to Rails 7.2, 8.0, and 8.1 via rails-query-command):

Every team putting AI coding agents to real work eventually runs into the exact same wall: agents reading static source files in isolation guess wrong about production bottlenecks, and you obviously cannot hand an autonomous agent an unrestricted rails console or rails runner against live data. (I wrote recently in AI Engineering Has Entered Its Audit Era about how scoping agent authority and proving output has become the real engineering work, a theme @oleksandr_sainchuk also explored on the write side in How we keep AI agent actions under server side control in rails.)

At Forem, unlocking our 70ms-to-16ms latency drop required building our own bespoke workaround for this: a read-only Postgres gateway (forem-db-query) wrapped in a privacy guard so our performance loops could inspect live query plans, sequential scans, and row distributions safely before touching a line of code. Plenty of other teams have quietly cobbled together their own read-only wrappers, MCP tools, or custom rake tasks to solve the exact same problem.

Even when we and others already have workarounds for something like this, the whole point of Rails is that it makes intuitive, necessary things first-class in a way that pays off in the long run.

When bin/rails query becomes a standard verb across the entire ecosystem—read-only by contract, emitting structured JSON, with schema, models, and explain built right in—twenty bespoke team scripts collapse into one shared convention. Every developer, every operational runbook, and every coding agent immediately knows how to ask a Rails app a safe question about its data.

Meeting the moment

Frameworks fade when they treat their boundaries like a purity test—insisting that every problem must be solved in one language, or ignoring how software is actually being built today.

Rails has lasted, and continues to lead, because its core competency has never just been Ruby syntax. Its core competency is taste and integration: looking at the messy, pragmatic things developers actually need to ship—from migrations, background jobs, and zero-downtime Kamal deploys to painless native Rust extensions and agent-safe database introspection—and pulling them together into defaults that feel obvious in hindsight.

We are going to keep replacing hot compute loops with Rust where it makes DEV faster. And we are going to keep doing it happily inside a Rails monolith that keeps rising to meet the moment.

Long live Rails and Happy Coding ❤️

Top comments (0)