HTMX in Production: What I Kept, What I Removed

go dev.to

HTMX articles come in two camps: "the end of SPAs" and "a toy". Production reports are the rare thing. Here is one.

TL;DR: my prospecting cockpit runs in production on HTMX, Go, html/template, Postgres and Redis. What held up: one endpoint per fragment, templates split by component, Redis as an optional cache. What I removed: the SSE push, which froze the page on HTTP/1.1. And htmx 4.0 just shipped, which says something about the approach's maturity.

This article is for backend developers who want a real interface without adopting a full frontend framework.

The setup

The cockpit is my freelance prospecting tool. Conversation tracking, monitoring, lead analysis. I use it every day, and it runs in production.

The stack is short. Go with net/http. html/template templates. HTMX in the browser. Postgres for data, Redis as a cache.

HTMX is a small JavaScript library. It reads HTML attributes and swaps parts of the page with HTML returned by the server. No frontend build, no npm, no client-side state.

The bet: all the logic stays in Go, the browser only displays.

The rule that emerged: one endpoint, one fragment

At first, my templates were monoliths. The base template weighed 102 KB. Two pages were above 70 KB each.

It works, but nobody dares touch it anymore. The refactor imposed a simple rule: an HTMX endpoint returns one fragment, and every fragment lives in its own file.

A dedicated fragments/ folder. Pages split by component. The base CSS went from 1,256 lines to 192, with a per-page file included automatically.

html/template holds up very well, on one condition: split it the way you would split your code.

What I removed: the SSE push

I had built real-time. A Redis pub/sub channel, an events endpoint, a toast in the page when an analysis finished. Elegant on paper.

In practice, the page showed a never-ending loading state. An SSE stream is an HTTP request that never finishes. On HTTP/1.1, that permanent stream occupies one of the browser's few connection slots to your origin.

I covered this family of traps in my article on Go timeouts and SSE. This time it was my own app.

The real question was not "how do I fix it". It was "who needs this real-time". Honest answer: nobody. An HTMX refresh on click gives the same information.

The SSE left in one commit. Real-time is a permanent cost, not a gift. Pay it only when the need exists.

What I kept on the server side

Redis stayed, but as a cache only. Matching embeddings are cached with a TTL. Same for the most re-read account data.

The important part: everything is optional. The Redis adapter is nil-safe, and the cockpit starts and works without Redis, just slower. An optional dependency is one less outage.

The job queue stayed in Postgres. Durable, transactional, already there. The pair, Postgres for state and Redis for speed, covers everything an app like this needs.

htmx 4.0 just shipped, and it matters

On 28 August 2026, htmx 4.0 was released. The engine moves from XMLHttpRequest to fetch, the browser's modern request API. The project skipped version 3, as promised.

What I take away is not the technical novelty. It is the signal: the hypermedia approach is maintained, funded, and built to last.

I have not migrated yet. My usage is deliberately simple, core attributes and fragments. The migration will wait for a quiet slot, and that is exactly what I want from a frontend dependency.

Who I recommend this stack to, and who not

Go for it if you are a small backend team with an internal tool, a back office or a CRUD-heavy app. The payoff is huge: one codebase, one deployment, zero frontend pipeline.

Think twice if your product lives on rich client-side interactions. Collaborative editing, offline, complex animations: there, a frontend framework earns its keep.

And if you already have a frontend team fluent in its framework, HTMX is not an upgrade. It is a different trade-off.

The checklist if you try HTMX

The rules I would apply from day one, in order.

  • [ ] An HTMX endpoint returns one fragment, and every fragment lives in its own file
  • [ ] Split your templates by component before they reach 100 KB
  • [ ] Extract per-page CSS, loaded automatically by convention
  • [ ] Do not add real-time without a real need: a refresh on click is often enough
  • [ ] If you do SSE, first read how it behaves on HTTP/1.1
  • [ ] Make dependencies optional: the app must start without the cache
  • [ ] Keep durable state in Postgres and cache in Redis, not the other way around

What to remember

HTMX in production is mostly template discipline and deliberate server-side choices. The library itself fades into the background.

My verdict after months of daily use: I keep the stack, I removed the excess, and htmx 4 reassures me.

Want a solid interface without a frontend factory, or a second opinion on your Go web stack? Let's talk.


Sources: htmx 4.0 announcement (28 August 2026) · htmx.org · Go html/template (pkg.go.dev) · MDN, Server-sent events

Source: dev.to

arrow_back Back to Tutorials