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: Requires npm run build to generate the .next directory first.

Server Implementation

Both commands eventually delegate to packages/next/src/server/lib/start-server.ts, but with different configurations:

  • Development: isDev: true enables the dev server with child process forking, CPU profiling, and telemetry tracking as defined in next-dev.ts.
  • Production: isDev: false runs the server directly without development overlays or restart capabilities as defined in next-start.ts.

Bundler Behavior

  • Development: Dynamically selects between Turbopack and Webpack based on CLI arguments (parseBundlerArgs in the dev server), allowing experimental features like experimentalServerFastRefresh.
  • 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 with watchpack.
  • 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 dev launches a development server via next-dev.ts with isDev: true, enabling hot reloading, file watchers, and incremental compilation optimized for development speed.
  • npm run start launches a production server via next-start.ts with isDev: false, serving pre-built assets from the .next directory with minimal overhead and no development features.
  • The build step is mandatory for npm run start but optional for npm run dev, which compiles code on-demand.
  • Both commands share the underlying start-server.ts implementation but diverge based on the isDev flag, 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →