$ the-wire · showcase
Recursive fs.watch fallback now watches directories, not files
By RepoJournal · Filed · About Node.js
Node.js overhauled its JavaScript recursive fs.watch fallback on Linux, cutting setup watch handles from 13,501 to 896 and CPU cost per event from ~9 ms to ~2 ms.
Node.js reworked the JavaScript recursive watcher used on platforms without native recursive mode, notably Linux, to watch directories instead of individual files [1]. The old implementation armed an fs.watch() handle and stat() for every file, and answered every event by stat()ing and re-reading the whole directory; a 13k-entry tree cost 13.5k inotify watches, ~150 ms and ~50 MB to set up, and appending to one file in a 3900-entry directory cost ~9 ms of CPU per event [1]. The new implementation arms one watcher per directory and answers each event with a single stat() [2]. In this repository's test/ tree (13,500 entries, 896 directories), setup dropped from ~150 ms and 13,501 handles to ~45 ms and 896 handles, with RSS falling from +52 MB to +20 MB [2]. This is a significant improvement for any recursive watcher deployment on Linux. Additionally, process.permission.has() and drop() now accept a WHATWG URL or a plain Uint8Array as the reference argument, resolving URLs via fileURLToPath() for fs.* scopes [3]. The change also switches permission.cc from Utf8Value to BufferValue when reading a Buffer/TypedArray reference, since Utf8Value forces a UTF-8 conversion that can silently corrupt non-UTF-8 paths [3]. Also, the streams Web Platform Tests were updated to upstream commit 4832db4761, last updated in April 2026, bringing in renamed owning-type tests from .any.js to .tentative.* [4].
Action items
- → Benchmark and profile any recursive fs.watch usage on Linux; expect notable setup and per-event CPU savings with the new fallback nodejs/node [monitor]
- → Review process.permission.has()/drop() call sites for binary or URL references; the new Uint8Array and URL support avoids silent corruption nodejs/node [plan]
References
- [1] fs: watch directories, not files, in recursive fs.watch fallback ↗ nodejs/node
- [2] fs: watch directories, not files, in recursive fs.watch fallback ↗ nodejs/node
- [3] permission: support URL and Uint8Array as has()/drop() reference ↗ nodejs/node
- [4] test: update WPT for streams to 4832db4761 ↗ nodejs/node