For the complete Netlify documentation index, see llms.txt. Markdown versions of any documentation page are available by appending .md to its URL. When you run your project locally with the Netlify CLI, your server runs alongside your frontend, functions, and edge functions.
Locally, your server runs on the same platform code that runs it in production. The entry file is loaded the same way, and it gets the same context and lifecycle. Refer to Differences from production for what isn't the same.
Start the server
Section titled “Start the server”Run the Netlify dev server from the root of your project, using version 27.17.0 or later of the Netlify CLI:
netlify devYour server runs on the version of Node.js installed on your machine. Use Node.js 24 or later, as in production.
The CLI starts your server in its own Node.js process the first time a request needs it, and stops it when the dev server stops.
The Netlify Vite plugin doesn't run your server yet. Use the Netlify CLI instead.
Routing
Section titled “Routing”Locally, requests reach your server in the same order as in production:
- Static files, functions, and edge functions take precedence over your server.
- Your server receives every request that nothing else handles. Locally, this is the case even if it sets
pathorexcludedPath. - WebSocket upgrades reach your server too, so you can test real-time features locally.
Reload on changes
Section titled “Reload on changes”The CLI watches the netlify/server/ directory. When a file in it is added, changed, or removed, the CLI stops the running server and starts a new one with your changes on the next request.
Stopping the server works the same way as shutdown in production. Your process receives SIGTERM, and your shutdown hooks run before it exits. Locally, the whole shutdown, including waiting for requests in progress, has 5 seconds before the process is stopped.
Changes to files outside netlify/server/, such as modules your server imports from elsewhere in your project, don't restart it. Restart netlify dev to pick those up.
Programmatic usage
Section titled “Programmatic usage”The same engine that powers netlify dev is available as the @netlify/dev package, which is useful for end-to-end tests that need your server running with the rest of your project:
npm install --save-dev @netlify/devimport { NetlifyDev } from "@netlify/dev";
const netlifyDev = new NetlifyDev({ projectRoot: "./fixtures/my-project", server: { enabled: true },});
await netlifyDev.start();
// ...run your tests...
await netlifyDev.stop();Differences from production
Section titled “Differences from production”Your server runs on the same platform code locally as in production, with a few differences to keep in mind:
- Locally there is always a single instance, so behavior that depends on several instances running at once, such as in-memory state not being shared between them, doesn't show up.
- Your server's
pathandexcludedPatharen't applied locally, so it receives every request that nothing else handles. - The limits that apply in production, such as how long a request can run, aren't enforced locally.
- The working directory of your server isn't the same locally as in production. Resolve files relative to the module that reads them, for example with
import.meta.dirname, rather than relative toprocess.cwd(). - Shutdown has 5 seconds in total locally, compared to up to 115 seconds in production.
- On Windows, the server process is stopped without receiving
SIGTERM, so your shutdown logic doesn't run locally. - Health check hooks don't run locally, since there's only one instance and no routing between instances to inform.
Did you find this doc useful?
Your feedback helps us improve our docs.