Node.js10 min read

File System (fs) Module Basics

Master file operations in Node.js. Understand sync vs async, file operations, and when to use each method.

Sarah Chen
December 19, 2025
0.0k0

File System (fs) Module

What is the fs Module?

The fs (file system) module lets Node.js interact with files and directories on your computer.

Why Do We Need It?

Browser JavaScript can't:

Browser JavaScript:
❌ Read files from disk
❌ Write files to disk
❌ Access file system
❌ Create directories

Why? Security reasons - browsers can't access your computer's files

Node.js can:

Node.js (Server-side):
✅ Read files from disk
✅ Write files to disk
✅ Access file system
✅ Create directories

Why? Runs on your server, not in browser

File Operations Flow

┌─────────────────────────────────┐
│      Your Node.js App            │
└──────────────┬────────────────────┘
               │
               │ fs.readFile()
               │ fs.writeFile()
               │ fs.mkdir()
               │
┌──────────────▼────────────────────┐
│         fs Module                  │
└──────────────┬────────────────────┘
               │
┌──────────────▼────────────────────┐
│      Operating System              │
│      (File System)                  │
└─────────────────────────────────────┘

Sync vs Async: The Critical Difference

Synchronous (Blocking)

const fs = require('fs');

const data = fs.readFileSync('file.txt', 'utf8');
console.log(data);
console.log('This runs AFTER file is read');

How it works:

Time →
1. Start reading file
2. WAIT (blocked)...
3. WAIT (blocked)...
4. File read complete
5. Continue to next line

Problem: App is frozen while reading!

Asynchronous (Non-Blocking)

const fs = require('fs');

fs.readFile('file.txt', 'utf8', (err, data) => {
  console.log(data);
});
console.log('This runs IMMEDIATELY');

How it works:

Time →
1. Start reading file (don't wait)
2. Continue to next line immediately
3. "This runs IMMEDIATELY" prints
4. File read completes in background
5. Callback executes with data

Benefit: App continues working!

When to Use Sync vs Async

Use Sync When:

  • Startup scripts (read config once)
  • CLI tools
  • Simple scripts
  • When you MUST wait for file operation

Use Async When:

  • Web servers (handle multiple requests)
  • Production applications
  • Any time you need non-blocking behavior

Import the Module

const fs = require('fs');
// or for promises
const fs = require('fs').promises;

Reading Files

Synchronous (blocks execution):

const content = fs.readFileSync('file.txt', 'utf8');
console.log(content);

Asynchronous with callback:

fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});

Async/await (recommended):

const fs = require('fs').promises;

async function readFile() {
  const content = await fs.readFile('file.txt', 'utf8');
  console.log(content);
}

Writing Files

const fs = require('fs').promises;

// Write (overwrites existing)
await fs.writeFile('output.txt', 'Hello World!');

// Append to file
await fs.appendFile('log.txt', 'New log entry\n');

Check if File Exists

const fs = require('fs');

if (fs.existsSync('file.txt')) {
  console.log('File exists!');
}

// Or with promises
try {
  await fs.access('file.txt');
  console.log('File exists!');
} catch {
  console.log('File does not exist');
}

Delete Files

// Delete file
await fs.unlink('file.txt');

// Delete directory (must be empty)
await fs.rmdir('folder');

// Delete directory with contents
await fs.rm('folder', { recursive: true });

Create Directories

// Create single directory
await fs.mkdir('new-folder');

// Create nested directories
await fs.mkdir('path/to/nested', { recursive: true });

List Directory Contents

const files = await fs.readdir('.');
console.log(files);  // ['file1.txt', 'file2.txt', 'folder']

// With file types
const entries = await fs.readdir('.', { withFileTypes: true });
entries.forEach(entry => {
  console.log(`${entry.name} - ${entry.isDirectory() ? 'Dir' : 'File'}`);
});

Get File Info

const stats = await fs.stat('file.txt');
console.log({
  size: stats.size,           // bytes
  isFile: stats.isFile(),
  isDirectory: stats.isDirectory(),
  created: stats.birthtime,
  modified: stats.mtime
});

Copy and Rename

// Copy file
await fs.copyFile('source.txt', 'dest.txt');

// Rename/move file
await fs.rename('old.txt', 'new.txt');

Practical Example: Log Manager

const fs = require('fs').promises;
const path = require('path');

async function log(message) {
  const timestamp = new Date().toISOString();
  const line = `[${timestamp}] ${message}\n`;
  await fs.appendFile('app.log', line);
}

async function readLogs() {
  try {
    return await fs.readFile('app.log', 'utf8');
  } catch {
    return 'No logs yet';
  }
}

// Usage
await log('App started');
await log('User logged in');
console.log(await readLogs());

Key Takeaway

Use fs.promises with async/await for clean file operations. Remember: readFile for reading, writeFile for writing, unlink for deleting, mkdir for directories. Always handle errors!

#Node.js#File System#fs#Beginner