The site renders on the server and React then hydrates it in the browser: it paints the same tree again and compares it against the HTML that arrived. If they differ it does not patch the difference — it throws the server HTML away and repaints the whole page on the client. That is the expensive way to do server rendering: you pay for the render and then bin it.
The console showed React error #418, which is that mismatch in minified form. Some loads had it, some did not, so I put it off for weeks.
The part worth writing down
What broke the "sometimes yes, sometimes no" was loading the home page with Playwright while changing the browser's time zone. It stops being intermittent the moment you look at the right variable:
- 4
- time zones tested, 3 with the page broken
- 2
- different days written for the same instant
- 6
- files touched to fix it
- 5
- tests keeping it from coming back
The cause was repeated across half the project, in the most innocent-looking way a date can be written:
From 22:00 UTC onwards the two halves wrote different days for the same date. React compared "16 de agosto" against "15 de agosto", saw two strings that do not match, and did exactly what it is supposed to do.
The most annoying detail: the PageSpeed robot measures in UTC. So the score I kept looking at was always the bad case, while in my own browser, in Madrid, the site was fine. I spent that time on images, fonts and bundle size, because the numbers did not match what I could see.
The fix
My first attempt was to pin TZ=Europe/Madrid in the container. The error went away, of course: I am in Madrid. That fixed nothing, it just made the server agree with me. For someone in Mexico it was still broken.
The real fix was the boring one: a formatearFecha() function with the zone written into it, and every date on the site going through it instead of calling Intl directly. Six files, 94 lines added and 14 removed. What matters is not that the zone is Madrid, it is that it is one fixed zone, the same on both sides.
Plus a regression test, because you cannot see this failure by looking at the screen:
Where it stands today
As of 29 August 2026, loading the production home page 16 times across Madrid, UTC, Los Angeles and Tokyo: the day is written identically in all four and the <h1> is present in every one. The time zone mismatch is gone.
What is still wrong, before you find it yourself
In those same 16 loads, 2 still produced a #418. It no longer follows the old pattern though: it comes and goes within the same zone, so it is a different failure from the one this case is about. My guess is something computed from a running clock rather than a fixed date. Unresolved.
And one place still has the original bug intact: the my account page, a client component that still formats dates without naming a zone. It sits behind the login, so neither the PageSpeed robot nor many people ever reach it. That explains why it is still there; it does not make it right.
Stack: Next.js 15, React, Docker, self-managed VPS. My own project, nothing confidential — which is why it can be told in full, numbers and tests included.