Introduction
The fs (File System) module is a core Node.js module that provides an API for interacting with the file system. It lets you read, write, update, delete, and watch files and directories. Node exposes three styles of API for almost every operation: synchronous (blocking), asynchronous with callbacks (non-blocking), and promise-based via fs.promises (non-blocking, works with async/await). Choosing the right style matters for performance and code readability.
Cricket analogy: The fs module is like the groundskeeper who can prepare, alter, and remove parts of the pitch; you can do it while play is paused (sync), during a break with a callback for the umpire, or via a scheduled promise for later.
Syntax
const fs = require('fs');
const fsPromises = require('fs/promises'); // or fs.promises
// Synchronous
const dataSync = fs.readFileSync('file.txt', 'utf8');
// Callback-based (asynchronous)
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// Promise-based (asynchronous)
async function readIt() {
const data = await fsPromises.readFile('file.txt', 'utf8');
console.log(data);
}Explanation
fs.readFileSync blocks the event loop until the file is fully read, which is fine for startup scripts but harmful in a server handling concurrent requests. fs.readFile takes an error-first callback that fires once the read completes, keeping the event loop free. fs.promises.readFile returns a Promise, so it can be awaited inside an async function for cleaner, sequential-looking code without blocking. The same three styles exist for writeFile, appendFile, unlink (delete), mkdir, readdir, stat, and most other fs operations.
Cricket analogy: readFileSync is like stopping the whole match to check one player's stats sheet before play resumes; readFile with a callback is like a runner fetching stats while play continues and reporting back when ready; promises are like awaiting that runner's report cleanly in the commentary script.
Example
const fs = require('fs');
const fsPromises = require('fs/promises');
// Write then read using promises
async function writeAndRead() {
await fsPromises.writeFile('notes.txt', 'Hello Node.js fs module!');
const content = await fsPromises.readFile('notes.txt', 'utf8');
console.log('File content:', content);
const stats = await fsPromises.stat('notes.txt');
console.log('Is file:', stats.isFile());
console.log('Size in bytes:', stats.size);
}
writeAndRead().catch(console.error);Output
Running the example creates a file named notes.txt containing the text, then logs: 'File content: Hello Node.js fs module!', 'Is file: true', and 'Size in bytes: 25' (the exact byte count of the written string). If writeAndRead's promise rejects (for example due to missing permissions), the .catch(console.error) prints the error instead.
Cricket analogy: It's like a scorer writing 'Player run out' into the book, then reading back 'Score: 25 runs off 30 balls' and 'File exists: true' as confirmation the entry was saved correctly, with an error path if the scorebook was locked.
Key Takeaways
- fs.readFileSync/writeFileSync are synchronous and block the event loop; avoid them in server request handlers.
- fs.readFile/writeFile use error-first callbacks and are non-blocking.
- fs.promises (or require('fs/promises')) returns Promises, enabling clean async/await syntax.
- fs.stat/fsPromises.stat return metadata like file size and whether the path is a file or directory.
- Always handle errors — missing files, permission issues, and disk errors are common in real applications.
Practice what you learned
1. Which fs method blocks the Node.js event loop until it completes?
2. How do you access the promise-based version of the fs module?
3. What pattern does fs.readFile use to report success or failure?
4. Which method would you use to get metadata such as file size?
Was this page helpful?
You May Also Like
The path Module in Node.js
Understand how to build, parse, and normalize file system paths cross-platform using Node's built-in path module.
Streams in Node.js
Processing data piece by piece with Readable, Writable, Duplex, and Transform streams, including backpressure handling.
Promises in Node.js
Understanding the Promise object and its pending, fulfilled, and rejected states for cleaner async code.
Async/Await in Node.js
Writing asynchronous code that reads like synchronous code using the async/await syntax built on Promises.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics