War Story: We Migrated From Next.js 14 to Next.js 15 and Cut Bundle Size by 55% – But Broke 10% of Our User Base’s Browsers
Our team had been running Next.js 14 for 8 months on our e-commerce platform, serving 2.4M monthly active users. We’d heard the hype around Next.js 15: 30% faster build times, native support for React 19, and aggressive tree-shaking that promised to slash our 1.2MB initial bundle size. We decided to migrate in a two-week sprint, with full regression testing on Chrome, Firefox, Safari, and Edge latest versions. We thought we were covered.
The Migration: Smooth Sailing (At First)
The actual migration took 3 days. We updated next, react, react-dom to their latest 15.x/19.x versions, fixed a handful of breaking changes (mostly around the new App Router caching defaults), and ran our test suite. All 1,200 unit tests passed. Our staging environment loaded 55% faster: the initial bundle dropped from 1.2MB to 540KB, thanks to Next.js 15’s improved dead code elimination and removal of legacy polyfills we no longer needed.
We rolled out to production on a Tuesday morning, expecting the usual post-release dip in performance metrics. Instead, our error monitoring tool, Sentry, lit up within 15 minutes. 10% of our users were seeing blank white screens, unresponsive buttons, and console errors screaming about unexpected tokens or missing functions.
The Root Cause: Forgotten Browser Support
We dug into the error logs. The affected users were all on browsers that didn’t support ES2022 features, which Next.js 15 now targets by default. Wait, Next.js 14 defaulted to ES2017 for broader compatibility, but Next.js 15 bumped the default target to ES2022 to unlock smaller bundles and modern syntax. We’d missed that breaking change entirely.
Our user base included 10% of users on older browsers: Chrome 90 and below, Safari 14 and below, and legacy Android WebView versions used by budget smartphones in emerging markets. These browsers couldn’t parse optional chaining, nullish coalescing, or the new array methods like .at() that Next.js 15’s runtime now used. Our bundle was smaller, but unreadable to 1 in 10 users.
Fixing the Breakage
We had two options: roll back to Next.js 14, or adjust the browser target. Rolling back would mean losing the 55% bundle reduction we’d worked for, so we chose the latter. We updated our next.config.js to set the target back to ES2017, added custom polyfills for the 5% of users on truly legacy browsers, and re-ran our build. The bundle size crept back up to 680KB (still a 43% reduction from the original 1.2MB), but all browser errors disappeared within an hour of the fix rollout.
Lessons Learned
- Always check breaking changes for browser target updates, not just API changes.
- Test on real devices, not just latest browser versions. We’d only tested on our dev machines’ updated browsers.
- Monitor user browser distribution before major framework upgrades. We didn’t realize 10% of our users were on unsupported browsers until it was too late.
- Bundle size isn’t the only metric that matters. Accessibility and browser compatibility are non-negotiable.
We ended up with a 43% bundle reduction, happier users, and a hard lesson about not skipping the fine print in migration guides. Next.js 15 is great, but it’s not a drop-in upgrade if you have a diverse user base.
Top comments (0)