The hydration mismatch you can't reproduce locally
Server and client render the same page differently exactly once, in production, for exactly one user. Chasing it down means understanding what actually diverges between the two environments.
Hammad Iqbal
Software Engineer
Server-side rendering promises that the HTML the server sends and the HTML the client renders will match, so React can attach event listeners instead of rebuilding the DOM from scratch. Most of the time that promise holds. Then a bug report comes in: a logged-in user saw a flash of the wrong content, a date rendered in the wrong timezone, a whole section vanished and reappeared. It never happens on your machine.
- A hydration mismatch means the server and client disagreed about the DOM before React ever got involved.
- The usual causes are time zones, locale formatting, random IDs, and anything reading window or Date on the server.
- Suppressing the warning hides the symptom; the actual state divergence is still there.
Why it never reproduces on your machine
Your dev server and your browser are usually in the same timezone, the same locale, and often the same process. Anything that depends on Date.now(), Intl, Math.random(), or window will quietly agree with itself locally and just as quietly disagree once the server runs in UTC on a container in another region while the client renders in the user's local timezone.
The usual suspects
Almost every mismatch traces back to a value that is computed differently depending on where the code runs, even though the code itself is identical.
- Formatting a date or number without pinning a fixed locale and timezone on both sides
- Generating an ID with Math.random() or crypto.randomUUID() during render instead of after mount
- Reading window, localStorage, or navigator directly in a component body
- Conditionally rendering based on typeof window !== 'undefined', which is true on the client and false on the server by design
Fixing it without hiding it
suppressHydrationWarning has exactly one legitimate use: a value you've deliberately decided is allowed to differ, like a last-updated timestamp. For everything else, move the divergent value out of the first render — compute it in useEffect and render a stable placeholder until then, or pass it down from the server as a prop instead of recomputing it on the client.
If a bug only shows up in production and only sometimes, check what your component reads that isn't passed in as a prop — the clock, the locale, and the window object are the most common ways two renders quietly disagree.
Have a project this kind of thinking applies to?
Tell me what you're building — I read every message myself.