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?

ApproachProsCons
Local (recommended)Version locked per project; works in CI; explicit dependencyMust use npx or npm script
GlobalNo npx needed; quick to useVersion 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

OptionTypeDefaultDescription
watchArray of strings["."] (current directory)Directories and files to watch
extString"js,mjs,cjs,json"File extensions to watch (comma-separated)
ignoreArray of strings["node_modules"]Paths to ignore
delayNumber (ms) or String0Delay before restarting (debounce)
envObject{}Environment variables to set
execString"node"Command to execute
verboseBooleanfalseExtra logging output
signalString"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.json equivalent 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

ToolInstall RequiredTypeScriptConfigurationStability
nodemonYes (npm)Via --exec ts-nodeExtensive (nodemon.json)Very stable
node --watchNo (built-in)NoMinimal (CLI flags)Stable (Node 18.11+)
tsx watchYes (npm)NativeMinimalStable
ts-node-devYes (npm)NativeModerateStable

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 .ejs templates).
  • 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 --exec with 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

  1. Without auto-restart tools, you must manually stop and restart the server after every code change — a massive productivity drain.
  2. Nodemon watches your files and restarts the server automatically on save.
  3. Install nodemon as a dev dependency (npm install -D nodemon) and add a "dev" script to package.json.
  4. Configure with nodemon.json for watch paths, ignored paths, extensions, delays, and environment variables.
  5. Use --ext, --ignore, --watch, and --delay flags for quick command-line configuration.
  6. node --watch (Node.js 18.11+) is a built-in alternative that works for simple projects.
  7. For TypeScript, consider tsx watch or nodemon --exec ts-node.
  8. Watch out for infinite restart loops — ignore directories where your server writes files.
  9. Always use npm run dev for development and npm start for production.

Explain-It Challenge

Setup challenge: Create a new Node.js project from scratch with the following requirements:

  1. A src/ directory with server.js that serves different JSON responses for /, /api/health, and /api/time.
  2. A nodemon.json that watches only the src/ directory, ignores test files, and has a 500ms delay.
  3. A package.json with both start and dev scripts.
  4. Test that changing any file in src/ triggers an automatic restart.
  5. 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