Why our LCP regressed after a Next.js upgrade, and how we found it
Upgrading a core framework is rarely as simple as bumping package.json and watching the CI turn green. In high-traffic e-commerce environments, invisible changes in client runtime initialization can silently penalize your Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS).
The Symptom
Following a major version bump, our synthetic Lighthouse runs appeared reasonably healthy. However, within 48 hours of canary rollout, our real-user monitoring (RUM) p75 LCP spiked from 1.8s to 2.4s on mobile devices.
The Investigation
We captured detailed Chrome DevTools performance traces and compared Main Thread flamegraphs side-by-side:
- Hydration Scheduling Drift: The new runtime altered the timing of server HTML hydration, shifting script execution directly into the critical rendering window.
- CSS Chunk Loading: Critical CSS was being injected asynchronously via dynamic link insertion rather than inlined in the document
<head>.
The Solution
We resolved the regression with three targeted optimizations:
- Restoring synchronous critical CSS preloading in the document header.
- Deferring third-party analytics scripts to
requestIdleCallback. - Migrating non-interactive widgets to server-only static rendering without hydration overhead.
Within hours of rolling out the fix, our mobile LCP dropped back down to 1.7s, fully restoring our Core Web Vitals pass rate.