Page loadedSkip to main content

Deep Dive into Hydration: A Necessary Evil?

00:02:29:86

The problem

Server-side rendering solves the blank-page problem. The server sends fully rendered HTML and the user sees content almost immediately. But there is a catch: that content is a facade. Buttons do not respond, forms do not submit, nothing interactive works yet.

The page looks loaded but is completely unresponsive. Users click, nothing happens, and they click again. This gap between First Contentful Paint (FCP) and Time to Interactive (TTI) is what some call the uncanny valley of non-interactivity.

What hydration actually does

Hydration is the process of attaching JavaScript event listeners and state management to server-rendered HTML. The browser has to:

  1. Download the JavaScript bundle
  2. Parse and execute it
  3. Recreate the component tree in memory
  4. Walk the existing DOM and attach event handlers
  5. Reconcile any differences between server and client output

Think of it like receiving a fully assembled Lego model, but before you can press any of the buttons you have to read through the entire instruction manual and mentally verify every piece is in the right place.

The work is redundant by nature. The server already did the rendering. The client does it again, not to produce new output, but to understand the existing output well enough to take over.

Why it is expensive

On a modern laptop with a fast connection, hydration finishes in milliseconds and nobody notices. On a mid-range phone on a 3G network, it can take seconds. During that time:

  • The main thread is blocked
  • The page appears interactive but is not
  • User interactions are silently dropped or queued

The larger the component tree, the longer hydration takes. And the JavaScript bundle size scales with the component tree, so download time compounds the problem.

The solutions emerging

Islands Architecture

Astro pioneered this approach. Instead of hydrating the entire page, you mark specific components as interactive "islands." Everything else stays as pure HTML with zero JavaScript.

A blog post with one interactive chart only hydrates the chart component. The rest of the page, the text, headings, images, never loads a single byte of JavaScript.

Progressive Hydration

Rather than hydrating everything at once, prioritize what is in the viewport. Components below the fold get hydrated lazily, either on scroll or on interaction.

React 18's Suspense and selective hydration move in this direction, hydrating parts of the tree independently based on user interaction.

Resumability

This is the most radical approach, pioneered by Qwik. Instead of re-executing the application on the client, Qwik serializes the application state directly into the HTML. The client does not replay the rendering. It simply resumes from where the server stopped.

The result is near-instant interactivity regardless of application size. No bundle to download upfront, no component tree to rebuild. Event handlers are loaded on demand when the user actually interacts with something.

Where things are heading

Traditional hydration is a bridge technology. It exists because the client needs to understand what the server produced, and the only way current frameworks know how to do that is to redo the work.

The frameworks converging on islands, streaming, and resumability are all trying to eliminate that redundancy. The end goal is the same: get to interactive without making the browser repeat what the server already did.

Hydration solved a real problem. It is just not the final answer.