Real-World Usage & Examples

As a Full Stack Developer, one of the most common backend tasks you’ll perform is working with files — reading logs, storing data, handling uploads, generating reports, etc. In Node.js, this is handled using the powerful fs (File System) module.


What is the fs Module?

The fs module in Node.js allows you to interact with the file system on your machine. You can:

  • Create files
  • Read files
  • Update files
  • Delete files
  • Rename files
  • Work with directories

It comes as a built-in module, so no installation is required.


Importing fs Module

const fs = require('fs');

1. Reading Files in Node.js

Synchronous Method (Blocking)

const data = fs.readFileSync('sample.txt', 'utf8');
console.log(data);
  • Execution stops until file is read
  • Not recommended for production servers

Asynchronous Method (Non-Blocking)

fs.readFile('sample.txt', 'utf8', (err, data) => {
if (err) {
console.log(err);
return;
}
console.log(data);
});
  • Preferred in real-world applications
  • Doesn’t block other requests

2. Writing Files

Create or Overwrite File

fs.writeFile('output.txt', 'Hello from Node.js', (err) => {
if (err) throw err;
console.log('File created successfully');
});

Append Data to File

fs.appendFile('output.txt', '\nNew Line Added', (err) => {
if (err) throw err;
console.log('Data appended');
});

3. Deleting Files

fs.unlink('output.txt', (err) => {
if (err) throw err;
console.log('File deleted');
});

4. Renaming Files

fs.rename('old.txt', 'new.txt', (err) => {
if (err) throw err;
console.log('File renamed');
});

5. Working with Directories

Create Folder

fs.mkdir('myFolder', (err) => {
if (err) throw err;
console.log('Folder created');
});

Read Folder Contents

fs.readdir('./', (err, files) => {
if (err) throw err;
console.log(files);
});

Delete Folder

fs.rmdir('myFolder', (err) => {
if (err) throw err;
console.log('Folder deleted');
});

6. Real-World Example: Logging System

Let’s build a simple logging system like you would in a real application.

const fs = require('fs');

function logMessage(message) {
const log = `${new Date().toISOString()} - ${message}\n`;

fs.appendFile('app.log', log, (err) => {
if (err) throw err;
console.log('Log saved');
});
}

logMessage('User logged in');
logMessage('User added product to cart');

This is exactly how backend systems track activity.


7. Pro Tip (Industry Practice)

Use Promises or async/await instead of callbacks:

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

async function readFileExample() {
try {
const data = await fs.readFile('sample.txt', 'utf8');
console.log(data);
} catch (err) {
console.log(err);
}
}

readFileExample();

Key Takeaways

  • Always prefer asynchronous methods
  • Use fs.promises for modern code
  • Handle errors properly (very important in production)
  • Avoid blocking operations in servers

Node.js File System (fs Module) – Production-Level Understanding

When you move from beginner to professional backend development, the fs module is no longer just about reading files — it becomes part of:

  • Logging systems
  • Data pipelines
  • File uploads (APIs)
  • Report generation
  • Caching layers
  • Backup systems

If you don’t understand fs deeply, you’ll struggle in real-world Node.js projects.


1. Understanding Blocking vs Non-Blocking (Critical Concept)

Node.js is single-threaded, which means:

👉 If you use blocking operations → your entire server freezes
👉 If you use non-blocking → your server handles thousands of users

Blocking Example (Bad for Production)

const fs = require('fs');

console.log("Start");

const data = fs.readFileSync('bigfile.txt', 'utf8');

console.log(data);
console.log("End");

Problem:

  • If file is large → server waits
  • No other request is processed

Non-Blocking Example (Production Way)

const fs = require('fs');

console.log("Start");

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

console.log("End");

Output order:

Start
End
(file content later)

👉 This is the core strength of Node.js


2. File Descriptors (Low-Level Control)

Most developers skip this, but in real systems (especially MNC-level work), you must understand it.

fs.open('sample.txt', 'r', (err, fd) => {
if (err) throw err;

console.log("File Descriptor:", fd);

fs.close(fd, () => {
console.log("File closed");
});
});

Why Important?

  • Helps in large file processing
  • Used in streaming systems
  • Required for performance optimization

3. Streams with fs (VERY IMPORTANT IN REAL PROJECTS)

If you try to load a 1GB file using readFile, your server can crash.

👉 Solution: Streams


Reading Large Files Using Stream

const fs = require('fs');

const stream = fs.createReadStream('largefile.txt', 'utf8');

stream.on('data', (chunk) => {
console.log("Chunk received:", chunk.length);
});

stream.on('end', () => {
console.log("File reading completed");
});

Why Streams Matter

  • Memory efficient
  • Faster
  • Used in:
    • Video streaming
    • File uploads
    • APIs

Writing Using Streams

const fs = require('fs');

const writeStream = fs.createWriteStream('output.txt');

writeStream.write("Hello\n");
writeStream.write("This is streaming write\n");

writeStream.end();

4. Copying Files (Real-World Task)

const fs = require('fs');

fs.copyFile('source.txt', 'destination.txt', (err) => {
if (err) throw err;
console.log("File copied successfully");
});

5. Checking File Exists (Common Mistake Area)

❌ Wrong (Deprecated style):

fs.exists('file.txt', (exists) => {
console.log(exists);
});

✅ Correct way:

fs.access('file.txt', fs.constants.F_OK, (err) => {
if (err) {
console.log("File does NOT exist");
} else {
console.log("File exists");
}
});

6. File Stats (Metadata Handling)

fs.stat('sample.txt', (err, stats) => {
if (err) throw err;

console.log(stats);
console.log("Is File:", stats.isFile());
console.log("Size:", stats.size);
});

Use Cases

  • File upload validation
  • Size limits
  • Security checks

7. Watching Files (Real-Time Systems)

fs.watch('sample.txt', (eventType, filename) => {
console.log(`Event: ${eventType}`);
});

Used In

  • Live reload systems
  • Dev tools
  • Monitoring systems

8. Promises API (Modern Industry Standard)

Callbacks are outdated in large-scale apps.

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

async function fileOperations() {
try {
await fs.writeFile('demo.txt', 'Hello World');
const data = await fs.readFile('demo.txt', 'utf8');
console.log(data);
} catch (err) {
console.log(err);
}
}

fileOperations();

👉 Clean
👉 Scalable
👉 Production-ready


9. Real Project Example: Simple File-Based Database

In small applications, you might store data in JSON.

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

async function saveUser(user) {
let users = [];

try {
const data = await fs.readFile('users.json', 'utf8');
users = JSON.parse(data);
} catch (err) {
users = [];
}

users.push(user);

await fs.writeFile('users.json', JSON.stringify(users, null, 2));
}

saveUser({ name: "Rachit", role: "Developer" });

10. Error Handling (VERY IMPORTANT)

Bad code:

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

Good code:

fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) {
console.error("Error:", err.message);
return;
}
console.log(data);
});

11. Security Best Practices

❌ Dangerous

fs.readFile(req.query.filename);

👉 Vulnerable to:

  • Path traversal attacks (../../etc/passwd)

✅ Safe Approach

const path = require('path');

const safePath = path.join(__dirname, 'files', req.query.filename);

12. Performance Tips from Real Projects

From actual MNC-level experience:

  • Never use readFileSync in APIs
  • Use streams for large files
  • Cache frequently read files
  • Use logging wisely (don’t flood disk)
  • Rotate logs (important in production)

13. Mini Project: Log Rotation System

const fs = require('fs');

function logMessage(message) {
const file = 'app.log';

fs.stat(file, (err, stats) => {
if (!err && stats.size > 1024 * 1024) {
fs.rename(file, `app-${Date.now()}.log`, () => {});
}

const log = `${new Date().toISOString()} - ${message}\n`;

fs.appendFile(file, log, () => {});
});
}

logMessage("User login");

Final Notes (Important)

If you are preparing students for real-world jobs:

  • fs is not just theory → it’s used in every backend system
  • Streams + fs = must-know combo
  • Always think:
    • Performance
    • Security
    • Scalability

Real-World Usage & Examples

As a Full Stack Developer, one of the most common backend tasks you’ll perform is working with files — reading logs, storing data, handling uploads, generating reports, etc. In Node.js, this is handled using the powerful fs (File System) module.


What is the fs Module?

The fs module in Node.js allows you to interact with the file system on your machine. You can:

  • Create files
  • Read files
  • Update files
  • Delete files
  • Rename files
  • Work with directories

It comes as a built-in module, so no installation is required.


Importing fs Module

const fs = require('fs');

1. Reading Files in Node.js

Synchronous Method (Blocking)

const data = fs.readFileSync('sample.txt', 'utf8');
console.log(data);
  • Execution stops until file is read
  • Not recommended for production servers

Asynchronous Method (Non-Blocking)

fs.readFile('sample.txt', 'utf8', (err, data) => {
if (err) {
console.log(err);
return;
}
console.log(data);
});
  • Preferred in real-world applications
  • Doesn’t block other requests

2. Writing Files

Create or Overwrite File

fs.writeFile('output.txt', 'Hello from Node.js', (err) => {
if (err) throw err;
console.log('File created successfully');
});

Append Data to File

fs.appendFile('output.txt', '\nNew Line Added', (err) => {
if (err) throw err;
console.log('Data appended');
});

3. Deleting Files

fs.unlink('output.txt', (err) => {
if (err) throw err;
console.log('File deleted');
});

4. Renaming Files

fs.rename('old.txt', 'new.txt', (err) => {
if (err) throw err;
console.log('File renamed');
});

5. Working with Directories

Create Folder

fs.mkdir('myFolder', (err) => {
if (err) throw err;
console.log('Folder created');
});

Read Folder Contents

fs.readdir('./', (err, files) => {
if (err) throw err;
console.log(files);
});

Delete Folder

fs.rmdir('myFolder', (err) => {
if (err) throw err;
console.log('Folder deleted');
});

6. Real-World Example: Logging System

Let’s build a simple logging system like you would in a real application.

const fs = require('fs');

function logMessage(message) {
const log = `${new Date().toISOString()} - ${message}\n`;

fs.appendFile('app.log', log, (err) => {
if (err) throw err;
console.log('Log saved');
});
}

logMessage('User logged in');
logMessage('User added product to cart');

This is exactly how backend systems track activity.


7. Pro Tip (Industry Practice)

Use Promises or async/await instead of callbacks:

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

async function readFileExample() {
try {
const data = await fs.readFile('sample.txt', 'utf8');
console.log(data);
} catch (err) {
console.log(err);
}
}

readFileExample();

Key Takeaways

  • Always prefer asynchronous methods
  • Use fs.promises for modern code
  • Handle errors properly (very important in production)
  • Avoid blocking operations in servers

Node.js File System (fs Module) – Production-Level Understanding

When you move from beginner to professional backend development, the fs module is no longer just about reading files — it becomes part of:

  • Logging systems
  • Data pipelines
  • File uploads (APIs)
  • Report generation
  • Caching layers
  • Backup systems

If you don’t understand fs deeply, you’ll struggle in real-world Node.js projects.


1. Understanding Blocking vs Non-Blocking (Critical Concept)

Node.js is single-threaded, which means:

👉 If you use blocking operations → your entire server freezes
👉 If you use non-blocking → your server handles thousands of users

Blocking Example (Bad for Production)

const fs = require('fs');

console.log("Start");

const data = fs.readFileSync('bigfile.txt', 'utf8');

console.log(data);
console.log("End");

Problem:

  • If file is large → server waits
  • No other request is processed

Non-Blocking Example (Production Way)

const fs = require('fs');

console.log("Start");

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

console.log("End");

Output order:

Start
End
(file content later)

👉 This is the core strength of Node.js


2. File Descriptors (Low-Level Control)

Most developers skip this, but in real systems (especially MNC-level work), you must understand it.

fs.open('sample.txt', 'r', (err, fd) => {
if (err) throw err;

console.log("File Descriptor:", fd);

fs.close(fd, () => {
console.log("File closed");
});
});

Why Important?

  • Helps in large file processing
  • Used in streaming systems
  • Required for performance optimization

3. Streams with fs (VERY IMPORTANT IN REAL PROJECTS)

If you try to load a 1GB file using readFile, your server can crash.

👉 Solution: Streams


Reading Large Files Using Stream

const fs = require('fs');

const stream = fs.createReadStream('largefile.txt', 'utf8');

stream.on('data', (chunk) => {
console.log("Chunk received:", chunk.length);
});

stream.on('end', () => {
console.log("File reading completed");
});

Why Streams Matter

  • Memory efficient
  • Faster
  • Used in:
    • Video streaming
    • File uploads
    • APIs

Writing Using Streams

const fs = require('fs');

const writeStream = fs.createWriteStream('output.txt');

writeStream.write("Hello\n");
writeStream.write("This is streaming write\n");

writeStream.end();

4. Copying Files (Real-World Task)

const fs = require('fs');

fs.copyFile('source.txt', 'destination.txt', (err) => {
if (err) throw err;
console.log("File copied successfully");
});

5. Checking File Exists (Common Mistake Area)

❌ Wrong (Deprecated style):

fs.exists('file.txt', (exists) => {
console.log(exists);
});

✅ Correct way:

fs.access('file.txt', fs.constants.F_OK, (err) => {
if (err) {
console.log("File does NOT exist");
} else {
console.log("File exists");
}
});

6. File Stats (Metadata Handling)

fs.stat('sample.txt', (err, stats) => {
if (err) throw err;

console.log(stats);
console.log("Is File:", stats.isFile());
console.log("Size:", stats.size);
});

Use Cases

  • File upload validation
  • Size limits
  • Security checks

7. Watching Files (Real-Time Systems)

fs.watch('sample.txt', (eventType, filename) => {
console.log(`Event: ${eventType}`);
});

Used In

  • Live reload systems
  • Dev tools
  • Monitoring systems

8. Promises API (Modern Industry Standard)

Callbacks are outdated in large-scale apps.

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

async function fileOperations() {
try {
await fs.writeFile('demo.txt', 'Hello World');
const data = await fs.readFile('demo.txt', 'utf8');
console.log(data);
} catch (err) {
console.log(err);
}
}

fileOperations();

👉 Clean
👉 Scalable
👉 Production-ready


9. Real Project Example: Simple File-Based Database

In small applications, you might store data in JSON.

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

async function saveUser(user) {
let users = [];

try {
const data = await fs.readFile('users.json', 'utf8');
users = JSON.parse(data);
} catch (err) {
users = [];
}

users.push(user);

await fs.writeFile('users.json', JSON.stringify(users, null, 2));
}

saveUser({ name: "Rachit", role: "Developer" });

10. Error Handling (VERY IMPORTANT)

Bad code:

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

Good code:

fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) {
console.error("Error:", err.message);
return;
}
console.log(data);
});

11. Security Best Practices

❌ Dangerous

fs.readFile(req.query.filename);

👉 Vulnerable to:

  • Path traversal attacks (../../etc/passwd)

✅ Safe Approach

const path = require('path');

const safePath = path.join(__dirname, 'files', req.query.filename);

12. Performance Tips from Real Projects

From actual MNC-level experience:

  • Never use readFileSync in APIs
  • Use streams for large files
  • Cache frequently read files
  • Use logging wisely (don’t flood disk)
  • Rotate logs (important in production)

13. Mini Project: Log Rotation System

const fs = require('fs');

function logMessage(message) {
const file = 'app.log';

fs.stat(file, (err, stats) => {
if (!err && stats.size > 1024 * 1024) {
fs.rename(file, `app-${Date.now()}.log`, () => {});
}

const log = `${new Date().toISOString()} - ${message}\n`;

fs.appendFile(file, log, () => {});
});
}

logMessage("User login");

Final Notes (Important)

If you are preparing students for real-world jobs:

  • fs is not just theory → it’s used in every backend system
  • Streams + fs = must-know combo
  • Always think:
    • Performance
    • Security
    • Scalability