Under The Hood
frontend angular Angular 17+ (hydration), 18+ (event replay)

Non-Destructive Hydration & Event Replay Mechanics

Last updated
Prerequisites:
Angular SSR/SSG basics
Understanding of the DOM lifecycle and event listeners
  • angular
  • hydration
  • ssr
  • event-replay
  • server-side-rendering
  • dom

Read at your depth

The practical view

Hydration is the process where Angular, after server-side rendering HTML, attaches client-side behavior to that existing HTML instead of re-creating it. With hydration enabled (provideClientHydration()), Angular reuses the SSR-generated DOM nodes and wires up event listeners, avoiding a destructive re-render (which caused flicker and broke focus/scroll). In Angular 18+, event replay is also available: user interactions that happened before hydration completed (clicks on buttons rendered by SSR) are recorded and replayed once the app hydrates, so no click is lost. This gives near-instant first paint plus full interactivity.

The same idea in other frameworks

react equivalent
React 19's hydration + (experimental) event replay are the direct analogues.

Legacy vs modern

Destructive re-render vs non-destructive hydration

Without hydration, Angular re-creates the DOM after SSR (flicker, lost focus); with hydration, the SSR DOM is adopted in place and early events replay.

before → after
No hydration (destructive re-render)
bootstrapApplication(App); // ❌ OLD: no provideClientHydration → Angular re-creates the DOM
Hydration + event replay
bootstrapApplication(App, {
  providers: [provideClientHydration(withEventReplay())], // ✅ NEW
});

Interview gotchas

Context

This tests the matching algorithm and its failure modes — interviewers want to know why some SSR apps hit hydration mismatches and how the framework reacts.

The mechanical answer

Hydration reuses a node when it matches the expected template structure: same element type, same order, and consistent Angular annotations (component host markers, i18n nodes). Anything that makes the client's expected tree differ from the SSR HTML — dynamic content that renders differently on server vs client (e.g. reading localStorage, window size, Date), structural directives whose data changed between server and client render, or third-party DOM mutation of the SSR markup — causes a mismatch. Angular logs a hydration error (NG0500 series) and falls back to re-rendering that subtree (destructive for that branch only) to avoid a broken UI. The transfer state mechanism also carries serialized data so client render matches server state.

Trap

The naive answer is 'hydration works unless you mutate the DOM'. Mismatches also come from nondeterministic rendering (Date.now(), Math.random, window access) and from services that produce different data on server vs client. Another trap: assuming a mismatch breaks the whole app — Angular falls back per-subtree, but silent mismatches can cause event/listener wiring errors, which is why the errors are worth fixing. Candidates who mention NG0500 errors and the per-subtree fallback show real experience.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.