Record-oriented streaming for JavaScript
exstream
High-level record operations with end-to-end backpressure, bounded concurrency, reliable branching, and explicit error handling. Exstream connects async iterables, Node.js streams, and Web Streams to JavaScript transforms and destinations.
const response = await fetch('/data/orders.json')
if (!response.ok) throw new Error(`HTTP ${response.status}`)
const orders = exstream(response.body)
.json({ path: '$.orders[*]' })
.mapAsync(
async (order) => ({
...order,
priority: order.total >= 750 ? 'high' : 'normal',
}),
{ concurrency: 8 },
)
.filter((order) => order.status === 'active')
await orders
.jsonlStringify()
.pipeTo(destination('active-orders', { speed: 50 }))Why Exstream
The easy pipeline is rarely the one that reaches production.
A loop can read, transform, and write records. Production turns that local sequence into a system: several parts now have to agree about pace, delivery, and completion. The hard part is no longer any individual callback. It is coordination.
Compare the same pipeline in native Node.js →- 01 Work starts to overlap
Use the available I/O capacity without starting more work than the system can hold.
- 02 The destination falls behind
Make the source wait instead of turning a temporary slowdown into a growing queue.
- 03 The flow branches or fails
Keep delivery, cancellation, and cleanup part of the same run.
Engineering by contract
The behavior is part of the API.
The fluent syntax is the visible part. Underneath it, Exstream favors explicit semantics over convenient surprises. That discipline continues through the reference, the type system, and execution itself, so a pipeline can be understood before it runs.
Read the operator contracts →- Contracts
- Retention, order, errors, and cancellation are documented per operator.
- Types
- Value and record-context types evolve through the complete chain.
- Execution
- Synchronous transforms stay synchronous; terminal work is always awaitable.
When it fits
Use Exstream when the pipeline itself is the problem.
If you can explain the job with one loop and a few awaits, keep it that way.
Reach for Exstream when correctness depends not only on each step, but on how the complete
flow behaves under load, failure, or cancellation. See when Exstream fits →