The Node fs module
By Flavio Copes
A guide to the Node.js fs module and its methods for working with the file system, from readFile and writeFile to rename, plus their blocking Sync versions.
The fs module provides a lot of very useful functionality to access and interact with the file system.
There is no need to install it. Being part of the Node core, you import it:
import fs from 'node:fs'
CommonJS still works with require('fs') or require('node:fs'). Prefer the node: prefix so the import is clearly a built-in module.
Once you do so, you have access to all its methods, which include:
fs.access(): check if the file exists and Node can access it with its permissionsfs.appendFile(): append data to a file. If the file does not exist, it’s createdfs.chmod(): change the permissions of a file specified by the filename passed. Related:fs.lchmod(),fs.fchmod()fs.chown(): change the owner and group of a file specified by the filename passed. Related:fs.fchown(),fs.lchown()fs.close(): close a file descriptorfs.copyFile(): copies a filefs.createReadStream(): create a readable file streamfs.createWriteStream(): create a writable file streamfs.link(): create a new hard link to a filefs.mkdir(): create a new folderfs.mkdtemp(): create a temporary directoryfs.open(): set the file modefs.readdir(): read the contents of a directoryfs.readFile(): read the content of a file. Related:fs.read()fs.readlink(): read the value of a symbolic linkfs.realpath(): resolve relative file path pointers (.,..) to the full pathfs.rename(): rename a file or folderfs.rmdir(): remove a folderfs.stat(): returns the status of the file identified by the filename passed. Related:fs.fstat(),fs.lstat()fs.symlink(): create a new symbolic link to a filefs.truncate(): truncate to the specified length the file identified by the filename passed. Related:fs.ftruncate()fs.unlink(): remove a file or a symbolic linkfs.unwatchFile(): stop watching for changes on a filefs.utimes(): change the timestamp of the file identified by the filename passed. Related:fs.futimes()fs.watchFile(): start watching for changes on a file. Related:fs.watch()fs.writeFile(): write data to a file. Related:fs.write()
One peculiar thing about the fs module is that all the methods are asynchronous by default, but they can also work synchronously by appending Sync.
For example:
fs.rename()fs.renameSync()fs.write()fs.writeSync()
This makes a huge difference in your application flow.
For new code, prefer the promise API from node:fs/promises. It has been stable for years (Node 24 LTS and Node 26 Current included). See also reading files and writing files with Node.
For example let’s examine the fs.rename() method. The promise API looks like this:
import { rename } from 'node:fs/promises'
try {
await rename('before.json', 'after.json')
//done
} catch (err) {
console.error(err)
}
The older callback API still works:
import fs from 'node:fs'
fs.rename('before.json', 'after.json', (err) => {
if (err) {
return console.error(err)
}
//done
})
A synchronous API can be used like this, with a try/catch block to handle errors:
import fs from 'node:fs'
try {
fs.renameSync('before.json', 'after.json')
//done
} catch (err) {
console.error(err)
}
The key difference here is that the execution of your script will block in the Sync example, until the file operation succeeded. The promise and callback versions keep the event loop free while the filesystem work runs.
Want me to talk about your product? You can sponsor this site.
Related posts about node: