Contents
An article on server-rendered HTML pushed down a socket hit the Hacker News front page again this week. I read the thread and mostly smiled. I have been building software this way for years, and it was already getting called the future of web software when A List Apart ran a whole piece on it in 2021.
None of that is a knock on the people finding it now. It is a good pattern, and good patterns get found more than once. But the conversation almost always stops at the part that demos well and skips the part that decides whether the thing holds up once real people are using it. So here is the version I would give a client over coffee, if they asked whether their next internal tool should be built this way. Short answer, usually yes. The longer answer is a bit more complicated.
What WebSockets actually is
Strip the branding off and it's straightforward. Instead of shipping a pile of JavaScript that fetches JSON and rebuilds the interface in the browser, you keep the rendering on the server. The server produces the finished HTML, and when something changes it sends a small piece of that HTML to the browser, which drops it into place. The Rails crowd calls their version Hotwire, and their one-line pitch is the clearest I have seen: send HTML over the wire instead of JSON.
The upside is real. You write one language for the screen instead of two. You stop keeping a second copy of your business logic alive in the browser. A form that validates, a table that filters, a dashboard tile that changes when a job finishes: all of it lives in one place, in the code you already trust. For most business software that is the entire job. Internal tools are mostly forms and tables and the odd live number, and paying for a full client-side app to run them is a tax you feel for years. I have made the case before that a lot of businesses need a web page, not an app, and this is a big reason that is a real choice instead of a cop-out.
Push it real good 🎶
In my stack, "HTML over WebSockets" is really two pieces doing two jobs.
Livewire is the part that renders HTML on the server and swaps it into the page, and it is the tool I lean on inside the TALL stack. Most of the time it does that over plain web requests, not a socket at all. Each request carries a small JSON snapshot of the component's state; the server rebuilds the component from that snapshot, runs your method, and sends back fresh HTML. There is no long-running process on the server holding your screen in memory between clicks. It is stateless by design, and Caleb Porzio, who wrote Livewire, walks through exactly how that works if you want the guts of it.
The actual WebSocket shows up when I want the server to push something to the browser on its own, with no click behind it. A new order lands. A number ticks up. Someone else on the team edits a record you happen to be looking at. For that I add Laravel Echo and a WebSocket server, and on Laravel that is Reverb, the first-party one that speaks the Pusher protocol and scales out across Redis. Livewire listens for those broadcasts and re-renders the affected piece. That becomes the "live" in "live dashboard."
The part nobody mentions
That second piece is where the sharp edge lives. The demo always runs on a perfect connection. Your users do not. They are on hotel wifi, on a phone walking into an elevator, on a laptop that just woke up. The socket drops. It always drops. The only question that matters is what happens when it comes back.
Here is what got me the first time, somewhere around two in the morning. A dashboard that had updated cleanly all day would, every so often, come back from a dropped connection showing yesterday's number like it was current. Nothing threw an error. The code was right. What actually happened was simpler and meaner: while that socket was down, the server broadcast an update, and the browser was not there to hear it. The Pusher protocol does not hold your messages and hand them over when you reconnect. Miss one and it is gone. So the page sat there, confident and wrong, until the next full request happened to refresh it.
Latency gets all the attention because it is easy to measure and fun to argue about. Reconnection is the one that turns into a support ticket you cannot reproduce. If you take one thing from this, take that. When you weigh this approach, do not ask how fast it updates. Ask what it does when the connection drops and comes back. The fix is not exotic. You reconcile on reconnect instead of trusting you caught every message. But you have to decide to do it, and nobody tells you that going in.
When to reach for it, and when not
I use this as the default for server-driven business software. Admin panels, internal dashboards, client portals, the operational stuff that actually runs a company. Screens that are mostly reading and writing your own data with some live updates layered on. It ships fast and it stays maintainable.
I reach for a heavier client-side framework when the interface itself is the product. A drawing canvas, a spreadsheet, a collaborative editor, anything that has to keep working with no connection at all. Those things live on rich client state, and fighting that with server-rendered fragments is a bad time.
There is also a quieter reason to slow down before choosing, and it has nothing to do with the tech. A live connection changes how an app feels, and faster is not automatically better. I have written about why a faster website can feel worse than a slower one, and real-time updates are where that shows up most. A number that moves under someone's cursor while they are reading it is not a feature. It is a distraction you built on purpose.
The pattern is genuinely good. It is also years of accumulated lessons that keep getting reset every time a new crowd finds it. If you are weighing it for something you actually have to run and support, the reconnection question is the one worth sitting with, and it is exactly the kind of decision we work through with clients before writing a line of custom software. Get that part right and the rest of it really is as pleasant as the demos make it look.