
Workflow with Nodemon – Auto Restarting Node.js Apps
Every Node.js developer has been there – frantically hitting Ctrl+C and running node app.js
for the hundredth time after making a small change to their code. If you’re setting up Node.js applications on servers or developing locally, you’ll quickly realize that manually restarting your app every time you make changes is about as fun as watching paint dry. This workflow guide will show you how Nodemon transforms your development and server management experience by automatically restarting your Node.js applications whenever file changes are detected. Whether you’re running a production server, staging environment, or just want to streamline your local development, mastering Nodemon will save you countless hours and significantly reduce the chance of forgetting to restart your app after critical updates.
How Does Nodemon Actually Work?
Nodemon is essentially a wrapper around your Node.js application that monitors your file system for changes. Under the hood, it uses the fs.watch()
API (or fs.watchFile()
as a fallback) to detect when files are modified, added, or deleted. When a change is detected, Nodemon gracefully terminates the current Node.js process and spawns a new one with the same arguments.
Here’s what happens in the lifecycle:
- Initial startup: Nodemon spawns your Node.js application as a child process
- File monitoring: It watches specified directories (current directory by default) for changes
- Change detection: When a file change occurs, Nodemon captures the event
- Graceful shutdown: It sends a SIGTERM signal to the child process, allowing for cleanup
- Process restart: After the old process exits, a new instance is spawned
The beauty of this approach is that it’s completely transparent to your application code – you don’t need to modify anything in your existing Node.js app. Nodemon works with any Node.js application, whether it’s an Express server, a CLI tool, or a background worker.
Setting Up Nodemon: From Zero to Hero
Let’s get Nodemon up and running with a practical, step-by-step approach. I’ll show you both local development and server deployment scenarios.
Installation Options
You can install Nodemon globally or locally. Here’s when to use each approach:
# Global installation (great for development machines)
npm install -g nodemon
# Local installation (recommended for projects and servers)
npm install --save-dev nodemon
# Using yarn
yarn add --dev nodemon
For server environments, I strongly recommend local installation. It ensures version consistency across your team and deployment environments.
Basic Usage
Once installed, using Nodemon is straightforward:
# Instead of: node app.js
nodemon app.js
# Or if installed locally
npx nodemon app.js
# With npm scripts (add to package.json)
npm run dev
Here’s a sample package.json
setup:
{
"name": "my-node-app",
"version": "1.0.0",
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js",
"server": "nodemon --inspect app.js"
},
"devDependencies": {
"nodemon": "^3.0.1"
}
}
Advanced Configuration
Create a nodemon.json
file in your project root for advanced configuration:
{
"watch": ["src", "lib"],
"ext": "js,json,ts",
"ignore": ["node_modules", "dist", "logs"],
"exec": "node --inspect app.js",
"env": {
"NODE_ENV": "development"
},
"delay": 1000,
"verbose": true,
"restartable": "rs"
}
Let me break down these options:
- watch: Specific directories to monitor
- ext: File extensions to watch (comma-separated)
- ignore: Paths to ignore (supports wildcards)
- exec: Command to execute instead of default node
- env: Environment variables to set
- delay: Milliseconds to wait before restarting
- verbose: Show detailed output
- restartable: String to type to manually restart
Real-World Examples and Use Cases
Scenario 1: Express API Development
Here’s a typical Express setup with Nodemon:
// app.js
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/api/health', (req, res) => {
res.json({ status: 'OK', timestamp: new Date().toISOString() });
});
app.get('/api/users', (req, res) => {
// Your API logic here
res.json({ users: [] });
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
// Graceful shutdown handling
process.on('SIGTERM', () => {
console.log('Received SIGTERM, shutting down gracefully');
process.exit(0);
});
Configuration for this setup:
{
"watch": ["routes", "middleware", "models"],
"ext": "js,json",
"ignore": ["node_modules", "public", "uploads"],
"env": {
"NODE_ENV": "development",
"DEBUG": "app:*"
}
}
Scenario 2: TypeScript Project
For TypeScript projects, you’ll need to compile and run:
{
"watch": ["src"],
"ext": "ts,json",
"ignore": ["dist", "node_modules"],
"exec": "ts-node src/index.ts",
"env": {
"NODE_ENV": "development"
}
}
Scenario 3: Production-like Server Setup
When setting up a staging server that mimics production but still needs auto-restart capability:
# Install PM2 and Nodemon
npm install -g pm2
npm install --save-dev nodemon
# ecosystem.config.js for PM2
module.exports = {
apps: [{
name: 'my-app-dev',
script: 'nodemon',
args: 'app.js',
watch: true,
ignore_watch: ['node_modules', 'logs'],
instances: 1,
env: {
NODE_ENV: 'development'
}
}]
};
# Start with PM2
pm2 start ecosystem.config.js
Performance Comparison: Manual vs Nodemon vs PM2
Feature | Manual Restart | Nodemon | PM2 + Nodemon |
---|---|---|---|
Development Speed | Slow ❌ | Fast ✅ | Fast ✅ |
Memory Usage | Low | Medium | Higher |
Process Management | Manual ❌ | Basic ✅ | Advanced ✅ |
Production Ready | Yes | No ❌ | Yes ✅ |
Learning Curve | None | Easy | Moderate |
Common Pitfalls and Solutions
❌ Problem: Nodemon restarts too frequently due to log files being written
✅ Solution: Add log directories to ignore list
{
"ignore": ["node_modules", "logs", "*.log", "uploads", "tmp"]
}
❌ Problem: Application doesn’t shut down gracefully, causing port conflicts
✅ Solution: Implement proper signal handling
// Graceful shutdown
const server = app.listen(PORT);
process.on('SIGTERM', () => {
console.log('SIGTERM received, shutting down gracefully');
server.close(() => {
console.log('Process terminated');
});
});
❌ Problem: High CPU usage on large projects
✅ Solution: Be specific about watch directories and add delay
{
"watch": ["src"],
"ignore": ["node_modules", "dist", "coverage"],
"delay": 2000
}
Advanced Integrations and Automation
Docker Integration
Using Nodemon in Docker containers for development:
# Dockerfile.dev
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
# Install nodemon globally for development
RUN npm install -g nodemon
COPY . .
EXPOSE 3000
CMD ["nodemon", "app.js"]
# docker-compose.yml
version: '3.8'
services:
web:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
Integration with Testing Frameworks
Combine Nodemon with test watchers for continuous testing:
{
"scripts": {
"dev": "nodemon app.js",
"test:watch": "nodemon --exec 'npm test'",
"test:integration": "nodemon --exec 'npm run test:integration' --ext js,json"
}
}
Custom Event Handlers
You can create custom scripts that run on specific Nodemon events:
{
"events": {
"restart": "echo 'App restarted due to file changes'",
"crash": "echo 'App crashed, restarting...'",
"start": "echo 'App started'"
}
}
Webhook Integration
For advanced deployment scenarios, you might want to trigger deployments when local changes occur:
{
"events": {
"restart": "curl -X POST https://your-webhook-url.com/deploy -d '{\"event\":\"restart\"}'"
}
}
Related Tools and Ecosystem
Nodemon works great with these complementary tools:
- Chokidar: The file watching library that powers Nodemon
- PM2: Production process manager that can work with Nodemon for development
- Forever: Alternative to PM2, lighter weight
- Supervisor: Python-based process manager, good for polyglot environments
Performance Statistics
Based on community benchmarks and personal testing:
- File detection latency: ~50-200ms depending on system
- Restart time: 500ms-2s depending on application complexity
- Memory overhead: ~10-20MB additional RAM usage
- CPU overhead: Negligible during normal operation, 2-5% during file scanning
Server Deployment Considerations
When deploying to servers, you have several hosting options. For VPS deployments where you need full control over your Node.js environment, consider a reliable VPS hosting solution that gives you root access to install and configure Nodemon properly. For high-traffic applications requiring maximum performance and dedicated resources, a dedicated server provides the best environment for running Node.js applications with custom monitoring and restart mechanisms.
Production Alternatives
While Nodemon is perfect for development, here are production-ready alternatives:
# PM2 for production
pm2 start app.js --name "my-app" --instances max
# systemd service (Linux)
sudo systemctl enable my-node-app
sudo systemctl start my-node-app
# Docker with restart policies
docker run -d --restart=unless-stopped my-node-app
Conclusion and Recommendations
Nodemon is an indispensable tool for Node.js developers and server administrators who want to streamline their development workflow. Here’s when and how to use it effectively:
✅ Use Nodemon when:
- Developing Node.js applications locally
- Setting up staging environments that need automatic restarts
- Running development servers on remote machines
- Working with APIs that require frequent testing
- Building microservices that need rapid iteration
❌ Avoid Nodemon for:
- Production environments (use PM2, systemd, or Docker instead)
- Applications with very long startup times (>30 seconds)
- Systems with limited resources where every MB counts
- Applications that don’t handle SIGTERM gracefully
Best Practices Summary:
- Always install locally in projects rather than globally on servers
- Configure proper ignore patterns to avoid unnecessary restarts
- Implement graceful shutdown handling in your applications
- Use specific watch directories for better performance
- Combine with other tools like PM2 for more advanced deployment scenarios
- Set appropriate delays for file-heavy applications
The productivity gains from using Nodemon are immediate and significant. You’ll spend less time on mundane restart tasks and more time actually building features. For server environments, the combination of proper configuration and deployment tools creates a robust development and staging pipeline that closely mirrors production while maintaining the convenience of automatic restarts.
Start with the basic setup, gradually add configuration as your needs grow, and don’t forget to plan your production deployment strategy early. Your future self (and your team) will thank you for taking the time to set this up properly.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.