skip to content

An Angular app hydrates cleanly in development but throws NG0507 after deployment behind a CDN. What is Angular detecting, and what else alters server HTML?

level: seniorimportance: nice to knowfreq 30%

answer

  1. comments are load-bearing
  2. an integrity marker comment
  3. minification in transit
  4. invalid nesting, tbody, whitespace

basics

~10 s

NG0507 means the server's hydration integrity comment is missing, so something rewrote the HTML in transit, typically CDN minification stripping comments and whitespace. Disable it; also keep templates valid HTML and whitespace settings identical.

solid answer

~40 s

Angular's hydration relies on the server HTML exactly as produced, including comment nodes that anchor blocks and containers and text nodes whose positions are serialized. The server adds a `<!--nghm-->` integrity comment; if the client cannot find it, Angular throws NG0507 because the HTML was altered after rendering. Behind a CDN the usual cause is HTML minification that strips comments and collapses whitespace, and the fix is to turn it off for server-rendered pages; custom post-processing does the same. Related divergences show up as NG0500-family errors instead: invalid nesting like a `<div>` inside a `<p>`, a `<table>` without `<tbody>` that browsers repair, or `preserveWhitespaces` set differently for the browser and server builds.

go deeper

for a junior

Recall that hydration needs the server HTML unchanged, including its comments and whitespace.

for a middle

Explain the integrity marker behind NG0507 and how invalid nesting or a missing tbody makes the parser change the DOM.

for a senior

Trace a production-only failure to CDN or proxy rewriting by comparing origin and delivered HTML, and fix the infrastructure rather than the component.

for a principal

Treat server HTML as a contract across teams that own CDN, proxy and build tooling, and make changes to those layers include a hydration check.

## The symptom An Angular application hydrates cleanly with the development server. After deployment behind a CDN, the browser console reports **NG0507: HTML content was altered after server-side rendering**, and the page no longer hydrates. ## What Angular is checking Hydration relies on the server HTML **byte-for-byte in structure**, including the parts a human would call noise: - **comment nodes** that Angular uses as anchors for containers, `@if` and `@for` blocks and projected content; - **text and whitespace nodes** whose positions are recorded in the serialized hydration data; - the **`<!--nghm-->` integrity marker**, a comment the server places at the start of the body. Before hydrating, the client looks for that marker. If it is missing, Angular concludes that something rewrote the HTML between the server and the browser, and throws NG0507 rather than trying to match a DOM it can no longer trust. ## The usual culprits 1. **CDN or proxy "optimisations".** HTML minification that removes comments and collapses whitespace deletes the marker and the anchors. Turn that option off for server-rendered pages. 2. **Custom post-processing.** A build step or server middleware that minifies or rewrites the generated HTML has the same effect. 3. **Injected content.** Scripts added by an edge layer or a tag manager that insert nodes before hydration can cause NG0500-family mismatches even when the marker survives. ## Other ways server and browser HTML diverge NG0507 is the "marker missing" case. Related divergences surface as NG0500, NG0501 or NG0502 instead: | Cause | Why the DOM differs | Fix | | --- | --- | --- | | Invalid nesting such as `<div>` inside `<p>` or `<a>` inside `<a>` | The browser parser repairs the tree differently from the serialized structure | Make the template valid HTML | | `<table>` without `<tbody>` | Browsers insert a `<tbody>` the server never wrote | Always write `<tbody>` explicitly | | `preserveWhitespaces` set differently for the browser and server builds | One side keeps whitespace text nodes the other drops | Keep the setting identical, ideally the default `false` | ## A diagnosis routine 1. Compare the HTML **as the origin server sends it** with the HTML the browser receives through the CDN; a missing `<!--nghm-->` comment confirms the rewrite. 2. Check CDN, proxy and server middleware settings for HTML minification or comment stripping. 3. For NG0500-family errors, reproduce in development mode, where detailed checks run, and read the expected and actual DOM in the message. 4. Validate the template HTML, since invalid nesting is easy to miss when the browser silently repairs it. ## Preventing a repeat - Add a smoke test that fetches a server-rendered page **through the CDN** and asserts that the `<!--nghm-->` comment is present. - Run the app in development mode against production-like HTML before enabling any new edge feature, since the detailed hydration checks only run there. - Record in the CDN configuration why HTML minification is off, so the next "performance" change does not switch it back on. - Lint templates for invalid nesting and missing `<tbody>` in code review. ## Why this is a senior question The failure appears only in production-like paths, after an infrastructure change, and the fix is often outside the Angular code base. A candidate who has operated SSR knows that hydration makes the HTML a **contract between the server and the client**, and that anything in between, including tooling meant to help, can break it.

  • Why does a table without <tbody> break hydration?
    The HTML parser inserts a `<tbody>` element that the server's serialized structure does not contain, so Angular finds a node it did not create where it expected a row. Writing `<tbody>` explicitly makes both sides identical.
  • Why must preserveWhitespaces match between the browser and server builds?
    It decides whether whitespace text nodes are kept in compiled templates. If only one build keeps them, the server HTML and the client's expectations differ by text nodes, which breaks node-by-node matching. Keep the default `false` on both, ideally set once in the shared app tsconfig.

saying these in an interview costs you the question

  • HTML comments in server output are debug noise that can be stripped
  • NG0507 means the server and client bundles have different versions
  • Browsers never change valid-looking HTML while parsing it
  • Whitespace differences cannot affect hydration
  • NG0507 is fixed by adding ngSkipHydration to the root component