Streamsmedium

Flowing vs Paused Mode

Readable streams operate in two modes: paused (data is read explicitly via .read()) and flowing (data is emitted automatically via 'data' events). Streams start in paused mode.

Memory anchor

Paused mode = a beer tap you pull manually (one glass at a time). Flowing mode = you opened the tap and walked away—beer pours nonstop whether anyone's drinking or not. Attaching a 'data' listener is like taping the tap open.

Expected depth

A stream switches to flowing mode when: a 'data' event listener is attached, .resume() is called, or .pipe() is called. It switches back to paused with .pause() or by removing all 'data' listeners. In flowing mode, data is emitted as fast as the readable produces it, potentially faster than the consumer can handle—hence the need for backpressure management. The preferred modern approach is async iteration (for await...of), which handles mode switching internally.

Deep — senior internals

The mode system is a legacy from Node.js 0.10 streams. The 'readable' event represents the third mode variant: the stream emits 'readable' when data is available, and the consumer calls .read(n) explicitly. This is the most low-level control. In Node.js internals, streams track mode via readableFlowing property: null (initial), true (flowing), false (paused by .pause()). Switching from null to flowing without a consumer causes data loss—this is a classic gotcha with streams that emit before listeners are attached in async setups.

🎤Interview-ready answer

Readable streams start paused. Attaching a 'data' listener or calling pipe() switches to flowing mode, emitting data as fast as it's produced. Async iteration (for await...of) is the modern idiom that handles mode management automatically. The key risk in flowing mode is not having a fast enough consumer—data events emit regardless of consumer readiness.

Common trap

Attaching a 'data' event listener then removing it leaves the stream in a null flowing state if readable.readableFlowing is false, potentially causing data loss on the next 'data' listener attachment. The stream may have already consumed buffered data that won't be re-emitted.