What does the fs module do in Node.js?
1. What the fs module is
fs(File System) is a built-in Node.js module that lets you perform file and folder operations in JavaScript.
It works on top of system APIs (Windows, Linux, macOS) and offers two modes:
- synchronous (blocks the thread),
- asynchronous (via callbacks, promises, or
async/await).
2. Loading the module
In CommonJS:
const fs = require('fs');In ES Modules:
import fs from 'fs';3. Main fs capabilities
| Category | Example methods |
|---|---|
| Reading files | readFile, readFileSync, createReadStream |
| Writing files | writeFile, appendFile, createWriteStream |
| Directory operations | mkdir, readdir, rmdir, rename |
| Deletion | unlink, rm |
| File info | stat, lstat, access, existsSync |
| Copying / moving | copyFile, rename |
| Watching files | watch, watchFile |
4. Examples of common operations
Reading a file (asynchronously)
import fs from 'fs';
fs.readFile('./data.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log('File contents:', data);
});Reading a file (with promises)
The modern way:
import { readFile } from 'fs/promises';
const text = await readFile('./data.txt', 'utf8');
console.log(text);fs/promises is the promise-based version of fs, ideal for async/await.
Writing to a file
import fs from 'fs';
fs.writeFile('./output.txt', 'Hello, Node.js!', (err) => {
if (err) throw err;
console.log('File created!');
});If the file doesn't exist, it gets created. If it does, its content is overwritten.
Appending to the end of a file
import fs from 'fs';
fs.appendFile('./log.txt', 'A new entry\n', (err) => {
if (err) throw err;
console.log('Entry appended!');
});Creating a folder
import fs from 'fs';
fs.mkdir('./uploads', { recursive: true }, (err) => {
if (err) throw err;
console.log('Folder created!');
});{ recursive: true } creates every nested directory that doesn't exist yet.
Reading a directory's contents
import fs from 'fs';
fs.readdir('./', (err, files) => {
if (err) throw err;
console.log('Files in the folder:', files);
});Output:
['app.js', 'package.json', 'data.txt']Deleting a file
import fs from 'fs';
fs.unlink('./output.txt', (err) => {
if (err) throw err;
console.log('File deleted!');
});Getting file information
import fs from 'fs';
fs.stat('./data.txt', (err, stats) => {
if (err) throw err;
console.log('Size:', stats.size);
console.log('Modified:', stats.mtime);
});An example stats object:
Stats {
size: 1024,
isFile: [Function: isFile],
isDirectory: [Function: isDirectory],
mtime: 2025-10-19T10:00:00Z
}5. Streaming reads and writes
For large files, the stream API is a better choice.
Streaming a read:
const readStream = fs.createReadStream('./bigfile.txt', 'utf8');
readStream.on('data', (chunk) => {
console.log('A chunk of the file:', chunk);
});
readStream.on('end', () => {
console.log('Reading finished!');
});Streaming a write:
const writeStream = fs.createWriteStream('./output.txt');
writeStream.write('First line\n');
writeStream.write('Second line\n');
writeStream.end('File written!');Streams are handy for working with huge files, they don't load the whole file into memory.
6. Watching files
fs.watch('./data.txt', (eventType, filename) => {
console.log(`Change: ${eventType} in file ${filename}`);
});Lets you track changes, handy for live reload, logs, hot-reloading servers, and so on.
7. Async vs sync API
Node.js provides both versions for almost every function:
| Async (recommended) | Sync (blocks the thread) |
|---|---|
fs.readFile(path, cb) | fs.readFileSync(path) |
fs.writeFile(path, data, cb) | fs.writeFileSync(path, data) |
fs.mkdir(path, cb) | fs.mkdirSync(path) |
fs.readdir(path, cb) | fs.readdirSync(path) |
Sync methods stop the rest of the code from running, so they're used rarely, for example, at configuration startup.
8. The fs/promises module
The modern alternative:
import { mkdir, readFile, writeFile } from 'fs/promises';
await mkdir('./data', { recursive: true });
await writeFile('./data/info.txt', 'Hello!');
const text = await readFile('./data/info.txt', 'utf8');
console.log(text);It runs entirely on Promise, no callbacks, ideal for async/await.
9. A real-world example
Copying a file:
import { readFile, writeFile } from 'fs/promises';
async function copyFile(src, dest) {
const data = await readFile(src);
await writeFile(dest, data);
console.log('File copied successfully!');
}
await copyFile('./data.txt', './backup.txt');10. Commonly used methods
| Method | Purpose |
|---|---|
readFile(path, [options], callback) | Reading a file |
writeFile(path, data, [options], callback) | Writing a file |
appendFile(path, data, callback) | Appending to the end |
unlink(path, callback) | Deleting a file |
rename(oldPath, newPath, callback) | Renaming |
mkdir(path, [options], callback) | Creating a folder |
readdir(path, callback) | Reading a folder |
stat(path, callback) | File information |
watch(path, listener) | Watching for changes |
In one sentence
The
fsmodule is Node.js's built-in API for working with files and directories (reading, writing, copying, streams, watching), available in both callback and promise form.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.