Tags: web-dev concept

Hydration

Date: 2026-08-16


Making server-rendered markup interactive by re-running the same component code in the browser. It’s why a server-rendered page can appear instantly and then ignore your clicks for two seconds — the pixels arrived early and the JavaScript that makes them work did not.


What it is

Hydration is the process where a client-side framework walks server-rendered HTML, attaches event listeners, and rebuilds its internal state so the markup becomes interactive.

SERVER                          BROWSER

render components  ──HTML──▶    paint immediately       ← looks ready
                                      │
                   ──JS────▶    download bundle
                                      │
                                parse + execute
                                      │
                                re-run the same components
                                      │
                                attach listeners
                                      ▼
                                actually interactive     ← is ready

The gap between “looks ready” and “is ready” is the uncanny valley of server rendering: a page that renders in 800ms and responds at 3.2 seconds is arguably worse than one that renders at 2s, because it invites interaction it can’t service.

Why it costs so much

The work is done twice. The server renders components to produce HTML; the browser re-runs the same components to reproduce the tree it needs to track. That means shipping:

  • The component code for everything on the page
  • The framework runtime
  • The data used to render it, serialised into the page — usually a large JSON blob

That serialised data is the part people miss. A server-rendered page often contains its entire dataset inline, which then has to be parsed synchronously on the main thread — see JavaScript Execution Cost and Long Tasks and Blocking.

In plain terms: the server sends you the finished page, then sends you everything needed to build the finished page again, so the browser can take ownership of it.

What it does to the metrics

Hydration mismatch

When the browser’s render doesn’t match the server’s markup, the framework discards the server HTML and re-renders from scratch — losing the benefit entirely and often causing a visible flash.

Common causes:

// different on server and client — mismatch
<span>{new Date().toLocaleTimeString()}</span>
<span>{Math.random()}</span>
<span>{window.innerWidth > 768 ? 'desktop' : 'mobile'}</span>

Anything time-dependent, random, or browser-only. The fixes: render a stable placeholder and update after mount, or mark the subtree as client-only. Frameworks warn about mismatches in development and mostly stay silent in production, so check the console in development builds — a mismatch found late is a whole class of unexplained layout shift.

Reducing it

In order of effect:

  • Ship less interactivity. Most of a category page is static content that never needs hydrating
  • Islands Architecture — hydrate only the interactive components, leaving the rest as inert HTML
  • Server Components — components that render on the server and never ship to the client at all
  • Progressive or selective hydration — prioritise what’s visible or what the user interacts with first, rather than hydrating top to bottom
  • Lazy-hydrate below the fold on intersection
  • Reduce the serialised payload. Don’t inline data the client can fetch, and don’t inline data the client never uses
  • Code Splitting so hydration only loads what this route needs

The honest framing

Hydration is the cost of wanting one component model to run in two places. It buys real things — shared code, a single mental model, server rendering without rewriting the UI — and it charges for them in main-thread time on the user’s device.

The architectures gaining ground all attack the same premise: that the whole page needs to be interactive. On a retail site it emphatically doesn’t, and that observation is what Islands Architecture and server components are built on.