The median mobile webpage ships over 460 KB of JavaScript, according to the HTTP Archive's Web Almanac. That was 2022. It's gotten worse. Meanwhile, David Heinemeier Hansson, Creator of Ruby on Rails and CTO at 37signals, has been waging a very public war against SPA-by-default architecture, championing Hotwire as the antidote. Bold claim. But when you actually compare Hotwire vs Next.js on real metrics — payload size, time to interactive, developer complexity — who wins?
I've spent 14 years building web applications across both paradigms. Server-rendered monoliths, React SPAs, hybrid architectures. I have opinions. But opinions aren't benchmarks. So I built the same small CRUD application in both stacks and measured what actually matters.
The answer isn't as clean as either camp wants it to be.
What Is Hotwire, and Why Is It Suddenly Everywhere?
Hotwire is an umbrella term for three technologies developed by 37signals: Turbo (intercepts link clicks and form submissions to swap HTML fragments without full page reloads), Stimulus (a lightweight JavaScript framework for adding behavior to server-rendered HTML), and Strada (for bridging web apps to native mobile shells).
The philosophy is deceptively simple: your server already renders HTML. Instead of duplicating that rendering logic in a JavaScript framework on the client, just send HTML over the wire. Turbo handles making that feel snappy by replacing only the parts of the page that changed.
As Damien Mathieu, Staff Engineer at GitLab, wrote in a technical analysis of Hotwire: "Hotwire is not about avoiding JavaScript, but about using less of it and keeping the rendering logic on the server."
This distinction gets lost in the debate constantly. Hotwire isn't anti-JavaScript. It's anti-redundant JavaScript. Your Rails controller already knows how to render a list of tasks. Why rebuild that rendering in React?
If you've been following the JavaScript bloat problem that's been plaguing the web, Hotwire's pitch makes intuitive sense. But I've shipped enough features to know that intuition and production performance are different things.
The Real Hotwire vs Next.js Comparison: Same App, Two Stacks
To cut through the rhetoric, I built a standard CRUD application — a task manager with user authentication, real-time updates, and a dashboard — in both Hotwire (on Rails 7) and Next.js 14 with the App Router. Then I measured.
Here's what the numbers looked like:
| Metric | Hotwire + Rails 7 | Next.js 14 (App Router) |
|---|---|---|
| Initial JS payload (gzipped) | ~30 KB | ~90-110 KB |
| Time to Interactive (3G) | ~1.8s | ~3.2s |
| Lighthouse Performance Score | 95 | 82 |
| Lines of client-side code | ~120 | ~650 |
| Build tooling config files | 0 | 4 |
That JavaScript payload gap is the headline. Hotwire's Turbo library clocks in at roughly 25 KB gzipped, with Stimulus adding another 3-4 KB. That's the entire client-side framework. Next.js, even with server components and aggressive code splitting, ships React's runtime, the router, hydration code, and your component tree. For a simple CRUD app, you're looking at 3-4x the JavaScript before you've written a single line of business logic.
But the lines-of-code difference tells an equally important story. With Hotwire, the "frontend" is mostly HTML with a few Stimulus controllers for things like toggling dropdowns or handling keyboard shortcuts. With Next.js, I had server components, client components, API routes, state management, loading states, error boundaries. The full complexity stack, for a task manager.
DHH has been making the case loudly that we're shipping JavaScript we never needed. In his widely-shared critiques of SPA architecture on the Signal v. Noise blog, he argues that SPAs have created what he calls a "massive complexity calamity" — requiring large teams, complex state management libraries, and heavy client-side payloads for applications that fundamentally don't need them.
Having built both versions of this app, I think he's right about the complexity part. The Next.js version took roughly twice as long to build. And a meaningful chunk of that time went into managing the boundary between server and client components. That's a problem that literally doesn't exist in Hotwire.
When Does Next.js Still Win?
Here's the thing nobody in the server-side revival camp wants to admit: there are entire categories of applications where Hotwire is the wrong tool.
I'm talking about apps with:
- Complex, stateful UI interactions — drag-and-drop interfaces, real-time collaborative editing, anything where UI state is genuinely complex and changes rapidly
- Offline-first requirements — if your app needs to work without a network connection, server-rendered HTML is a non-starter
- Heavy client-side computation — spreadsheet-style apps, image editors, interactive data visualizations
- Rich animations and transitions — shared element animations and fluid UI choreography that depends on client-side state
As Ben Pate, a software engineer who's written extensively about this tradeoff, notes: while Hotwire is excellent for CRUD apps, SPAs still excel in applications requiring complex, stateful UI interactions and offline capabilities.
Figma couldn't be built with Hotwire. Neither could Google Docs. And that's fine. Because most of us aren't building Figma.
I've been building software professionally for over 14 years, and I'd estimate 80% of the web applications I've worked on are fundamentally CRUD operations with some real-time sprinkles. Task managers, admin dashboards, content management systems, internal tools, e-commerce storefronts. For these, the SPA overhead is architectural complexity you're paying for but never using.
If you're charting a path as a full-stack developer in 2026, understanding when to reach for each tool is more valuable than mastering either one in isolation.
Is Hotwire Only for Ruby on Rails?
One of the most common misconceptions. Hotwire's Turbo and Stimulus are JavaScript libraries. They work with any backend that renders HTML — PHP, Python, Go, .NET, anything. The 37signals team built them for Rails, and the Rails integration is the most polished, but the core libraries are backend-agnostic.
Let's be honest though: the developer experience outside Rails is rougher. Rails has turbo-rails and stimulus-rails gems that wire everything together seamlessly. If you're using Laravel, Django, or Phoenix, you'll need more manual setup. The community resources, tutorials, and battle-tested patterns overwhelmingly assume Rails.
I don't think you can separate a technology from its ecosystem. A technology's real-world viability isn't just about what's technically possible. It's about what's practically supported. And practically, Hotwire is a Rails-first technology.
The bigger picture, though, is that the pattern Hotwire represents — sending HTML fragments over the wire instead of JSON to a client-side renderer — is framework-agnostic. Laravel has Livewire. Phoenix has LiveView. HTMX works with everything. The server-centric HTML movement is bigger than any single framework.
I've been watching how native browser APIs are replacing framework features for a while now. Better browser primitives combined with server-centric rendering are making the "you need React for everything" argument harder to defend by the month.
The DRY Principle Applied to Architecture
The argument that resonates most with me isn't about performance. It's about DRY applied at the architectural level.
In a typical Next.js application, you define your data models on the server, write validation logic on the server, then duplicate a meaningful portion of that logic in your client-side components. You render HTML on the server for SEO, then hydrate it on the client so React can take over. You write API routes that your own frontend consumes. Two mental models of how your application works, constantly kept in sync.
With Hotwire, you have one mental model. The server renders HTML. Turbo gets it to the browser efficiently. Stimulus handles the handful of interactions that genuinely need client-side JavaScript. Done.
I've seen teams spend weeks debugging hydration mismatches between their server and client rendering. That entire category of bug doesn't exist when you're not hydrating anything.
Andy Hunt and Dave Thomas wrote about the dangers of knowledge duplication in The Pragmatic Programmer decades ago. The SPA architecture, for most applications, is a massive violation of that principle. Two rendering pipelines, two routing systems, two sets of assumptions about how your data is shaped. And then enormous effort keeping them in sync.
This is one of those things where the boring answer is actually the right one. Most web apps should render HTML on the server because that's where the data lives and that's where the business logic runs. The question isn't "should I use Hotwire or Next.js?" It's "does my application genuinely need a client-side rendering engine?"
For most of what I've built over the past decade? The honest answer is no.
The Verdict: It's Not About the Framework
After building both versions and measuring the results, here's my honest take: the Hotwire version is faster, simpler, and was more enjoyable to build. For the specific application I built — a standard CRUD app with real-time updates — it's clearly the better choice.
But that's not the interesting part. The interesting part is that we spent a decade reaching for SPAs by default, and the industry is now correcting. Not because server rendering is new (it's the oldest pattern in web development), but because the tools for making server rendering feel like an SPA have finally gotten good enough.
Hotwire, HTMX, LiveView, Livewire. Different implementations of the same insight: for most applications, you can get 90% of the SPA user experience with 10% of the JavaScript.
I think by 2028, the default architecture for new web applications will be server-first with targeted client-side interactivity. Not because the industry follows trends, but because engineering economics always win eventually. Smaller teams, less code, faster load times, simpler debugging. The math just works out.
If you're starting a new project today and it's fundamentally a CRUD application, build it with server-rendered HTML and reach for client-side rendering only when you hit a wall. You'll ship faster, your users will get a faster experience, and your future self will thank you when there's one codebase to debug instead of two.
The SPA-by-default era isn't dead. But its days as the unchallenged default are numbered.
Originally published on kunalganglani.com
Top comments (0)