Master Code
On The Go

Learn. Practice. Build.

Home › How-To › fs Module Guide

Node.js Guide

Node.js fs Module — Complete Guide

Every file operation you'll ever need: reading, writing, appending, deleting, watching, and manipulating paths.

Quick answer: Import fs/promises for async operations (await fs.readFile) — that's the modern default. Use plain fs only for sync operations like fs.readFileSync in startup scripts.

1

The Three APIs

// Sync (blocks — use in scripts)
const fs = require('fs');
fs.readFileSync('file.txt', 'utf8');

// Callback (old style — avoid in new code)
fs.readFile('file.txt', 'utf8', (err, data) => { ... });

// Promises (modern — use this)
const fs = require('fs/promises');
await fs.readFile('file.txt', 'utf8');

// Or with ES Modules
import { readFile } from 'fs/promises';
2

Reading Files

import { readFile } from 'fs/promises';

// Read as text
const text = await readFile('./notes.txt', 'utf8');

// Read as Buffer (binary)
const buffer = await readFile('./image.png');

// Sync version
import { readFileSync } from 'fs';
const text = readFileSync('./notes.txt', 'utf8');
3

Writing Files

import { writeFile } from 'fs/promises';

// Overwrites the file if it exists
await writeFile('./output.txt', 'Hello, Node!');

// With explicit encoding
await writeFile('./output.txt', 'Hello, Node!', 'utf8');

// Append instead of overwrite
import { appendFile } from 'fs/promises';
await appendFile('./log.txt', 'New log entry\n');

💡 Warn: writeFile overwrites silently. To append, use appendFile.

4

File Info & Checks

import { stat, access, existsSync } from 'fs';
import { constants } from 'fs';

// Check if a file exists (sync)
if (existsSync('./config.json')) {
    console.log('Config found');
}

// Get file info
const stats = await stat('./notes.txt');
console.log(stats.size);         // size in bytes
console.log(stats.isFile());     // true
console.log(stats.isDirectory()); // false
console.log(stats.mtime);        // last modified

// Check access permissions
await access('./notes.txt', constants.R_OK | constants.W_OK);
5

Directories

import { mkdir, readdir, rmdir, rm } from 'fs/promises';

// Create a directory (with parents)
await mkdir('./uploads/users', { recursive: true });

// List directory contents
const files = await readdir('./src');
console.log(files);   // ['index.js', 'utils.js']

// Delete empty directory
await rmdir('./empty-folder');

// Delete with contents (recursive)
await rm('./old-folder', { recursive: true, force: true });
6

Rename, Copy, Delete

import { rename, copyFile, unlink } from 'fs/promises';

// Move or rename
await rename('./old.txt', './new.txt');

// Copy a file
await copyFile('./source.txt', './backup.txt');

// Delete a file
await unlink('./temp.txt');
7

Streaming Large Files

For files over ~50MB, streaming prevents memory issues:

import { createReadStream, createWriteStream } from 'fs';
import { pipeline } from 'stream/promises';

const src = createReadStream('./big-file.mp4');
const dst = createWriteStream('./copy.mp4');

await pipeline(src, dst);

Streaming reads the file in chunks instead of loading it all at once.

8

Working with Paths

Always use the path module for cross-platform paths:

import path from 'path';

// Join path segments correctly
const filePath = path.join('users', 'sarah', 'profile.json');

// Get absolute path
const absolute = path.resolve('./data.json');

// Extract parts
path.basename('/users/sarah/file.txt'); // 'file.txt'
path.dirname('/users/sarah/file.txt');  // '/users/sarah'
path.extname('image.png');              // '.png'

Never concatenate paths with + or / — Windows uses \, Unix uses /. The path module handles it.

📋 Quick Reference

fs.readFile(path, encoding)      Read a file
fs.writeFile(path, data)         Write (overwrites)
fs.appendFile(path, data)        Append
fs.unlink(path)                  Delete a file
fs.rename(old, new)              Rename or move
fs.copyFile(src, dest)           Copy
fs.stat(path)                    File info
fs.access(path)                  Check permissions
fs.mkdir(path, { recursive })    Create directory
fs.readdir(path)                 List directory
fs.rmdir(path)                   Delete empty directory
fs.rm(path, { recursive })       Delete with contents
fs.existsSync(path)              Exists check (sync only)

❓ Frequently Asked Questions

What is the fs module?

Node.js's built-in library for reading, writing, and manipulating files.

Sync or async?

Async in production. Sync only for startup scripts and CLIs.

fs vs fs.promises?;

fs.promises returns Promises, so you can use await. Cleaner and modern.

How to check if a file exists?

Use fs.existsSync(path) for sync, or await fs.access(path) in try/catch for async.

🎯 What's Next?

← All How-To Guides