The problem hydration creates
When a framework hydrates a server-rendered page, it rebuilds its component tree in the browser, compares it with the existing HTML and attaches event handlers. Until that finishes for a given part of the page, clicks and key presses on that part either do nothing or wait. Google's rendering guide describes this as a page that can look ready while it is not yet able to respond, and notes that hydration also means sending the same UI twice, once as HTML and again as the data and code needed to rebuild it (source 1).
On a fast laptop the gap may be too short to notice. On a mid-range phone with a CPU several times slower, a single hydration pass can become a long task of hundreds of milliseconds, and any tap that lands during it waits. That waiting shows up in Interaction to Next Paint as input delay (source 2).
What we look for
- How long hydration takes on each important route, measured on throttled CPU profiles, and how much of it runs as one uninterrupted task.
- What gets hydrated that never needs to be. Footers, article bodies and static marketing blocks often ship as interactive components when they contain no interactivity at all.
- Hydration mismatches. When server and client output differ, frameworks warn and may re-render or discard parts of the tree, which costs time and can cause visible flicker. Common causes include dates and times, random values, locale formatting and code that checks for
windowduring render. - Data duplication. Serialized state embedded in the HTML can be larger than the HTML itself. We check what is sent and whether all of it is needed on the client.
- Order of hydration. Whether the parts users touch first become interactive first.
The options we weigh
Every major framework now offers ways to hydrate less, later, or in pieces. Which ones apply depends on your stack and version:
- React and Next.js. Server Components keep code on the server entirely; only modules marked with
'use client'and their imports ship to the browser (source 3). Suspense boundaries let React hydrate sections independently, and React 19.2 also batches the reveal of server-rendered Suspense boundaries (source 4). - Vue. From Vue 3.5, async components in server-rendered apps can choose a hydration strategy such as
hydrateOnVisible,hydrateOnIdle,hydrateOnInteractionorhydrateOnMediaQuery(source 5). - Nuxt. Lazy components accept delayed hydration props such as
hydrate-on-visible,hydrate-on-idle,hydrate-on-interactionandhydrate-never(source 6). - Angular. Since version 22, incremental hydration is on by default when client hydration is enabled, and
@deferblocks can use hydrate triggers (source 7). - Astro and other island approaches. Components stay as static HTML unless given a client directive such as
client:visibleorclient:idle(source 8).
We do not recommend every option everywhere. Delaying hydration of a component that users reach for immediately makes things worse, and some strategies interact badly with analytics or testing setups. The plan says which components should change, which should not, and why.
How the engagement runs
- 01
Measure
Traces on fast and throttled profiles for up to three route families, with hydration work marked in each trace.
- 02
Map
A component map for each route showing what is interactive, what is static, and what hydrates when.
- 03
Fix mismatches first
A list of mismatch warnings with likely causes, because speed work on a route that re-renders after mismatches is built on sand.
- 04
Plan
A ranked plan of hydration changes written for your framework version, with expected effects described in plain words.
- 05
Review
Optional review of the pull requests your team writes from the plan, then retesting.
What you receive
The component maps, the trace files, the written plan, and a walkthrough call. If you choose the review add-on, we comment on pull requests and retest the routes once the changes reach staging.
Measuring progress
Hydration changes are easy to measure in the lab and slower to confirm in the field. In traces, we compare the gap between first contentful paint and the end of the last hydration task, and the length of the longest task in that window, on the same build and throttle settings before and after. In field data, the useful signal is Interaction to Next Paint for interactions that happen early in a visit, especially the input delay phase. If you collect attribution, interactions grouped by time since navigation make the change easy to see. Chrome UX Report data moves more slowly because it aggregates over 28 days, so we treat it as confirmation rather than the first check.
Common objections
A fair concern is that delaying hydration could break analytics, tests or third-party widgets. Those concerns are real and worth checking. Analytics that rely on component lifecycle events may fire later; end-to-end tests that click immediately may need to wait for hydration; widgets that expect the whole app to be live may need an earlier boundary. The plan lists these knock-on effects for each change, so they can be handled during implementation rather than discovered in production.
Questions about hydration work
Is hydration always the cause when a server-rendered page feels slow?
No. Large third-party scripts, slow APIs called after load, and heavy event handlers produce similar symptoms. The first step is a trace that shows which of these fills the main thread.
Will lazy hydration hurt accessibility?
It can if a control looks usable before it works. We check that delayed components either hydrate before a user can reach them or still work as plain HTML, for example a link that navigates even before its enhanced behaviour loads.
Can we fix hydration without upgrading our framework?
Often, yes. Removing interactivity that is not needed, moving data off the client and fixing mismatches work on most versions. Some strategies, such as Vue's built-in lazy hydration, need a minimum version, and the plan states which.
Sources
- Rendering on the Web, web.dev Primary source (Google)
- Interaction to Next Paint (INP), web.dev Primary source (Google)
- 'use client' directive, React reference Primary source (React team)
- React 19.2, React blog Primary source (React team)
- Async Components: Lazy Hydration, Vue.js guide Primary source (Vue team)
- Components directory: delayed hydration, Nuxt docs Primary source (Nuxt team)
- withIncrementalHydration API, Angular docs Primary source (Angular team)
- Islands architecture, Astro Docs Primary source (Astro)