Backpressure helps control data flow in streams so the receiver is not overwhelmed. It keeps the data moving smoothly without crashes or slowdowns.
Stream backpressure concept in Node.js
Start learning this pattern below
Jump into concepts and practice - no test required
const readable = getReadableStream(); const writable = getWritableStream(); readable.on('data', (chunk) => { const canWrite = writable.write(chunk); if (!canWrite) { readable.pause(); writable.once('drain', () => { readable.resume(); }); } });
readable.pause() stops the data flow temporarily.
writable.once('drain') waits for the writable stream to be ready again.
readable.on('data', (chunk) => { if (!writable.write(chunk)) { readable.pause(); writable.once('drain', () => readable.resume()); } });
pipe() automatically manages backpressure for you.readable.pipe(writable);
This program copies a file using streams. It pauses reading when the writable stream is full and resumes when it can accept more data. This prevents memory overload and keeps the process smooth.
import { createReadStream, createWriteStream } from 'node:fs'; const readable = createReadStream('input.txt'); const writable = createWriteStream('output.txt'); readable.on('data', (chunk) => { const canWrite = writable.write(chunk); if (!canWrite) { readable.pause(); writable.once('drain', () => { readable.resume(); }); } }); readable.on('end', () => { writable.end(); console.log('Copy complete'); });
Backpressure is important to avoid crashes or slowdowns when handling large or fast data streams.
Using pipe() is the easiest way to handle backpressure automatically.
Always listen for the drain event on writable streams to know when to resume reading.
Backpressure controls data flow between streams to prevent overload.
Pause the readable stream when writable is full, resume on drain.
Use pipe() for automatic backpressure handling.
Practice
Solution
Step 1: Understand stream data flow
Streams send data from readable to writable. If writable is slow, data can pile up.Step 2: Role of backpressure
Backpressure pauses the readable stream to avoid overwhelming the writable stream.Final Answer:
To control the flow of data and prevent writable streams from being overwhelmed -> Option BQuick Check:
Backpressure controls flow = A [OK]
- Thinking backpressure speeds up data
- Confusing backpressure with stream closing
- Assuming backpressure changes data format
Solution
Step 1: Recall event listening syntax in Node.js streams
Streams use the .on() method to listen for events.Step 2: Identify correct method for 'drain' event
The 'drain' event is listened to with writable.on('drain', callback).Final Answer:
writable.on('drain', () => { /* handle drain */ }); -> Option AQuick Check:
Use .on() to listen to events = D [OK]
- Using emit() instead of on() to listen
- Using browser event methods like addEventListener
- Using non-existent listen() method
const readable = getReadableStreamSomehow();
const writable = getWritableStreamSomehow();
readable.on('data', chunk => {
const canWrite = writable.write(chunk);
if (!canWrite) {
readable.pause();
}
});
writable.on('drain', () => {
readable.resume();
});
readable.on('end', () => {
writable.end();
});
What will happen if the writable stream's internal buffer is full?Solution
Step 1: Analyze writable.write() return value
When writable.write() returns false, it means the buffer is full and cannot accept more data now.Step 2: Check how readable reacts
On false, readable.pause() is called to stop sending data temporarily.Step 3: Understand 'drain' event handling
When writable drains, it emits 'drain', triggering readable.resume() to continue data flow.Final Answer:
The readable stream will pause until the writable stream drains -> Option DQuick Check:
Writable full -> readable pauses -> resumes on drain = C [OK]
- Assuming readable never pauses
- Thinking writable discards data silently
- Expecting program crash on full buffer
readable.on('data', chunk => {
if (!writable.write(chunk)) {
readable.pause();
}
});
// Missing 'drain' event listener on writable
readable.on('end', () => {
writable.end();
});
What is the main problem causing the readable stream to stay paused?Solution
Step 1: Identify missing event listener
The code pauses readable when writable.write returns false but never listens for 'drain'.Step 2: Understand consequence of missing 'drain'
Without 'drain' listener calling readable.resume(), readable stays paused indefinitely.Final Answer:
The 'drain' event listener is missing, so readable never resumes -> Option AQuick Check:
Missing drain listener -> readable stuck paused = B [OK]
- Thinking pause() should be replaced by end()
- Ignoring the need for 'drain' event
- Confusing 'end' event on readable vs writable
pipe(). Which sequence correctly manages backpressure between a readable and writable stream?Solution
Step 1: Understand backpressure manual handling
When writable.write returns false, it signals buffer full, so readable must pause.Step 2: Resume readable on 'drain' event
Writable emits 'drain' when ready for more data, so readable resumes then.Step 3: Verify option correctness
On 'data', write chunk; if write returns false, pause readable; on writable 'drain', resume readable matches this correct sequence; others misuse pause/resume or wrong events.Final Answer:
On 'data', write chunk; if write returns false, pause readable; on writable 'drain', resume readable -> Option CQuick Check:
Pause on false write, resume on drain = A [OK]
- Resuming readable immediately without pause
- Pausing readable on true write return
- Using wrong events like 'finish' or 'close' for resume
