Skip to content

Concurrency, capacity, and demand ​

map and mapSettled count work toward their bounds as follows. Defaults are { concurrency: 1, capacity: concurrency, ordered: true }.

OptionWhat counts toward the bound
concurrencyReserved upstream reads + active callbacks (including retry decisions and backoff)
capacityThe above + results awaiting delivery

Both must be positive safe integers with capacity >= concurrency. At most one upstream read is in flight. Increasing capacity lets later work proceed while completed results wait behind an earlier item.

Bounds apply independently to each stage. External source buffers and arrays collected by toArray are excluded.

Interactive slot walkthrough ​

An example with concurrency: 2, capacity: 3, and ordered: true:

Ordered map stage · concurrency: 2, capacity: 3

Scenario: items A, B, and C are read in order; B and C finish before A while ordered: true holds delivery for A.

—Free
—Free
—Free

Step 1 / 8 · Pending downstream next(): No

No downstream demand: no upstream read starts. All three capacity slots are free.

reads + running: 0 ≤ 2 · occupied slots: 0 ≤ 3

Output order ​

For input order A → B → C and completion order B → C → A:

OptionOutput orderResults awaiting delivery
ordered: true (default)A → B → CB and C occupy capacity until A is delivered.
ordered: falseB → C → ADownstream requests can deliver ready results and free capacity.

To preserve the completion order of side effects such as writes, use concurrency: 1 or sequential forEach.

Regardless of output ordering, map stops immediately on an unhandled callback error and aborts the other callbacks' signals. Use mapSettled to receive failures as results and continue.

Downstream read requests ​

New upstream reads start only while a downstream next() is pending. Once a value is delivered, new reads stop until the next request. Work already started, including retries, can continue and retain results within its reserved capacity.

A downstream take(n) limits output count; additional work may already have started. Put take(n) before map to limit the number of input items processed.

Higher-order stream bounds ​

For flatten, concat, flatMap, and concatMap, concurrency bounds active child sources and defaults to 1.

  • Each child occupies a slot from reservation until cleanup (return() and finalizers) finishes.
  • Each child holds at most one pending read or buffered item.
  • concat and concatMap retain slots for later children that have finished reading until earlier children end. This prevents unbounded accumulation of children waiting for their turn.

See Choosing operators for selection guidance.

Synchronous work and the event loop ​

Continuous synchronous work can prevent timers and I/O from running. Pipelines do not yield automatically; use the event-loop yielding recipe when needed.

MapOptions · MapContext · Retries