Next.js Config Not Working? Find the Production Blocker
- Average build time per page
- s/page
- Result
- Build time (seconds)
- 120 s
- You entered
- Pages in project
- 25 count
- You entered
If your Next.js configuration seems to be ignored or causes errors only in production, the blocker is usually a stale build cache, an environment variable that’s missing at build time, or a config option that only applies during `next build` rather than `next dev`. This article explains how to systematically identify and fix these production-only configuration issues.
Formula
The calculator above estimates your build throughput: rate = pages / time, and per-page time = time / pages. In words, if you know how many pages your app has and how long a full production build takes, you can see whether the build is abnormally slow (which often points to a config problem like excessive rewrites or unoptimized images). Variables: t = total build time in seconds, p = number of pages (including dynamic routes).
Worked Example
Using the defaults: t = 120 s, p = 25. Rate = 25 / 120 = 0.21 pages/s. Per-page = 120 / 25 = 4.8 s/page. If your actual per-page time is far above this, your config may be forcing full re-renders or re-downloads.
Why Does Next.js Config Behave Differently in Production?
Next.js runs your next.config.js at two distinct times: during next dev and during next build (which then serves static files or serverless functions). Many options—like output: 'standalone', images.unoptimized, or experimental.serverActions—only take effect at build time. So a config that works locally may fail on a hosting platform because the build environment lacks a variable, a file, or a specific Node version.
Common Production Blockers and How to Find Them
- Stale build cache: Next.js caches compiled output in
.next. If your host reuses a cache from an older config, your changes won’t apply. Fix: runnext buildwithrm -rf .nextor setNEXT_TELEMETRY_DISABLED=1and clear the cache in CI. - Missing environment variables: Config code that reads
process.envat build time will fail if the variable isn’t set in the build environment. Check your host’s environment variable settings—not just your local.env.local. - Incorrect file location: Next.js expects
next.config.js(or.mjs/.ts) in the project root. If you’re using a monorepo, the config must be in the app’s root, not the monorepo root. - Syntax or type errors: A single typo in the config can cause the build to fail silently or fall back to defaults. Run
node -e "require('./next.config.js')"to check for errors. - Using dev-only features: Some options like
reactStrictModeare fine, butexperimental.appDir(older versions) orexperimental.serverComponentsmay be ignored in production if not properly enabled.
How to Debug a Production-Only Config Failure
- Reproduce locally: Run
next buildlocally with the same environment variables as your host. UseNODE_ENV=productionexplicitly. - Check build logs: Look for warnings like “Invalid next.config.js options” or “The ‘images’ option is experimental”. These often point to the exact field.
- Simplify: Comment out half of your config and see if the build passes. Binary search the offending option.
- Verify output: After a successful build, inspect the
.nextfolder to see if your changes took effect (e.g., checkBUILD_IDor the generated routes).
Real-World Example: Images Not Optimizing in Production
Suppose you set images: { domains: ['example.com'] } but your production site still shows broken images. The blocker is often that the domain list is only used during next build for static optimization, but if you’re using a custom server or serverless functions, the config must be available at runtime. In Next.js 12+, the images config is bundled into the server, so a missing images.unoptimized or a mismatch with your CDN can cause issues.
Comparing Config Approaches: Static vs. Runtime
Next.js offers two main ways to configure: build-time (in next.config.js) and runtime (via environment variables or server code). Build-time config is baked into the bundle; runtime config is read when the server starts. If your production blocker is a value that changes per deployment (like an API URL), prefer runtime environment variables over hardcoded values in the config.
How to Choose the Right Fix
First, determine whether the issue is a build failure or a runtime misbehavior. If the build fails, focus on the config file syntax, environment variables, and Node version. If the build succeeds but the app misbehaves, check if the config is actually being applied—look for the option in the generated output or add a temporary console.log in the config to see if it’s executed.
Frequently Asked Questions
Why does my config work in dev but not in production?
Because next dev compiles on-demand and may not fully evaluate all config options. Production runs a full build, which is stricter and may require additional environment variables or a different Node version.
How do I clear the Next.js build cache?
Delete the .next folder and run next build again. In CI, you can add a step to remove it or set NEXT_TELEMETRY_DISABLED=1 to avoid cache-related issues.
What does “Invalid next.config.js options” mean?
It means Next.js detected a key or value that doesn’t match the expected schema. Check the spelling and the type (e.g., images.domains must be an array of strings).
Can I use environment variables inside next.config.js?
Yes, but they are evaluated at build time. If you need runtime values, use publicRuntimeConfig or serverRuntimeConfig (deprecated in favor of env vars) or read them from process.env in your server code.
Why is my custom webpack config ignored in production?
Custom webpack configs are applied during build. If you’re using a hosting platform that runs next build in a separate environment, ensure your config file is committed and doesn’t rely on local paths.
What is the safest way to test a production config?
Run next build locally with the same environment variables as your host, then serve the output with next start. This replicates the production environment closely.
Related
Formula used
in t | Build time (seconds) | s | 120 | 0 in p | Pages in project | count | 25 | 1 out rate | Pages built per second | pages/s | p / t | 2 out per_page | Average build time per page | s/page | t / p | 2
Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.