pause-stream review
pause-stream 0.0.11 contains no stream implementation of its own. Its entry file returns `require('through')`, making the package an alias for the old through 2.x streams1 helper. That helper holds chunks in a plain array while paused, then replays them on `resume()`. There is no byte limit, `highWaterMark`, modern Transform lifecycle, or coordinated error cleanup. We measured a 2-package, 1 MB Node install and a failed browser bundle. The package only makes sense when preserving legacy behavior long enough to remove it.
pause-stream 0.0.11 took 0.8 seconds and 1 MB in our sandbox, but its browser bundle failed and the repository is archived. Preserve it only for a contained streams1 dependency; use core `PassThrough` with `pipeline()` everywhere new.
We installed it
| Install | ✓ · 0.8s | 2 packages on disk · 1 MB |
| Import | ✓ | ESM import works · require() works · CommonJS package |
| Browser | n/a | could not be bundled for the browser (Node-only code, most likely) |
| Types | — | no TypeScript types found |
| Known vulns | 0 | 0 critical · 0 high · 0 moderate · 0 low (npm audit) |
Answers from our run
Does pause-stream install cleanly?
Yes. In a fresh container with an empty cache, npm install pause-stream finished in 0.8s, leaving 2 packages and 1 MB on disk. npm audit reported no known vulnerabilities.
Can pause-stream run in a browser?
Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.
Does pause-stream work with both ESM and CommonJS?
Yes. Both import 'pause-stream' and require('pause-stream') worked in Node 22 in our run. The package is published as CommonJS.
Does pause-stream include TypeScript types?
No type declarations were found in our install, so TypeScript users need their own declarations.
pause-stream or readable-stream: which should you use?
readable-stream: Choose it when supported runtimes need userland copies of current Node stream classes. pause-stream 0.0.11 took 0.8 seconds and 1 MB in our sandbox, but its browser bundle failed and the repository is archived.
When should you not use pause-stream?
The code is new. Core PassThrough and pipeline() provide current backpressure and cleanup without adding a package.
Use it if
- A streams1 application already imports this exact name and a small maintenance release cannot change its buffering behavior.
- Legacy code relies on `pause()` returning the same object before a destination is available.
- A transitive dependency audit needs to account for pause-stream and through 2.x as the same runtime function.
- A bounded migration window must preserve `queue()`, `push()`, synchronous replay, and data-event semantics.
- The code is new. Core `PassThrough` and `pipeline()` provide current backpressure and cleanup without adding a package.
- The producer can run ahead for an unknown time. Paused chunks accumulate in an unbounded array with no byte accounting.
- Cleanup depends on `stream.pipeline()`. This streams1 object's `destroy()` only clears state and emits `close`.
- A pipe chain needs one propagated error outcome. Classic `pipe()` requires an error listener and teardown plan for every hop.
- Maintenance or TypeScript support is required. npm last published in September 2013, GitHub archived the repo in 2018, and 0.0.11 ships no declarations.
Setup reality
Our uncached Node 22 install of pause-stream 0.0.11 finished in 0.8 seconds, leaving 2 packages and 1 MB on disk. The package is 48 KB unpacked, has 1 direct dependency and 0 peers, and reports MIT plus Apache2 licensing. npm audit found 0 known vulnerabilities. We found no TypeScript declarations.
Version 0.0.11 is CommonJS with no exports map. Both require() and ESM import worked because Node can wrap that entry. The entry itself delegates immediately to through 2.x, so pinning pause-stream alone does not describe the implementation. Our esbuild browser build failed on the Node stream dependency. Keep it out of frontend code.
pause() sets a flag. Each later write appends its value to an array and returns false. resume() synchronously emits queued data events in order and then emits drain when still running. Nothing limits the array. If the producer ignores the false result, memory consumption grows with every queued object or buffer.
The object starts from legacy new Stream(), rather than modern Readable, Writable, or Transform classes. destroy() discards its array, marks readable and writable false, and emits close; it does not stop the source. Existing chains need error listeners on every participant. The useful migration replaces this alias with core PassThrough and wraps the full route in pipeline().
Patterns
Confirm the wrapper and dependency export match confirm-reexport
const pauseStream = require("pause-stream")
const through = require("through")
console.log(pauseStream === through) // trueThe 0.0.11 entry returns `require('through')` with no wrapper, so Node supplies the identical cached function to both names.
Buffer a short gap before attaching output buffer-before-pipe
const pause = require("pause-stream")
const buffer = pause()
source.pipe(buffer.pause())
findDestination((error, destination) => {
if (error) return buffer.destroy()
buffer.pipe(destination)
buffer.resume()
})Paused data has no byte or item ceiling. Use this only when both the wait and the producer volume are tightly bounded.
Observe ordered replay during resume observe-pause
const buffer = require("pause-stream")()
const seen = []
buffer.on("data", chunk => seen.push(String(chunk)))
buffer.pause()
buffer.write("a")
buffer.write("b")
buffer.resume()
console.log(seen) // ["a", "b"]`resume()` drains the array synchronously in insertion order. It emits `drain` afterward unless a listener pauses the object again.
Respect the paused write signal honor-write-result
buffer.pause()
if (buffer.write(chunk) === false) {
producer.pause()
buffer.once("drain", () => producer.resume())
}A paused write returns `false`. Producers that keep writing bypass the only flow signal and expand the unbounded array.
Provide through-style write and end callbacks custom-transform
const pause = require("pause-stream")
const upper = pause(
function write(chunk) {
this.queue(String(chunk).toUpperCase())
},
function end() {
this.queue(null)
}
)The callback API belongs to through 2.x. `this.queue(null)` closes its readable side.
Handle each streams1 failure separately manual-errors
source.on("error", fail)
buffer.on("error", fail)
destination.on("error", fail)
source.pipe(buffer).pipe(destination)
function fail(error) {
if (source.destroy) source.destroy(error)
buffer.destroy()
}Classic `pipe()` does not create one failure boundary. Add a listener per object, and stop the producer yourself after buffer teardown.
Replace the queue with PassThrough replace-passthrough
const { PassThrough } = require("node:stream")
const buffer = new PassThrough({ highWaterMark: 1024 * 1024 })
source.pipe(buffer)
buffer.pause()
attachDestination(() => {
buffer.pipe(destination)
buffer.resume()
})Core `PassThrough` supports a `highWaterMark` plus current backpressure and destruction semantics.
Give the whole route one pipeline lifecycle managed-pipeline
const { PassThrough } = require("node:stream")
const { pipeline } = require("node:stream/promises")
await pipeline(
source,
new PassThrough(),
destination,
)`pipeline()` propagates failure and destruction across current stream classes, behavior the legacy pause-stream destroy method cannot provide.
Drop one alias without changing streams1 behavior replace-direct-through
// Before
const makeStream = require("pause-stream")
// After
const makeStream = require("through")At 0.0.11 the function is identical to through 2.x. Removing the alias reduces a package but does not modernize the stream.
Discard buffered values with legacy destroy destroy-buffer
const buffer = require("pause-stream")()
buffer.pause()
buffer.write("discard me")
buffer.destroy()
console.log(buffer.readable, buffer.writable) // false falseThis destroy path empties the array and emits `close`; it neither creates an error nor tears down the upstream writer.
Pass arbitrary objects through the old queue pass-objects
const buffer = require("pause-stream")()
buffer.on("data", record => console.log(record.id))
buffer.pause()
buffer.write({ id: 1 })
buffer.resume()Streams1 accepts the object without `objectMode`. It also performs no type check, byte accounting, or high-water enforcement.
Detect an expanding paused queue through heap usage inspect-memory
const buffer = require("pause-stream")()
buffer.pause()
setInterval(() => {
const mb = process.memoryUsage().heapUsed / 1024 / 1024
console.log(mb.toFixed(1))
}, 1000)
source.pipe(buffer)A rising heap is the observable symptom when the producer continues feeding the unbounded paused array.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| readable-stream | npm | Choose it when supported runtimes need userland copies of current Node stream classes. |
| through2 | npm | Choose it as an incremental step from streams1 callbacks to the Transform contract. |
| streamx | npm | Choose it for new throughput-sensitive pipelines built around a maintained alternative stream implementation. |
More utils guides
lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →
How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.

