awesome-everything RU
↑ Back to the climb

Browser & Frontend Runtime

Hydration cost: selective, progressive, islands, resumability

Crux Why full hydration is expensive, how selective hydration and islands reduce what needs to hydrate, and how resumability eliminates the re-render entirely.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at middle altitude — in the sky
◷ 16 min

A news article page: 2,000 words of text, one comment box, a like button. Classic full-page hydration runs the framework across all 2,000 words of text — making text that has no interactivity “interactive.” The bundle is larger than it needs to be and the hydration long task blocks the main thread, spiking INP. There are better options.

Why hydration is expensive. Hydration roughly doubles render work — the tree is rendered once on the server and effectively rendered again on the client. But it is worse than a simple doubling, because the client render runs on the user’s device, which may be a mid-range phone an order of magnitude slower than your server. And it is all main-thread JavaScript: downloading the bundle, parsing and compiling it (V8 work), then running the component tree and attaching handlers. On a large app this is hundreds of milliseconds to seconds of main-thread time during which the page looks done but is not. This whole window is the “uncanny valley” of SSR — the page is painted and looks interactive, the user tries to interact, and the input is dropped or queued behind the hydration long task, spiking INP.

Full vs selective hydration. Classic React hydration is full and eager: the whole app hydrates in one pass before anything is interactive, and it is blocking. React 18 introduced selective hydration: with Suspense boundaries, parts of the tree hydrate independently, and React prioritises hydrating whatever the user just interacted with. If the user clicks a not-yet-hydrated section, React hydrates that section first, ahead of the rest. It also makes hydration interruptible — it can yield to input mid-hydration. Selective hydration does not remove the total cost; it reorders it so the cost lands where the user is not looking and the part they touched comes alive first.

Hydration spectrum — from full to zero

Full hydration (classic React)
Hydrates the entire tree in one blocking pass. Nothing is interactive until the whole page finishes. Bundle includes every component’s code.
Selective hydration (React 18 + Suspense)
Parts of the tree hydrate independently. User interaction prioritises that boundary. Interruptible — yields to input. Same total cost, better order.
Islands architecture (Astro, Marko)
Page is static HTML by default. Only interactive components (“islands”) ship JS and hydrate. Static text: zero JS, never hydrates. Can delay: client:visible, client:idle.
Resumability (Qwik)
No hydration at all. App state + handler locations serialized into HTML. Client resumes from serialized state, attaches a handler only on first interaction. Startup JS ≈ 0.

Progressive hydration and the islands architecture. The deeper fix is to hydrate less. The islands architecture (Astro, Marko, Fresh) starts from the opposite default: the page is static HTML, and only the specific interactive components — the “islands” — ship JavaScript and hydrate. A blog post is 95% text: with islands, that 95% ships zero JavaScript and never hydrates, and only the comment box and the like button — the actual islands — carry JS. Each island hydrates independently, and can be told when to (client:visible hydrates on scroll into view, client:idle when the main thread is free). This is progressive hydration: the page is interactive where it needs to be, inert and free everywhere else.

Resumability: skipping hydration entirely. Qwik pushes the idea to its limit with resumability. Instead of re-running the component tree on the client to rebuild state and handlers, Qwik serializes the entire application state — including which handler is attached where — into the HTML itself. The client does not re-render to hydrate; it resumes from the serialized state, attaching a handler only when the user actually interacts with that specific element. Startup JavaScript approaches zero regardless of app size. The trade-off is a more complex serialization format and a framework built around it from the ground up — but conceptually it is the endpoint of the whole progression: from “hydrate everything” to “hydrate what the user touched” to “do not hydrate at all, just resume.”

Quiz

What does the islands architecture do differently from classic full-page hydration?

Quiz

A page is fully painted and visually complete, but tapping a button in the first 2 seconds does nothing. Which metric captures this and what is the cause?

Complete the analogy

Qwik avoids re-running the component tree on the client. Instead it serializes the whole app state — including which handler belongs where — into the HTML, and the client picks up exactly where the server left off, attaching a handler only on first interaction. What is this hydration-free approach called?

Pick the best fit

A content site: long articles (mostly text) with a comment box and a few interactive widgets. Pick the rendering and hydration approach.

Recall before you leave
  1. 01
    What are the four stages of hydration cost on the main thread?
  2. 02
    How does selective hydration change the user's experience compared to full hydration?
  3. 03
    What is the islands architecture's default assumption, and how does it differ from full hydration's default?
Recap

Hydration’s cost has four parts — download, parse/compile, execute, attach — all on the main thread, all after the page is painted. A 500 KB bundle is not just 500 KB of network; it is hundreds of milliseconds of parse-compile-execute on a phone. The uncanny valley: the page looks interactive, but input is dropped because the hydration long task owns the main thread — field INP. React 18 selective hydration makes the cost interruptible and priority-ordered but does not reduce the total. The islands architecture attacks the total by hydrating only the interactive parts — a text-heavy page with islands ships zero JS for the text. Resumability (Qwik) eliminates the re-render entirely: state and handler locations are serialized into the HTML, and the client resumes from that serialized state with zero startup JavaScript regardless of app size.

Connected lessons
appears again in267
Continue the climb ↑Hydration mismatch: causes, detection, and the determinism rule
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources4
expand
  1. 01
  2. 02
  3. 03
  4. 04

Trademarks belong to their respective owners. Editorial reference only.