next dev starts the Next.js development server with hot reloading, on-demand compilation and verbose errors, and it is deliberately not what you should run in production, where you use next build followed by next start.
Most of the grief around the dev server is predictable: a busy port, a slow first load, a missing environment variable, or a bug that only exists after the build.
Table of contents
- What next dev actually does
- Port, hostname and network access problems
- Slow starts and slow rebuilds
- Environment variables and the dev versus production gap
- From dev server to a live deployment
- Debugging, Turbopack and other useful flags
- How this fits the rest of the stack
- FAQ
What next dev actually does
When you run next dev, Next.js starts a local server, by default on port 3000, and compiles pages on demand. The first visit to a route triggers compilation of that route, which is why a cold page is slower than the second visit. After that, changes to your files are picked up and pushed to the browser through hot module replacement, so edits appear without a full reload.
The development server also does a lot you do not get in production. It shows an error overlay with a stack trace, enables React’s strict development warnings, skips many optimisations, and does not apply the same caching. The behaviour is tuned for feedback speed, not for runtime speed or fidelity.
In package.json, the standard scripts look like this:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}
The three commands form a pipeline. dev is for editing. build produces an optimised production output. start serves that output. Treating them as interchangeable is the root of many deployment surprises, since a bug in static generation or an environment variable read at build time only shows up after build.
The official docs are the reference for flags. Two are worth knowing immediately: -p to choose a port and -H to choose the hostname the server binds to. The existing guides on running a Next.js app locally and Next.js setup cover the basics from scratch.
Port, hostname and network access problems
The most common failure is a port already in use. Another process, often a previous dev server that did not shut down, holds 3000, and Next.js either moves to the next free port or errors. Pick a port explicitly:
next dev -p 4000
To find and stop whatever is holding a port on Linux or macOS, lsof -i :3000 lists the process and kill ends it. On Windows, netstat -ano | findstr :3000 shows the process ID to stop.
A second classic: the app works on your machine but not from a phone or another computer on the network. By default the server may listen only on localhost. Bind to all interfaces with next dev -H 0.0.0.0 and open the machine’s LAN address. Only do that on a trusted network, since the dev server is not hardened.
A third: running the dev server inside a container or a virtual machine. The server must bind to 0.0.0.0, not localhost, or the published port reaches nothing. In Docker, publish the port and set the host flag.
A fourth is file watching. In some container and network drive setups changes are not detected, so edits do not refresh. Polling-based watching options fix it at the cost of CPU. If hot reload silently stops, check where the project files live before suspecting your code.
Slow starts and slow rebuilds
Slow dev servers usually come from one of four causes.
A huge route graph. On-demand compilation means a large page that imports half your codebase compiles slowly on first visit. Break up heavy components and use dynamic imports for rarely needed pieces.
Barrel files and wide imports. Importing from an index file that re-exports hundreds of modules forces the compiler to process all of them. Import from the specific module instead.
Antivirus and sync tools. Real-time scanning of node_modules and .next slows every file read. Exclude those folders, and keep the project out of cloud-synced directories.
Memory pressure. A dev server on a small machine with many tabs and an editor open will swap. Close the extras or raise the Node memory limit.
If the first load is slow but later ones are fast, that is the on-demand model working as designed. If every change takes seconds, look at the project, not the tool. Clearing the build cache by deleting the .next folder is a safe, quick test that rules out a corrupt cache.
Check your Node version too. Next.js has a minimum supported Node version, and an outdated one produces confusing syntax errors that look like bugs in your code.
Environment variables and the dev versus production gap
Environment variables behave differently depending on how they are named and when they are read. Variables in .env.local are loaded by the dev server. Only those prefixed with NEXT_PUBLIC_ are inlined into browser code, and they are inlined at build time, so changing one requires a rebuild for production.
A frequent bug is a value that is undefined in the browser because it lacks the prefix, which is correct behaviour, since anything without it must stay server-side. Never prefix a secret with NEXT_PUBLIC_.
The larger gap is that dev and production are different programs. Things that work in next dev and fail in production include pages that depend on dev-only behaviour, images that were not configured for optimisation, dynamic routes that need static params, and code that assumes it runs on a single long-lived process.
The fix is to run the production path locally before you ship:
npm run build
npm run start
If the build succeeds and the app behaves in start, you have caught most dev-versus-production differences on your own machine instead of in front of users. Make this part of your checklist before every release, and make your continuous integration run next build so it fails the pull request rather than the deploy.
From dev server to a live deployment
Next.js applications that use server rendering or server actions need a running Node process in production, not just file hosting. Applications that export as static files can be served from any static host.
On RunxBuild, a Next.js app deploys as a web service from a GitHub repository. The platform runs the build, shows the build log, attaches a live route and keeps runtime logs per deploy, with rollback to the previous deploy if something goes wrong. Environment variables are set per service in the dashboard, so the production values never live in your repository. A static export can instead deploy as a static site with 120GB of bandwidth included. The Next.js service docs cover the build and start commands it expects.
Match the commands: the platform will run your build script and then start the server, so the same two commands you tested locally are the ones that matter.
Debugging, Turbopack and other useful flags
A few features of the dev server are worth knowing because they save hours.
Recent versions can use Turbopack, a Rust-based bundler, for development. It makes startup and updates noticeably faster on large projects. If you hit an odd compile error, check whether it reproduces with the default bundler before assuming your code is wrong, since bundler differences are a real source of confusing failures.
For debugging server code, start Node with the inspector so a debugger can attach:
NODE_OPTIONS='--inspect' next dev
Then attach from your editor or from Chrome’s inspect page, and set breakpoints in server components and route handlers. For client code, the browser developer tools work as usual with source maps enabled.
Watch the terminal as well as the browser. Many server-side errors, such as a failing fetch inside a server component, appear only in the terminal where next dev runs, and the browser shows a generic error page. When something is mysteriously blank, read that terminal first.
Finally, when behaviour becomes inexplicable, remove .next, reinstall dependencies if the lockfile changed, and restart. It is the Next.js version of turning it off and on again, and it works often enough to try before debugging.
How this fits the rest of the stack
A dev server costs nothing and a production service never does, so size the second before you outgrow the first. The RunxBuild hosting calculator shows what a Next.js service and its database cost together. When the app passes build and start on your machine, the RunxBuild dashboard is where you connect the repository and ship it.
Useful related references:
- Run NextJS App Locally: The dev Command, the Build, the Start, the .env, and the One Mistake That Breaks the Localhost
- Git Codespace: A Cloud Dev Environment, Not a Host
- npm run dev —host: Why the Flag Gets Swallowed, and the Fix
- Next.js services on RunxBuild
FAQ
What is the difference between next dev and next start?
next dev runs a development server with hot reloading and on-demand compilation. next start serves the optimised output produced by next build and is meant for production. You must run next build before next start.
How do I change the port for next dev?
Use the -p flag, for example next dev -p 4000, or set the PORT environment variable. Use -H to change the bind address if you need access from another device.
Why is next dev slow on the first page load?
Next.js compiles each route on demand, so the first visit to a route compiles it. Later visits are fast. Large import graphs and antivirus scanning of node_modules make it worse.
Why does my app work in next dev but fail after build?
The two modes differ in caching, optimisation, static generation and how environment variables are read. Run next build and next start locally to reproduce production behaviour before deploying.
Can I run next dev in production?
No. It is slower, exposes development overlays, and is not hardened. Use next build and next start, or deploy to a platform that runs them for you.