Episode 3 — NodeJS MongoDB Backend Architecture / 3.2 — Creating Server
3.2.f — Nodemon for Development
Nodemon automatically restarts your Node.js server whenever you save a file, eliminating the tedious cycle of stopping and restarting your server during development.
Navigation: ← 3.2 Overview | Next → 3.2 Exercise Questions
1. The Problem: Restarting the Server Manually
When developing a Node.js server, every code change requires a restart.
# The painful workflow without nodemon:
node server.js # Start server
# Make a change to server.js
# Ctrl+C # Stop server
node server.js # Restart server
# Make another change
# Ctrl+C # Stop again
node server.js # Restart again
# ... repeat 200 times per day
This is not just annoying — it breaks your flow. You make a change, switch to the terminal, press Ctrl+C, press up arrow, press Enter, switch back to the editor... every single time.
Nodemon solves this. It watches your files and restarts the server automatically when anything changes.
# With nodemon:
npx nodemon server.js # Start once
# Make changes → server restarts automatically
# Make more changes → server restarts automatically
# Never touch the terminal again (until you're done)
2. Installing Nodemon
Option 1: Project dependency (recommended)
Install as a development dependency — only needed during development, not in production.
npm install --save-dev nodemon
# or
npm install -D nodemon
This adds it to your package.json:
{
"devDependencies": {
"nodemon": "^3.1.0"
}
}
Run it using npx:
npx nodemon server.js
Option 2: Global installation
Install once, use in any project without npx.
npm install -g nodemon
Run it directly:
nodemon server.js
Which to choose?
| Approach | Pros | Cons |
|---|---|---|
| Local (recommended) | Version locked per project; works in CI; explicit dependency | Must use npx or npm script |
| Global | No npx needed; quick to use | Version not locked; not listed in package.json; may conflict between projects |
Best practice: Install locally and use npm scripts (covered next).
3. Configuring in package.json Scripts
The most common setup is adding a dev script to your package.json.
{
"name": "my-server",
"version": "1.0.0",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
},
"devDependencies": {
"nodemon": "^3.1.0"
}
}
Running the scripts
# Production: runs with plain node (no auto-restart)
npm start
# Development: runs with nodemon (auto-restart on changes)
npm run dev
Why npm start does not need run but dev does
start is a special npm script — you can run it with just npm start. All other custom scripts require npm run <name>.
npm start # Works (special script)
npm run start # Also works
npm run dev # Required for custom scripts
npm dev # Does NOT work
Common script patterns
{
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
"dev:debug": "nodemon --inspect server.js",
"test": "jest",
"test:watch": "jest --watch"
}
}
4. What Nodemon Does When It Runs
$ npm run dev
> my-server@1.0.0 dev
> nodemon server.js
[nodemon] 3.1.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,cjs,json
[nodemon] starting `node server.js`
Server running on http://localhost:3000
Now when you edit and save any .js, .mjs, .cjs, or .json file:
[nodemon] restarting due to changes...
[nodemon] starting `node server.js`
Server running on http://localhost:3000
Manual restart
Type rs and press Enter in the terminal to force a restart without changing any files.
rs
[nodemon] starting `node server.js`
5. nodemon.json Configuration
For advanced settings, create a nodemon.json file in your project root.
Basic configuration
{
"watch": ["src", "config"],
"ext": "js,json,ejs,html",
"ignore": ["node_modules", "logs", "public/uploads"],
"delay": 1000,
"env": {
"NODE_ENV": "development",
"PORT": "3000"
}
}
Configuration options explained
| Option | Type | Default | Description |
|---|---|---|---|
watch | Array of strings | ["."] (current directory) | Directories and files to watch |
ext | String | "js,mjs,cjs,json" | File extensions to watch (comma-separated) |
ignore | Array of strings | ["node_modules"] | Paths to ignore |
delay | Number (ms) or String | 0 | Delay before restarting (debounce) |
env | Object | {} | Environment variables to set |
exec | String | "node" | Command to execute |
verbose | Boolean | false | Extra logging output |
signal | String | "SIGUSR2" | Kill signal to send to process |
Comprehensive example
{
"watch": [
"src/",
"config/",
".env"
],
"ext": "js,json,ejs,html,css",
"ignore": [
"node_modules/",
"logs/",
"*.test.js",
"public/uploads/",
"coverage/"
],
"delay": 500,
"env": {
"NODE_ENV": "development",
"DEBUG": "app:*"
},
"verbose": true,
"exec": "node --inspect"
}
Alternative: configure in package.json
Instead of a separate file, you can add a nodemonConfig key to package.json:
{
"name": "my-server",
"scripts": {
"dev": "nodemon server.js"
},
"nodemonConfig": {
"watch": ["src"],
"ext": "js,json",
"ignore": ["tests/"]
}
}
6. Command-Line Flags
You can also configure nodemon directly from the command line.
--ext — Watch specific file types
# Watch only .js and .json files
nodemon --ext js,json server.js
# Watch JS, HTML, and EJS template files
nodemon --ext js,json,html,ejs server.js
--ignore — Exclude directories or files
# Ignore the tests directory
nodemon --ignore tests/ server.js
# Ignore multiple directories
nodemon --ignore tests/ --ignore logs/ server.js
# Ignore specific files
nodemon --ignore config/secrets.json server.js
--watch — Specify directories to watch
# Only watch the src directory
nodemon --watch src server.js
# Watch multiple directories
nodemon --watch src --watch config server.js
--delay — Add restart delay
# Wait 2 seconds before restarting (useful if files save in batches)
nodemon --delay 2 server.js
# 500 milliseconds
nodemon --delay 500ms server.js
--exec — Use a different executor
# Run with TypeScript using ts-node
nodemon --exec ts-node src/server.ts
# Run with the Node.js inspector
nodemon --exec "node --inspect" server.js
# Run a Python script (nodemon works with any language!)
nodemon --exec python app.py --ext py
--inspect — Enable Node.js debugger
# Start with debug port open
nodemon --inspect server.js
# Debug on a specific port
nodemon --inspect=9229 server.js
Complete command example
nodemon \
--watch src \
--watch config \
--ext js,json,ejs \
--ignore "src/tests/" \
--delay 1000 \
server.js
7. Alternatives to Nodemon
node --watch (Node.js 18.11+)
Node.js now has a built-in watch mode. No installation needed.
# Basic watch mode
node --watch server.js
# Watch and also restart on unhandled exceptions
node --watch-path=./src server.js
Advantages:
- Zero installation — built into Node.js.
- Simpler — no configuration file needed.
- Faster startup.
Limitations:
- Cannot ignore specific files/directories easily.
- Cannot watch specific extensions.
- Cannot set a restart delay.
- No
nodemon.jsonequivalent for configuration. - Still marked as experimental in some Node.js versions.
tsx watch (for TypeScript projects)
# Install tsx
npm install -D tsx
# Run with watch mode
npx tsx watch src/server.ts
Advantages:
- Runs TypeScript directly (no separate compile step).
- Fast — uses esbuild under the hood.
ts-node-dev (for TypeScript projects)
npm install -D ts-node-dev
npx tsnd --respawn src/server.ts
Comparison table
| Tool | Install Required | TypeScript | Configuration | Stability |
|---|---|---|---|---|
| nodemon | Yes (npm) | Via --exec ts-node | Extensive (nodemon.json) | Very stable |
| node --watch | No (built-in) | No | Minimal (CLI flags) | Stable (Node 18.11+) |
| tsx watch | Yes (npm) | Native | Minimal | Stable |
| ts-node-dev | Yes (npm) | Native | Moderate | Stable |
8. When to Use Nodemon vs node --watch
Use node --watch when:
- You have a simple project with few files.
- You do not need to ignore specific paths.
- You do not need to watch non-JS file types (like
.ejstemplates). - You want zero additional dependencies.
- You are using Node.js 18.11 or later.
Use nodemon when:
- You need fine-grained control over watched paths and ignored paths.
- You need to watch non-JS extensions (
.ejs,.html,.css). - You need a restart delay.
- You need environment variables set automatically.
- You want to use
--execwith a different runtime (ts-node,python). - You are working on a team project that needs consistent configuration via
nodemon.json.
Quick decision
Simple project, only .js files, Node 18+? → node --watch
Everything else? → nodemon
TypeScript project? → tsx watch or nodemon + ts-node
9. Troubleshooting Common Issues
Issue 1: Nodemon not detecting changes
# Verify what nodemon is watching
nodemon --verbose server.js
# Check if your file is in an ignored directory
# Check if your file extension is being watched
Issue 2: Infinite restart loop
This happens when your server writes to a file that nodemon is watching.
# Solution: ignore the output directory
nodemon --ignore logs/ --ignore data/ server.js
Or in nodemon.json:
{
"ignore": ["logs/*", "data/*", "*.log"]
}
Issue 3: Port already in use after restart
Sometimes the old process does not shut down before the new one starts.
# Add a delay
nodemon --delay 1000 server.js
Or handle graceful shutdown in your code:
const server = http.createServer(/* ... */);
server.listen(3000);
// Graceful shutdown
process.on('SIGTERM', () => {
console.log('Shutting down gracefully...');
server.close(() => {
console.log('Server closed');
process.exit(0);
});
});
Issue 4: Nodemon restarting too many times
Multiple rapid saves can cause multiple restarts.
{
"delay": 1000
}
This waits 1 second after the last change before restarting.
10. Recommended Development Setup
Here is a complete recommended setup for a new Node.js project:
Step 1: Initialize the project
mkdir my-server && cd my-server
npm init -y
npm install -D nodemon
Step 2: package.json
{
"name": "my-server",
"version": "1.0.0",
"main": "src/server.js",
"scripts": {
"start": "node src/server.js",
"dev": "nodemon src/server.js"
},
"devDependencies": {
"nodemon": "^3.1.0"
}
}
Step 3: nodemon.json
{
"watch": ["src"],
"ext": "js,json",
"ignore": ["src/tests", "*.test.js"],
"delay": 500
}
Step 4: src/server.js
const http = require('http');
const PORT = process.env.PORT || 3000;
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Server is running!' }));
});
server.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
Step 5: Start developing
npm run dev
Now every time you save a file in the src/ directory, the server restarts automatically.
Key Takeaways
- Without auto-restart tools, you must manually stop and restart the server after every code change — a massive productivity drain.
- Nodemon watches your files and restarts the server automatically on save.
- Install nodemon as a dev dependency (
npm install -D nodemon) and add a"dev"script topackage.json. - Configure with
nodemon.jsonfor watch paths, ignored paths, extensions, delays, and environment variables. - Use
--ext,--ignore,--watch, and--delayflags for quick command-line configuration. node --watch(Node.js 18.11+) is a built-in alternative that works for simple projects.- For TypeScript, consider
tsx watchornodemon --exec ts-node. - Watch out for infinite restart loops — ignore directories where your server writes files.
- Always use
npm run devfor development andnpm startfor production.
Explain-It Challenge
Setup challenge: Create a new Node.js project from scratch with the following requirements:
- A
src/directory withserver.jsthat serves different JSON responses for/,/api/health, and/api/time. - A
nodemon.jsonthat watches only thesrc/directory, ignores test files, and has a 500ms delay. - A
package.jsonwith bothstartanddevscripts. - Test that changing any file in
src/triggers an automatic restart. - Test that changing a file outside
src/does NOT trigger a restart.
Then explain to a study partner: what is the difference between npm start and npm run dev? When would you use each? Why should nodemon never be used in production?
Navigation: ← 3.2 Overview | Next → 3.2 Exercise Questions