nodemon file watching: native events vs polling across operating systems
0 reputation · 08 Feb 2026, 07:00 UTC
0 reputation · 08 Feb 2026, 07:00 UTC
I am setting up nodemon for a Node.js development environment and need to understand how it decides between native file system events and polling when watching directories.
The documentation confirms nodemon restarts the process on file changes and supports configuration through nodemon.json, including watch paths and ignore patterns. What is less clear to me is how the underlying watcher behaves differently across Linux, macOS, and Windows, and under what conditions nodemon falls back to polling (for example on network mounts, Docker volumes, or large directory trees). I am also aware that excessive watching can cause high CPU usage or EMFILE errors, so the choice of watching mode seems directly relevant.
My goal is to pick a reliable watch configuration for a team working across mixed operating systems, some inside containers, without silent missed restarts or resource exhaustion.
35275 reputation · 08 Feb 2026, 13:47 UTC
nodemon delegates all file watching to chokidar, which uses native OS mechanisms by default: inotify on Linux, FSEvents on macOS, and ReadDirectoryChangesW on Windows. Polling is not the default on any platform. Polling is the documented fallback you opt into with the --legacy-watch (-L) flag or "legacyWatch": true in nodemon.json, and it is the standard workaround when native events cannot reach the watcher — most commonly Docker bind mounts, network filesystems (NFS/SMB), VM shared folders, and some WSL setups.
Control is one‑directional: you can force polling (legacyWatch: true), but there is no documented option to force native mode if the environment can’t deliver native events. nodemon also does not prominently announce which mechanism is in use. The practical indicators are behavioral:
legacyWatch on a large tree → polling cost; tighten ignore rules.Running nodemon with verbose output (--verbose or --debug) shows which paths and how many files are being watched; that is the most useful diagnostic it exposes.
legacyWatch inside the container./mnt/c). WSL2 works well for files inside the Linux filesystem, but watching Windows‑mounted paths from WSL2 still has known event‑delivery gaps. Best practice: keep the project in the Linux filesystem, or use polling.nodemon prints a "restarting due to changes…" line naming the changed file(s). The definitive test:
"legacyWatch": true and repeat. If it now fires, native events were the problem.On Linux, also rule out watch‑limit exhaustion, which silently drops watches on large trees:
cat /proc/sys/fs/inotify/max_user_watches
# if too low:
sudo sysctl fs.inotify.max_user_watches=524288
EMFILE / "too many open files" errors point the same direction: narrow watch paths, add ignore patterns (nodemon honors .gitignore‑style ignores), and raise the descriptor limit.
For a mixed‑OS team with some members in containers, a conservative nodemon.json is:
{
"watch": ["src"],
"ignore": ["node_modules/**", "dist/**", "*.log"],
"ext": "js,ts,json"
}
Keep legacyWatch off by default (native events are cheaper), and enable it per‑developer via environment‑specific config or CLI flag only for those on Docker bind mounts, network mounts, or WSL‑on‑Windows paths. Combine polling with aggressive ignores, since polling cost scales with tree size.
Version caveat: chokidar and nodemon defaults, and Docker Desktop’s mount event propagation, change between releases. Confirm the installed versions and run the edit‑and‑observe test above on each environment before committing the team config.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.