iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Angular incremental hydration lets the server send fully rendered @defer sections while the browser keeps those sections dehydrated, meaning inert, until a trigger you choose fires. The Angular incremental hydration guide says the feature is enabled by default when an app uses provideClientHydration(), and that event replay turns on automatically with it. It builds on full-application hydration and deferrable views, so an SSR app must already have both working before you add a single hydrate trigger.
How incremental hydration differs from full hydration
Full hydration makes the whole server-rendered application interactive once the client boots. Incremental hydration is more selective. Angular describes it as “an advanced type of hydration that can leave sections of your application dehydrated and incrementally trigger hydration of those sections as they are needed” (Angular, Incremental Hydration guide).
The mechanism works like this. A hydrate trigger on an @defer block tells the server to render the main template rather than the @placeholder, so the reader sees real content in the first response. In the browser, Angular keeps the block’s dependencies deferred and leaves its content dehydrated until the trigger fires. If a user interacts with the block before that point, and the event matches a registered listener, Angular queues the event and replays it after hydration completes.
That makes incremental hydration a scheduling feature for SSR, not a lazy-rendering feature. The question it answers is “when does this section become interactive?”, not “when does this section first appear?”
#1 Best Overall
Setting up incremental hydration
Before you configure any triggers, confirm the following:
- Your application uses server-side rendering.
- Hydration is configured with
provideClientHydration(). - The sections you want to control are wrapped in
@deferblocks.
For a standalone bootstrap, the guide shows this shape:
import {bootstrapApplication, provideClientHydration} from '@angular/platform-browser';
bootstrapApplication(App, {
providers: [provideClientHydration()],
});
Incremental hydration is on by default in this configuration. To opt out and keep only full hydration, add withNoIncrementalHydration() to the provider list. Event replay does not need its own withEventReplay() call when incremental hydration is active, because it is enabled automatically. Check the exact feature names against the Angular version your project uses in the provideClientHydration API reference and the withIncrementalHydration API reference.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #2
Hydrate trigger reference
Each trigger answers a different question about timing. Compare them by what starts hydration, not by which one sounds fastest.
| Trigger | What starts hydration | Notes for implementation |
|---|---|---|
hydrate on idle |
The browser reports idle time. An optional timeout is passed to requestIdleCallback. |
Suits sections that can wait for spare browser time. If you set a timeout, document why that value was chosen. |
hydrate on viewport |
The target enters the viewport, detected with IntersectionObserver. |
Suits content that should become interactive as the reader scrolls toward it. |
hydrate on interaction |
A click or keydown occurs on the specified element. |
Suits a visible control that can stay inert until the reader engages with it. |
hydrate on hover |
mouseover or focusin occurs on the trigger area. |
Keyboard focus also triggers hydration, so this is not pointer-only. |
hydrate on immediate |
Hydration starts as soon as non-deferred content has finished rendering. | Offers almost no delay for the block. Use it only when the design requires it. |
hydrate on timer(500ms) |
A fixed duration elapses, written in milliseconds or seconds. | The delay is an explicit scheduling choice. The guide does not present any specific value as a performance target. |
hydrate when (custom condition) |
A custom expression becomes truthy. | Only works when the block is the top-most dehydrated @defer, and its parent component must already exist. |
hydrate never |
Nothing. The initial-render block stays dehydrated indefinitely. | Hydration triggers nested beneath this block will not fire either. |
Adding triggers to an @defer block
Hydrate triggers go inside the @defer parentheses, after any regular triggers and separated by semicolons:
@defer (on idle; hydrate on interaction) {
<large-cmp />
} @placeholder {
<div>Large component placeholder</div>
}
When you list several hydrate triggers, Angular treats them as OR conditions and hydrates the block as soon as any one of them fires. Hydrate triggers and regular on or when triggers can sit in the same block, but they govern different moments. On the initial server-rendered load, the hydrate triggers decide when the block becomes interactive. On later client-side renders, the regular triggers decide when the deferred content loads. In the example above, hydrate on interaction controls the first load, and on idle controls a later client-side render.
Rank #3
Because of that split, keep a @placeholder on every block that might render on the client after the initial load, such as after navigation. Hydration triggers do not cover those renders.
Free tools Windows power users keep installed
One-click scans. No signup required.
Nested @defer boundaries
Hydrating a child requires hydrating its parents first, because the child depends on the component hierarchy above it. When a nested child’s trigger fires, Angular hydrates the top-most dehydrated parent, then the child. The parent-first order is expected behavior, not a bug.
The guide also advises giving nested @defer blocks different triggers. If a parent and child both use the same trigger, they can start loading at the same moment and produce a cascade of simultaneous work. Decide the trigger for each level on purpose, and check whether a child’s trigger will in practice pull in a parent you meant to keep dehydrated.
Rank #4
Local development and Hot Module Replacement
With Hot Module Replacement (HMR) active, Angular fetches all @defer chunks eagerly, overriding the configured trigger conditions. This is a development-mode side effect, so do not use it to judge whether production scheduling works. To test normal trigger behavior locally, serve the app with ng serve --no-hmr, as described in the Deferred loading with @defer guide.
Constraints and common pitfalls
Incremental hydration carries every constraint of full hydration. Check these before you ship:
- Matching DOM. The server and client must generate the same DOM structure, including relevant whitespace and comment nodes. A mismatch is a common cause of hydration errors.
- No changes to server HTML. The HTML the server produced must not be altered between rendering and client hydration.
- No direct DOM manipulation. Native DOM changes, including writes through
innerHTMLorouterHTML, are a documented source of hydration errors. Use Angular’s template bindings instead. - Trigger review per boundary. Confirm that each block has the intended initial-load hydrate behavior and a sensible
@defertrigger for later client-side renders. - Nested cascades. Verify that nested triggers do not cause unwanted simultaneous loads.
The DOM-parity rules are covered in more detail in the Angular Hydration guide.
What the guide does and does not claim about performance
Angular presents smaller initial bundles and better initial loading as potential benefits of incremental hydration. The current incremental hydration guide does not publish a benchmark, figure, or measured effect size for this feature, so no performance number should be attributed to it. The guide names First Input Delay as one metric that smaller initial bundles may improve. Google has since replaced First Input Delay with Interaction to Next Paint as a Core Web Vital, so measure INP alongside Cumulative Layout Shift when you evaluate a page.
Measure the effect on your own application. Compare the same page with and without the hydrate triggers, using the same network and device conditions, rather than assuming the feature improves a given metric.
Once you have a baseline, adjust one trigger at a time, starting with the lowest-priority sections, and watch for simultaneous hydration cascades in nested blocks.
Use this page for the trigger rules and the behavior, and the Angular guides for syntax details that change between releases.
The rest of the work is in your templates: choose triggers by interaction and visibility needs, keep the DOM consistent between server and client, and check each block in both the initial load and client navigation paths.
Incremental hydration gives you a precise control over when sections of an SSR page become interactive. Used with clear triggers and a measured baseline, it lets you keep the first response complete while deferring the cost of interactivity to the moments that need it.
Quick Recap
”
The Bottom Line
“”
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

