Tuning Nodemon: Managing Restarts and Watcher Limits
Avoid 'too many open files' errors and restart loops by moving from default nodemon usage to a structured nodemon.json configuration.
14 Jan 2026, 15:53 UTC

The problem: The 'Too Many Open Files' crash
In a small project, running nodemon index.js works perfectly. But as a project grows into a monorepo or includes large directories of assets and documentation, you might encounter a critical failure: the ENOSPC error or a "too many open files" warning. This happens because nodemon, by default, attempts to watch every file in your directory tree, eventually exhausting the operating system's file watcher limits.
Thesis: Strategic configuration prevents watcher exhaustion and restart loops
Nodemon is a process wrapper that spawns your Node.js application as a child process. While its default behavior is convenient, professional engineering requires moving from command-line flags to a nodemon.json configuration. By explicitly defining what to watch and what to ignore, you reduce system overhead and prevent "restart loops"—where the app writes a file that triggers another restart, indefinitely.
Optimizing the Watch List
To stop nodemon from overloading your OS, you must narrow its scope. Instead of watching the root, use a configuration file to ignore heavy directories like node_modules, .git, and build artifacts.
The nodemon.json configuration
Create a nodemon.json file in your project root. This ensures every developer on the team shares the same trigger rules:
{
"ignore": [
"node_modules/*",
"logs/*",
"*.test.js",
"docs/**/*"
],
"ext": "js,json,html",
"exec": "node ./src/server.js"
}
- ignore: A list of glob patterns. Any change within these paths will be ignored by the watcher.
- ext: A comma-separated list of extensions. By default, nodemon only watches
.js,.mjs, and.cjs. Addingjsonorhtmlis essential if your app logic depends on config files or templates. - exec: Defines the exact command to run. This is useful for adding Node.js flags (like
--inspectfor debugging) without changing yourpackage.jsonscripts.
Worked Example: Handling Configuration-Driven Restarts
Imagine an Express application that loads a config.json file at startup. Without specific configuration, changing a value in that JSON file won't trigger a restart, meaning you'll have to manually kill the process to see the new settings.
- Setup: Create the
nodemon.jsonshown above, ensuringjsonis included in theextfield. - Execution: Run the app via terminal (requires
nodemoninstalled as a devDependency):# Run from project root npm run dev - Verification: Open
config.json, change a port number or API key, and save. - Expected Result: The terminal should immediately display:
[nodemon] restarting due to changes...followed by the start sequence of your app.
Trade-offs and Engineering Constraints
While nodemon accelerates development, it introduces specific risks that must be managed:
- OS Limits: On Linux, the
fs.inotify.max_user_watcheslimit is a hard ceiling. If you still see errors after configuringignore, you may need to increase this system-level limit viasysctl. - The Production Trap: Nodemon is strictly for development. Using it in production is dangerous because it adds a layer of process management that can lead to instability or accidental restarts during a deployment sync. Use a dedicated process manager like PM2 or systemd for production.
- Infinite Loops: If your application writes to a file that nodemon is watching (e.g., a
local_db.jsonfile), you will enter a restart loop. Always add your data-writing directories to theignorelist.
Verifying the Setup
To confirm your configuration is working, perform these three checks:
- Positive Test: Edit a
.jsfile; the app should restart. - Negative Test: Edit a file in an
ignoredirectory (e.g.,docs/readme.md); the app should not restart. - Manual Trigger: Type
rsin the terminal while nodemon is running to force a restart without changing any files.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.