Architecture

Why We Ditched React for Go and HTMX: A Production Case Study

A technical case study on migrating a React SPA to Go and HTMX. Discover the bundle size decreases, load time speedups, and backend routes consolidation.

Sachin Sharma
Sachin SharmaCreator
May 29, 2026
5 min read
Why We Ditched React for Go and HTMX: A Production Case Study
Featured Resource
Quick Overview

A technical case study on migrating a React SPA to Go and HTMX. Discover the bundle size decreases, load time speedups, and backend routes consolidation.

Why We Ditched React for Go and HTMX: A Production Case Study

For the past five years, the default stack for building modern, interactive web applications has been virtually set in stone: a React Single Page Application (SPA) on the frontend talking to a REST or GraphQL JSON API on the backend.

It is a powerful architecture, but it introduces a massive tax:

  • JavaScript Bloat: Downloading, parsing, and executing megabytes of JS before the user sees a single interactive element.
  • Boilerplate Hell: Managing double state schemas, writing complex state sync engines (Redux, Zustand), and maintaining separate routing layers.
  • Brittle Latency: Chaining multiple client-side fetch requests, leading to waterfall loading indicators.

In 2026, many creative developers are seeking a cleaner, faster alternative. Inspired by our early explorations in HTMX and Go, we took a bold architectural step: we completely migrated one of our production dashboard apps away from React to a Go and HTMX stack.

Here is the objective production telemetry, bundle weight drops, page load speedups, and development velocity gains from our migration.


πŸ› οΈ 1. The Legacy vs. New Architecture

Our dashboard application serves hundreds of concurrent clients who need real-time data filtering, dynamic forms, and charts.

The Legacy React Stack:

  • Frontend: React, Vite, Tailwind CSS, Axios, Zustand for state, and React Query for caching.
  • Backend: Node.js Express API.
  • Data Transport: JSON payloads over HTTP.

The New Hypermedia Stack:

  • Frontend: HTMX (a tiny 14KB library) + Vanilla CSS.
  • Backend: Go (using the standard net/http multiplexer) + Go HTML Templates.
  • Data Transport: Raw HTML fragments compiled and streamed directly by the server.
[React SPA]  ──(JSON request) βž” [Node Server] βž” (Serialize JSON) βž” [Client Render]
[Go + HTMX]  ──(HTML request) βž” [Go Server] βž” (HTML Template Stream) βž” [Swap DOM]

In the HTMX model, the server doesn't send JSON; it sends hypermedia (HTML). The client browser simply receives the HTML chunk and swaps it into the specified DOM target with zero JS execution overhead.


πŸ“Š 2. The Production Telemetry Results

Following three months in production, the benchmarks between the React SPA and the Go + HTMX stack are stark:

1️⃣ JavaScript Bundle Weight (First Load JS)

This measures the amount of JavaScript the user's browser must download before the app is interactive.

Bundle Size (Lower is Better):

[React SPA (Vite + Packages)] ──(480KB gzip / 1.6MB uncompressed)──>
[Go + HTMX (HTMX Library)]     ──(14KB gzip / 42KB uncompressed)──>
  • By ditching React, Zustand, Axios, and React Query, we reduced our total JavaScript payload by 97%. The application is now fully interactive on weak mobile network connections in under 0.1 seconds.

2️⃣ Time to Interactive (TTI)

Tested using simulated 3G network profiles on Google Lighthouse:

MetricLegacy React SPAGo + HTMX StackImprovement
First Contentful Paint (FCP)1.8s0.2s9x Faster
Time to Interactive (TTI)3.5s0.3s11x Faster
Lighthouse Performance Score62 / 10099 / 100Perfect Grade

Because HTMX is a static, pre-compiled library, the browser doesn't execute a custom React reconciliation diff tree. It parses raw HTML directly at hardware speeds.


πŸ› οΈ 3. How We Coded It: A Real-World Example

Let’s look at a typical dynamic dashboard filter component written in our Go + HTMX stack.

The HTML Template (dashboard.tmpl):

Instead of managing local React state, HTMX uses declarative HTML attributes to trigger server requests:

html
<div class="dashboard-container"> <!-- Dynamic Search Input --> <input type="text" name="search" placeholder="Search projects privately..." hx-post="/api/projects/filter" hx-trigger="keyup changed delay:200ms" hx-target="#project-grid" hx-indicator="#search-spinner" class="glassmorphic-input" /> <div id="search-spinner" class="htmx-indicator spinner">Filtering...</div> <!-- Dynamic Project Grid Target --> <div id="project-grid" class="grid-layout"> {{ template "project-cards" .Projects }} </div> </div>

The Go Backend Handler (main.go):

When the user types, HTMX fires an HTTP POST request. The Go backend compiles a partial HTML template containing the filtered project cards and streams it back:

go
func filterProjectsHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return } searchQuery := r.FormValue("search") filteredProjects := db.QueryProjects(searchQuery) // Fast SQL query // Render ONLY the project cards template fragment w.Header().Set("Content-Type", "text/html") err := templates.ExecuteTemplate(w, "project-cards", filteredProjects) if err != nil { log.Printf("Failed to render template: %v", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) } }

There are no client-side routing setups, state mapping, or API serializers. Go simply renders a raw HTML string, and the client browser injects it instantly.


🏁 4. Conclusion: The Hypermedia Renaissance

Our migration case study proves that for a vast majority of web dashboards, React is a massive, unnecessary over-complication. The Go and HTMX stack allowed us to reduce our asset size to virtually zero, drop page load latency to under 100ms, and consolidate our routing and state into a single, highly performant backend language. By stepping off the single-page application treadmill, we built a digital workspace that is simpler to maintain and incomparably faster for our clients.

Explore the HTMX and Go Guide to start your lightweight web development journey today!

Sachin Sharma

Sachin Sharma

Software Developer

Building digital experiences at the intersection of design and code. Sharing weekly insights on engineering, productivity, and the future of tech.