npm run dev vs npm run start in Next.js: Key Differences Explained
npm run dev launches a development server with hot reloading and incremental compilation, while npm run start serves a pre-built production application from the .next directory without file watchers or on-the-fly bundling.
When working with the vercel/next.js repository, understanding the distinction between these two npm scripts is essential for optimizing your workflow. The functional difference between npm run dev and npm run start determines whether you're running a live development environment optimized for iteration speed or serving optimized production assets designed for runtime performance.
What Does npm run dev Do?
The npm run dev command (which maps to next dev) initializes a development server designed for active coding sessions. According to the source code in packages/next/src/cli/next-dev.ts, this command invokes the nextDev() function, which sets up a complex development environment.
Hot Reloading and Fast Refresh
When you run next dev, the server enables React Fast Refresh and hot module replacement (HMR). The CLI forks a child process (fork(startServerPath)) that runs ../server/lib/start-server with isDev: true. This flag triggers the development-specific code paths in packages/next/src/server/lib/start-server.ts, enabling on-the-fly compilation and client-side state preservation during updates.
File Watching and Incremental Compilation
The development server initializes file-system watchers using watchpack (with specific limits set for macOS) to monitor your source files. As implemented in next-dev.ts, the server performs incremental compilation—only recompiling files that have changed rather than rebuilding the entire application. The CLI also sets environment flags like __NEXT_DEV_SERVER=1 and NEXT_PRIVATE_WORKER=1 to enable development-specific telemetry and debugging features.
What Does npm run start Do?
The npm run start command (which maps to next start) launches a production server that serves pre-compiled assets. According to packages/next/src/cli/next-start.ts, this command invokes the nextStart() function, which operates fundamentally differently from its development counterpart.
Serving Pre-Built Output
Unlike next dev, the next start command requires a previous build step. It looks for the .next directory containing the output of next build and serves those static and server-rendered assets directly. The CLI calls startServer with isDev: false, which disables all development features and runs the compiled server code exactly as it will perform in production.
Production-Optimized Runtime
When running next start, the server disables file watchers, hot reloading, and source map generation. As implemented in the CLI entry point, it sets minimal environment variables and does not fork child processes for development tooling. The server loads the optimized bundles created during the build phase, resulting in lower memory overhead and faster request handling compared to the development server.
Key Technical Differences
Understanding the architectural divergence between these commands helps clarify when to use each mode.
Build Step Requirement
npm run dev: No prior build required. Compiles files incrementally when requested.npm run start: Requiresnpm run buildto generate the.nextdirectory first.
Server Implementation
Both commands eventually delegate to packages/next/src/server/lib/start-server.ts, but with different configurations:
- Development:
isDev: trueenables the dev server with child process forking, CPU profiling, and telemetry tracking as defined innext-dev.ts. - Production:
isDev: falseruns the server directly without development overlays or restart capabilities as defined innext-start.ts.
Bundler Behavior
- Development: Dynamically selects between Turbopack and Webpack based on CLI arguments (
parseBundlerArgsin the dev server), allowing experimental features likeexperimentalServerFastRefresh. - Production: Uses the bundler configuration frozen at build time; no runtime bundler selection occurs during
next start.
Process Model and Environment
- Development: Sets
__NEXT_DEV_SERVER=1, forks a child process for the server, and initializes file watchers withwatchpack. - Production: Runs in the main process with minimal environment flags and no active file monitoring.
When to Use Each Command
Development Workflow
Use npm run dev when:
- Writing new features or debugging code
- You need immediate feedback through hot reloading
- Testing experimental Turbopack features
- Profiling CPU usage during development (the dev CLI supports
--profiler)
Production Deployment
Use npm run start when:
- Previewing the production build locally before deployment
- Running the application in a production environment
- Optimizing for request latency and memory usage
- Serving the exact assets that will run on Vercel or other hosting platforms
Summary
npm run devlaunches a development server vianext-dev.tswithisDev: true, enabling hot reloading, file watchers, and incremental compilation optimized for development speed.npm run startlaunches a production server vianext-start.tswithisDev: false, serving pre-built assets from the.nextdirectory with minimal overhead and no development features.- The build step is mandatory for
npm run startbut optional fornpm run dev, which compiles code on-demand. - Both commands share the underlying
start-server.tsimplementation but diverge based on theisDevflag, determining whether to enable development-specific tooling like React Fast Refresh and Turbopack experimental features.
Frequently Asked Questions
Can I use npm run start without running npm run build first?
No, npm run start requires the .next directory to exist with pre-compiled assets. If you attempt to run next start without a prior build, the server will exit with an error indicating that the build output is missing. Always execute npm run build before npm run start in production workflows.
Does npm run dev use the same server code as npm run start?
Both commands ultimately delegate to packages/next/src/server/lib/start-server.ts, but they invoke it with different configurations. The next dev command in packages/next/src/cli/next-dev.ts sets isDev: true and forks a child process, while next start in packages/next/src/cli/next-start.ts sets isDev: false and runs directly. This flag determines whether development features like hot reloading are enabled.
Why is my app slower when running npm run dev compared to npm run start?
The development server prioritizes iteration speed over request performance. It runs incremental compilation, maintains file watchers, and injects development overlays that add overhead. In contrast, npm run start serves optimized, pre-compiled bundles with caching enabled and all development tooling disabled, resulting in faster response times and lower memory usage suitable for production traffic.
Can I use Turbopack with npm run start?
No, Turbopack is currently a development-only bundler used when running next dev with the --turbo flag. The next start command serves assets that were already compiled during the build phase, using whatever bundler (Webpack or Turbopack) was configured at build time. To use Turbopack in production, you would build with the experimental Turbopack flag, but the runtime server itself does not perform bundling.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →