Your Next.js Build Turned Glacial at 2 AM—Here's Why and How to Fix It
It’s 2 AM on Friday. Your Next.js build—which clocked in at 45 seconds last week—now takes 8 minutes. Your CI/CD pipeline is burning through minutes, your staging deployment is stalled, and you’re awake trying to figure out why. The deploy button worked yesterday.
This is the exact moment when “it was working fine” becomes your least favorite phrase.
Slow builds aren’t rare—they’re inevitable as codebases grow. But they’re also solvable. Here are the four common culprits and how to kill them.
The Four Build Killers
1. Dependencies You Didn’t Know You Added
Next.js bundles are only as fast as the heaviest package you import. A single “helper” library pulling in lodash, moment.js, or a bloated charting package can spike your build time by 30–60 seconds. Worse: if a new dependency appears in your node_modules, it gets processed by webpack regardless of whether you use it.
Check your dependency tree:
npm list --depth=0
Look for multiple versions of the same package. If you see npm WARN for duplicates, webpack is processing the same code twice. That’s wasted CPU cycles in every build.
2. Memory Exhaustion
Node.js has a default heap limit (~2.2 GB on most systems). As your codebase grows, the build allocates memory for source parsing, AST transformations, tree-shaking analysis, and code splitting. When you hit the limit, Node switches to aggressive garbage collection, and everything crawls.
You’ll see this in build logs: long pauses with no output, or cryptic “JavaScript heap out of memory” errors.
3. Cache Poisoning
Next.js caches build artifacts in .next/. Corrupted or stale cache can slow down every subsequent build. A single large image, font, or compiled chunk lingering in the cache forces Next.js to re-validate and re-build things it shouldn’t touch. Months of accumulated build data = seconds of wasted time per build.
4. Webpack Configuration Drift
If you’ve customized next.config.js (custom loaders, plugins, optimization rules), any misconfiguration cascades. A loader running on every file instead of a subset, or a plugin re-running unnecessary transforms, adds seconds per file. With 500+ component files, that multiplies fast.
The 5-Minute Diagnostic
Run these checks in order:
-
Check build time variance: Compare today’s build time to last week’s logs. If it jumped >50%, you added something big recently.
-
Measure without cache:
rm -rf .next && npm run build. Time it. If the uncached build is still 8 minutes, the problem is in your code or dependencies, not the cache. -
Profile memory:
node --max-old-space-size=4096 node_modules/.bin/next build. Allocate 4 GB and retry. If build suddenly completes in 90 seconds, your Node process is memory-starved. -
Check for new packages:
git log --oneline -20 | grep -i package. See if anyone added dependencies in the last few days. -
Inspect the cache:
ls -lh .next/. Files >100 MB are suspicious..next/shouldn’t exceed 500 MB for a typical app.
Fixes That Work
Right now (next 10 minutes):
- Clear the cache: rm -rf .next && npm run build
- Increase Node heap: Add --max-old-space-size=4096 to your build script in package.json
- Kill background processes: Ensure your IDE, Docker, or other apps aren’t hogging resources
This build (next 30 minutes):
- Prune unused packages: npm prune and audit your package.json for dead weight
- Consolidate duplicate packages: If you have two versions of the same lib, merge them
- Comment out experimental config: Review next.config.js for custom loaders or plugins added as “let me try this”
This week (prevention):
- Set up build time monitoring: Add a threshold (e.g., fail if build >3 minutes). Your CI/CD alerts you before slowdowns hit production
- Use dynamic imports: Convert heavy components to next/dynamic with lazy loading
- Enable SWC minification: Ensure swcMinify: true in next.config.js. It’s faster than Terser
Stop It From Happening Again
- Lock your dependencies: Use
npm ciin CI/CD. Use exact versions inpackage.json, not ranges like^1.2.3 - Add a pre-commit hook: Use
huskyto reject PRs that add packages without review - Monitor build times: Commit a
build-stats.jsonto track trends. A 30% regression in a single PR is your cue - Test builds before pushing: Run
npm run buildlocally. If it’s slow for you, it’s slow for CI
The Real Cost of Slow Builds
Slow builds aren’t just annoying—they compound: - Blocked deployments: 8-minute builds mean staging updates every 30 minutes instead of every 5 - Stalled iteration: Developers context-switch while waiting - CI/CD bloat: 20 engineers × 5 extra minutes per build = ~1.5 hours of team time lost daily
For teams shipping on tight schedules, this adds up to missed deadlines and burned cash.
If you’re scaling custom software and want to skip the “mysterious slowdowns” phase, Trove Deck Solution includes build pipeline audits during the technical scoping phase. We flag these bottlenecks before they become 2 AM crises. Prevention is cheaper than firefighting.