Working with the File System & Streams
Learn how to read and write files in Node.js using the fs module, both synchronously and asynchronously, and discover how streams let you process large amounts of data efficiently.
Working with the File System & Streams is a free Node.js Backend Development Bootcamp lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Node.js Backend Development Bootcamp learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Why the File System Matters
Most backends eventually read or write files on disk — logs, config, uploads, reports. Node's built-in fs module handles it all; just require it.
const fs = require('fs');
console.log(typeof fs.readFile);Synchronous vs Asynchronous
Most fs methods come in two flavors: sync (like readFileSync) blocks the event loop, async doesn't. On servers, always prefer async.
const fs = require('fs');
const data = fs.readFileSync('config.txt', 'utf8');
console.log(data);Reading a File Asynchronously
The classic callback form gives you error first, then data. Always check err before touching the data — a missing file or bad permission lands there.
const fs = require('fs');
fs.readFile('notes.txt', 'utf8', (err, data) => {
if (err) { console.error('Failed:', err.message); return; }
console.log('File says:', data);
});The Promise-Based API
Modern Node exposes a promise-based API under fs/promises — pairs perfectly with async/await and skips callback nesting entirely.
const fs = require('fs/promises');
async function load() {
const data = await fs.readFile('notes.txt', 'utf8');
console.log(data);
}
load();Writing Files
Use writeFile to create or overwrite a file. No file? It's created. File exists? Its contents are replaced wholesale.
const fs = require('fs/promises');
async function save() {
await fs.writeFile('output.txt', 'Hello from Node!');
console.log('Saved.');
}
save();Appending Instead of Overwriting
To add to a file without wiping it, use appendFile — exactly what you want for log files that grow line by line.
const fs = require('fs/promises');
async function log(line) {
await fs.appendFile('app.log', line + '\n');
}
log('Server started');Working with Paths
Hard-coded paths break across operating systems. The path module fixes that: path.join uses the right separator, and __dirname is the current file's folder.
const path = require('path');
const full = path.join(__dirname, 'data', 'users.json');
console.log(full);Checking If a File Exists
Don't check existence first — that risks race conditions. Just try the operation and catch the error; a missing file throws with code ENOENT.
const fs = require('fs/promises');
async function read() {
try {
return await fs.readFile('maybe.txt', 'utf8');
} catch (err) {
if (err.code === 'ENOENT') return 'default content';
throw err;
}
}Why Streams Exist
Reading a 2 GB file with readFile loads it all into memory — a crash waiting to happen. Streams process data in small chunks, keeping memory low.
const fs = require('fs');
const stream = fs.createReadStream('huge.log', 'utf8');
stream.on('data', chunk => console.log('Got', chunk.length, 'bytes'));Piping Streams Together
The power move with streams is pipe: connect a readable straight to a writable. Node handles backpressure so a fast reader won't flood a slow writer.
const fs = require('fs');
const read = fs.createReadStream('input.txt');
const write = fs.createWriteStream('copy.txt');
read.pipe(write);Listing and Creating Directories
The fs module manages folders too: mkdir creates directories (add { recursive: true } for nested paths), and readdir lists contents.
const fs = require('fs/promises');
async function setup() {
await fs.mkdir('uploads', { recursive: true });
const files = await fs.readdir('.');
console.log(files);
}
setup();Quick Check
Test your understanding of file operations.
Recap
You can now work the file system: fs's sync/callback/promise APIs, async on servers, basic I/O, cross-platform path, and streams for big files.
Frequently asked questions
Is the “Working with the File System & Streams” lesson free?
Yes — the full text of “Working with the File System & Streams” is free to read here on the web, and the Node.js Backend Development Bootcamp course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Node.js Backend Development Bootcamp course, upgrade to CoddyKit PRO.
What will I learn in “Working with the File System & Streams”?
Learn how to read and write files in Node.js using the fs module, both synchronously and asynchronously, and discover how streams let you process large amounts of data efficiently. You practise Node.js Backend Development Bootcamp with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Node.js Backend Development Bootcamp?
No prior experience is required. Node.js Backend Development Bootcamp on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Working with the File System & Streams” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Node.js Backend Development Bootcamp lesson?
Yes. Every Node.js Backend Development Bootcamp lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Introduction to Node.js & NPM
- Node.js Module System Explained
- Asynchronous JavaScript & Event Loop
- Working with the File System & Streams