Bird
Raised Fist0
Node.jsframework~20 mins

Stream backpressure concept in Node.js - Practice Problems & Coding Challenges

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Challenge - 5 Problems
🎖️
Stream Backpressure Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
🧠 Conceptual
intermediate
2:00remaining
What is the main purpose of backpressure in Node.js streams?
Why do streams use backpressure in Node.js?
ATo speed up the data transfer between streams regardless of the writable stream's capacity
BTo close the stream automatically when data size exceeds a limit
CTo buffer all data in memory before writing it to the destination
DTo control the flow of data so the writable stream is not overwhelmed by the readable stream
Attempts:
2 left
💡 Hint
Think about what happens if data is sent faster than it can be processed.
component_behavior
intermediate
2:00remaining
What happens when writable.write() returns false in a Node.js stream?
In Node.js streams, if writable.write(chunk) returns false, what does it mean for the data flow?
AThe writable stream has ended and cannot accept more data
BThe chunk was written successfully and the stream is ready for more data immediately
CThe internal buffer is full; the writable stream asks the readable stream to pause sending data
DThe chunk was rejected and will be lost
Attempts:
2 left
💡 Hint
Consider what the return value of writable.write() indicates about the buffer state.
state_output
advanced
2:00remaining
What is the output of this Node.js stream code regarding backpressure?
Consider this code snippet using streams in Node.js. What will be logged to the console?
Node.js
const { Readable, Writable } = require('stream');

const readable = new Readable({
  read() {
    this.push('data');
    this.push(null);
  }
});

const writable = new Writable({
  write(chunk, encoding, callback) {
    console.log('Writing:', chunk.toString());
    callback();
  }
});

const canWriteMore = writable.write('chunk1');
console.log('Can write more after chunk1:', canWriteMore);

writable.on('drain', () => {
  console.log('Drain event fired');
});
ACan write more after chunk1: false
B
Writing: chunk1
Can write more after chunk1: true
C
Writing: chunk1
Can write more after chunk1: false
Drain event fired
D
Writing: chunk1
Drain event fired
Can write more after chunk1: true
Attempts:
2 left
💡 Hint
Check what writable.write returns when the internal buffer is empty.
🔧 Debug
advanced
2:00remaining
Why does this Node.js stream code cause a memory leak?
This code reads from a file and writes to another file using streams. Why might it cause a memory leak related to backpressure?
Node.js
const fs = require('fs');

const readable = fs.createReadStream('input.txt');
const writable = fs.createWriteStream('output.txt');

readable.on('data', (chunk) => {
  writable.write(chunk);
});
ABecause writable.write is called without checking its return value, causing the readable stream to keep emitting data even if writable buffer is full
BBecause the readable stream is not paused after the 'end' event
CBecause the writable stream is not closed after writing
DBecause the 'data' event is not removed after the first chunk
Attempts:
2 left
💡 Hint
Think about what happens if writable.write returns false but readable keeps emitting data.
📝 Syntax
expert
3:00remaining
Which option correctly implements backpressure handling in a Node.js stream pipe?
Given a readable and writable stream, which code snippet correctly handles backpressure to avoid memory issues?
A
readable.on('data', (chunk) => {
  if (!writable.write(chunk)) {
    readable.pause();
  }
});
writable.on('drain', () => {
  readable.resume();
});
B
readable.on('data', (chunk) => {
  writable.write(chunk);
});
writable.on('drain', () => {
  readable.resume();
});
C
readable.pipe(writable);
readable.pause();
writable.resume();
D
readable.pipe(writable);
writable.on('drain', () => {
  readable.pause();
});
Attempts:
2 left
💡 Hint
Backpressure requires pausing readable when writable buffer is full and resuming on drain.

Practice

(1/5)
1. What is the main purpose of backpressure in Node.js streams?
easy
A. To speed up data transfer between streams
B. To control the flow of data and prevent writable streams from being overwhelmed
C. To close streams automatically after data transfer
D. To convert data formats between streams

Solution

  1. Step 1: Understand stream data flow

    Streams send data from readable to writable. If writable is slow, data can pile up.
  2. Step 2: Role of backpressure

    Backpressure pauses the readable stream to avoid overwhelming the writable stream.
  3. Final Answer:

    To control the flow of data and prevent writable streams from being overwhelmed -> Option B
  4. Quick Check:

    Backpressure controls flow = A [OK]
Hint: Backpressure means controlling data flow to avoid overload [OK]
Common Mistakes:
  • Thinking backpressure speeds up data
  • Confusing backpressure with stream closing
  • Assuming backpressure changes data format
2. Which of the following is the correct way to listen for the 'drain' event on a writable stream in Node.js?
easy
A. writable.on('drain', () => { /* handle drain */ });
B. writable.emit('drain', () => { /* handle drain */ });
C. writable.listen('drain', () => { /* handle drain */ });
D. writable.addEventListener('drain', () => { /* handle drain */ });

Solution

  1. Step 1: Recall event listening syntax in Node.js streams

    Streams use the .on() method to listen for events.
  2. Step 2: Identify correct method for 'drain' event

    The 'drain' event is listened to with writable.on('drain', callback).
  3. Final Answer:

    writable.on('drain', () => { /* handle drain */ }); -> Option A
  4. Quick Check:

    Use .on() to listen to events = D [OK]
Hint: Use .on() to listen for stream events like 'drain' [OK]
Common Mistakes:
  • Using emit() instead of on() to listen
  • Using browser event methods like addEventListener
  • Using non-existent listen() method
3. Consider this code snippet:
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?
medium
A. The writable stream will discard new data chunks
B. The readable stream will continue sending data without pause
C. The program will throw an error and crash
D. The readable stream will pause until the writable stream drains

Solution

  1. Step 1: Analyze writable.write() return value

    When writable.write() returns false, it means the buffer is full and cannot accept more data now.
  2. Step 2: Check how readable reacts

    On false, readable.pause() is called to stop sending data temporarily.
  3. Step 3: Understand 'drain' event handling

    When writable drains, it emits 'drain', triggering readable.resume() to continue data flow.
  4. Final Answer:

    The readable stream will pause until the writable stream drains -> Option D
  5. Quick Check:

    Writable full -> readable pauses -> resumes on drain = C [OK]
Hint: Writable.write false means pause readable until drain event [OK]
Common Mistakes:
  • Assuming readable never pauses
  • Thinking writable discards data silently
  • Expecting program crash on full buffer
4. You wrote this code to handle backpressure but the readable stream never resumes after pausing:
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?
medium
A. The 'drain' event listener is missing, so readable never resumes
B. The writable stream should not use write() inside 'data' event
C. The readable stream should call end() instead of pause()
D. The 'end' event should be listened on writable, not readable

Solution

  1. Step 1: Identify missing event listener

    The code pauses readable when writable.write returns false but never listens for 'drain'.
  2. Step 2: Understand consequence of missing 'drain'

    Without 'drain' listener calling readable.resume(), readable stays paused indefinitely.
  3. Final Answer:

    The 'drain' event listener is missing, so readable never resumes -> Option A
  4. Quick Check:

    Missing drain listener -> readable stuck paused = B [OK]
Hint: Always listen for 'drain' to resume paused readable streams [OK]
Common Mistakes:
  • Thinking pause() should be replaced by end()
  • Ignoring the need for 'drain' event
  • Confusing 'end' event on readable vs writable
5. You want to implement backpressure handling manually without using pipe(). Which sequence correctly manages backpressure between a readable and writable stream?
hard
A. On 'data', pause readable; write chunk; on writable 'error', resume readable
B. On 'data', write chunk; always resume readable immediately; on writable 'finish', pause readable
C. On 'data', write chunk; if write returns false, pause readable; on writable 'drain', resume readable
D. On 'data', write chunk; if write returns true, pause readable; on writable 'close', resume readable

Solution

  1. Step 1: Understand backpressure manual handling

    When writable.write returns false, it signals buffer full, so readable must pause.
  2. Step 2: Resume readable on 'drain' event

    Writable emits 'drain' when ready for more data, so readable resumes then.
  3. 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.
  4. Final Answer:

    On 'data', write chunk; if write returns false, pause readable; on writable 'drain', resume readable -> Option C
  5. Quick Check:

    Pause on false write, resume on drain = A [OK]
Hint: Pause readable if write returns false; resume on writable 'drain' [OK]
Common Mistakes:
  • Resuming readable immediately without pause
  • Pausing readable on true write return
  • Using wrong events like 'finish' or 'close' for resume