# npm run dev vs npm run start in Next.js: Key Differences Explained

> Understand the key differences between npm run dev and npm run start in Next.js. Learn how each command impacts your development and production workflows for optimal performance.

- Repository: [Vercel/next.js](https://github.com/vercel/next.js)
- Tags: deep-dive
- Published: 2026-02-16

---

**`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`](https://github.com/vercel/next.js/blob/main/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`](https://github.com/vercel/next.js/blob/main/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`](https://github.com/vercel/next.js/blob/main/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`](https://github.com/vercel/next.js/blob/main/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`](https://github.com/vercel/next.js/blob/main/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`](https://github.com/vercel/next.js/blob/main/next-dev.ts).
- **Production**: `isDev: false` runs the server directly without development overlays or restart capabilities as defined in [`next-start.ts`](https://github.com/vercel/next.js/blob/main/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`](https://github.com/vercel/next.js/blob/main/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`](https://github.com/vercel/next.js/blob/main/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`](https://github.com/vercel/next.js/blob/main/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`](https://github.com/vercel/next.js/blob/main/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`](https://github.com/vercel/next.js/blob/main/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`](https://github.com/vercel/next.js/blob/main/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.