HTMX Is Overkill (Until Your React Bundle Explodes)

Why I stopped reaching for SPA frameworks first and started shipping HTML-over-the-wire for most projects

Most teams over-engineer their frontend stack from day one. HTMX reminds us that server-rendered HTML with strategic interactivity beats a 500KB React bundle for 80% of web apps—and I've got the production stories to prove it.

Jay McBride

Jay McBride

Software Engineer

7 min read
Support my work on Buy Me a Coffee

Introduction: The Pattern That Keeps Breaking

I’ve watched three different startups burn months building a React-powered admin panel that gets used by exactly four people. Same story every time: the team picked a SPA framework on day one because it felt “modern,” shipped a 2MB initial bundle, fought hydration bugs for weeks, and ended up with a system that takes five seconds to show a data table.

You know what would’ve worked? Server-rendered HTML with a few strategic AJAX swaps.

HTMX isn’t revolutionary because it does something new. It’s revolutionary because it reminds us that most web apps don’t need a JSON API, client-side routing, or a state management library. They need fast page loads, simple interactions, and HTML that arrives ready to display.

This article is for teams who’ve shipped a SPA, felt the pain, and wondered if there’s a simpler path. If you’re still convinced every project needs React, come back after your next performance audit.

Enjoying this? 👉 Tip a coffee and keep posts coming

Here’s what I’ve learned from building production apps with HTMX—and what breaks when you push it too far.


The Core Judgment: Default to HTML Over the Wire

Most interactive features can be built with three primitives:

  1. Send an HTTP request
  2. Get HTML back
  3. Swap it into the DOM

That’s it. No build step, no state synchronization, no JSON parsing. HTMX gives you declarative attributes to do exactly that—hx-get, hx-post, hx-target, hx-swap—and gets out of your way.

The real question isn’t “Can HTMX do this?” It’s “Why are we sending 400KB of JavaScript to render a form?”

I default to server-rendered HTML with HTMX for internal tools, marketing sites, and any CRUD-heavy application where the user isn’t doing real-time collaboration. The vast majority of web apps fall into this category.

Teams reach for SPAs by habit, not necessity. HTMX forces you to justify the complexity.


How This Works in the Real World

When you click a button with hx-post="/update", HTMX sends a POST request. The server responds with an HTML fragment—not JSON—and HTMX swaps it into the target element you specified.

The browser doesn’t reload. The URL can update. CSS transitions apply. To the user, it feels like a SPA.

But here’s what doesn’t happen:

  • No client-side routing logic
  • No JSON serialization/deserialization
  • No virtual DOM diffing
  • No hydration mismatches

Your backend template engine (Django, Rails, Laravel, Go templates) becomes your “component library.” You already know how to write it.

What Actually Breaks

HTMX falls apart when:

  • You need offline support or heavy client-side caching
  • Your UI requires complex, stateful interactions (think Figma or spreadsheets)
  • You’re building a public API that non-browser clients will consume

In those cases, a JSON API and a proper frontend framework make sense. For everything else, you’re over-engineering.


A Real Example: Admin Panel Rebuild

I inherited a React-based admin panel at a mid-sized SaaS. It had:

  • 18 different npm packages for state management, routing, and form validation
  • A 1.2MB production bundle (gzipped: 350KB)
  • Average Time to Interactive: 4.2 seconds on a mid-tier connection
  • Constant bugs from stale client-side state

We rewrapped the backend APIs to return HTML partials instead of JSON, dropped in HTMX, and removed React entirely.

Results after two weeks:

  • Bundle size: 14KB (just HTMX)
  • TTI: 800ms
  • Zero hydration errors
  • Forms validated server-side (the only place validation actually matters)

The team could now build features in the templating language they already used for marketing pages. No context-switching. No “frontend” vs “backend” silos.

What surprised me: the speed of iteration increased more than I expected. When your entire stack is server-rendered, you can add a new page, a new form, or a new table in minutes, not hours.


Common Mistakes I Keep Seeing

Treating HTMX Like a Framework

HTMX is 14KB of JavaScript that enhances HTML. It’s not a framework. Don’t try to build “HTMX apps”—build server-rendered apps that use HTMX for interactions.

If you find yourself writing custom JavaScript to manage state or coordinate between HTMX elements, stop. You’re rebuilding React badly.

Ignoring Progressive Enhancement

HTMX works best when your app degrades gracefully. Every hx-post should also work as a plain form submission. Every hx-get should work as a regular link.

This isn’t dogma—it’s resilience. If your JavaScript fails to load (it will, eventually), your app should still function.

Sending Huge HTML Payloads

Just because you’re sending HTML doesn’t mean you should send the entire page on every swap. Target small fragments. If your response is 50KB of HTML, you’re doing it wrong.

Use partials, components, or template inheritance to send only what changed.


Tradeoffs and When This Breaks Down

You’re Tied to Server Latency

Every interaction requires a server round-trip. If your backend is slow or your users are on high-latency connections, HTMX will feel sluggish.

Mitigation: cache aggressively, use CDNs, optimize your backend queries. These are good practices anyway.

Complex Client-Side Logic Gets Messy

If you need autocomplete with fuzzy search, drag-and-drop reordering, or real-time validation as the user types, HTMX alone won’t cut it.

You can add Alpine.js or vanilla JavaScript for isolated interactivity, but at a certain complexity threshold, React or Vue becomes simpler.

SEO Isn’t Automatic

Server-rendered HTML is inherently SEO-friendly, but if you’re dynamically loading content on page load (e.g., hx-trigger="load"), crawlers might miss it.

Test with Google Search Console. Render initial content server-side, use HTMX for updates after load.


Best Practices I Actually Follow

  • Start with plain HTML forms. Add hx-post only when you need async behavior.
  • Use HTTP response codes correctly. Return 422 for validation errors, 303 for redirects, 200 for swaps.
  • Leverage hx-target and hx-swap for surgical updates. Replace a row, append to a list, prepend to a feed—don’t reload the whole section.
  • Return toast notifications via headers. Use HX-Trigger to fire client-side events like “show success message.”
  • Keep HTMX requests idempotent. If the same request runs twice (network retry, user double-click), it shouldn’t break your data.

Conclusion: Simplicity Wins When You Ship

HTMX isn’t a magic bullet. It’s a reminder that the web’s original architecture—send a request, get HTML, display it—still works for most applications.

If your product is a CRUD app, an internal tool, or a content-driven site, you don’t need a SPA. You need fast page loads, simple deployments, and a stack your whole team can understand.

Start with server-rendered HTML. Reach for HTMX when you need interactivity. Reach for React when HTMX breaks down.

And for the love of everything holy, stop shipping 500KB bundles to render a login form.


Frequently Asked Questions (FAQs)

Does HTMX replace React?

Not for complex, stateful UIs. But for most web apps—especially internal tools and CRUD-heavy systems—it eliminates the need for a SPA framework entirely.

Can I use HTMX with a REST API?

Technically, yes, but you’re missing the point. HTMX shines when your backend returns HTML, not JSON. If you already have a REST API, stick with a traditional SPA framework.

What about accessibility?

HTMX respects semantic HTML. If your backend templates are accessible, your HTMX interactions will be too. Use ARIA live regions for dynamic updates, just like you would in any web app.

How do I handle authentication?

The same way you do with server-rendered apps. Use session cookies, CSRF tokens, and HTTP-only flags. HTMX sends the same headers and cookies as a normal browser request.

What if my team only knows React?

This is a learning curve question, not a technical one. HTMX requires understanding HTTP, HTML templates, and server-side rendering. If your team is backend-heavy, they’ll pick it up in days. If they’re frontend-heavy, it might feel like a step backward—until they ship their first feature in 20 minutes.


Your turn: What’s the last feature you built that shipped 200KB+ of JavaScript when 14KB of HTMX would’ve done the job?

Enjoying this? 👉 Tip a coffee and keep posts coming

Found this helpful?

Share it with your network

Jay McBride

Written by Jay McBride

Software engineer with 10+ years building production systems and mentoring developers. I write about the tradeoffs nobody mentions, the decisions that break at scale, and what actually matters when you ship. If you've already seen the AI summaries, you're in the right place.

Based on 10+ years building production systems and mentoring developers.

Support my work on Buy Me a Coffee

Recommended for You

10 min read

Why I Stopped Defaulting to React for Every Project

After years of watching teams drown in JavaScript complexity, I'm back to building most apps with server-rendered frameworks—and shipping faster than ever.

Read Article
8 min read

Angular Doesn't Suck: Debunking Myths and Proving Its Worth

Why Modern Angular Is Perfect for Enterprise and Large-Scale Applications

Read Article