File System Operations: Sync, Async & Promises API (fs/promises)0%
EventEmitter Pattern & Custom Event Architecture

File System Operations: Sync, Async & Promises API (fs/promises)

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

File System Operations: Sync, Async & Promises API (fs/promises)

File system manipulation is a daily responsibility for backend engineers: reading configurations, saving user uploads, processing log files, and streaming large datasets. Node.js provides three distinct flavors of the fs (File System) module: Synchronous, Callback-based Asynchronous, and Promises-based Asynchronous (fs/promises).


1. The Three fs API Flavors

1. Synchronous (fs.readFileSync) - AVOID IN REQUEST HANDLERS

Blocks the entire Event Loop until the disk read finishes. Permissible ONLY during initial server boot to load config files.

JavaScript
// DO NOT DO THIS inside an Express route handler!
const data = fs.readFileSync('/var/log/system.log', 'utf8');

2. Callback-based (fs.readFile)

The historical Node.js pattern; executes asynchronously without blocking the main thread.

JavaScript
fs.readFile('./config.json', 'utf8', (err, data) => {
if (err) return console.error('Read failed:', err);
console.log('Config:', JSON.parse(data));
});

Clean, modern, fully non-blocking, and seamlessly integrated with async / await:

JavaScript
import fs from 'node:fs/promises';
import path from 'node:path';
 
async function manageUserData(user) {
const filePath = path.join(process.cwd(), 'data', `user-${user.id}.json`);
 
// 1. Write file with pretty-printed JSON
await fs.writeFile(filePath, JSON.stringify(user, null, 2), 'utf8');
 
// 2. Read file back
const rawData = await fs.readFile(filePath, 'utf8');
const parsedUser = JSON.parse(rawData);
 
// 3. Append to activity log
await fs.appendFile(
path.join(process.cwd(), 'data', 'activity.log'),
`[${new Date().toISOString()}] User ${user.id} updated\n`
);
 
return parsedUser;
}

2. Directory and Metadata Operations

Node.js offers complete control over file system trees and permissions:

JavaScript
import fs from 'node:fs/promises';
 
async function fileOperationsDemo() {
// Check if directory exists; create recursively if missing
await fs.mkdir('./uploads/avatars', { recursive: true });
 
// Inspect file metadata (size, creation time, permissions)
const stats = await fs.stat('./package.json');
console.log('File size in bytes:', stats.size);
console.log('Is directory?', stats.isDirectory());
console.log('Last modified:', stats.mtime);
 
// Read all files in a directory
const files = await fs.readdir('./src');
console.log('Source files:', files);
 
// Safely delete a file
await fs.unlink('./temp.txt').catch(err => {
if (err.code !== 'ENOENT') throw err; // Ignore if file already doesn't exist
});
}

Interactive Quiz

Multiple Choice Questions

Question 1
Which Node.js file system API is the modern industry standard for use with async/await?
Question 2
Why is using synchronous methods like fs.readFileSync() considered a critical anti-pattern inside an Express.js route handler?
Question 3
How do you create nested directories (e.g., uploads/2026/invoices) without throwing an error if intermediate parent directories do not exist?
Question 4
What does the fs.stat() method return?
Question 5
Which method from fs/promises deletes a file from the file system?

Next Lesson

EventEmitter Pattern & Custom Event Architecture

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext