A concurrency limiter (a bulkhead) caps how many executions run at the same time. A few more can wait in a queue; everything beyond that is rejected at once. Use it to stop one slow dependency from taking all your sockets, DB connections or memory, and to shed load before it piles up. It does not limit calls per second: a fast dependency can still get thousands of calls a second. For that, use a rate limiter. If you don’t know the right number, use the adaptive concurrency limiter.
Polly-style builder with a shortcut for every strategy: addRetry(), addTimeout(), addCircuitBreaker(), …
Convenient, but it bundles every strategy. For the smallest browser bundle use PipelineBuilder with
retryStrategy(), timeoutStrategy(), … instead; the two are interchangeable.
The type parameters track which errors the pipeline can raise, for pipeline.settle() + Outcome.match().
Polly-style builder with a shortcut for every strategy: addRetry(), addTimeout(), addCircuitBreaker(), …
Convenient, but it bundles every strategy. For the smallest browser bundle use PipelineBuilder with
retryStrategy(), timeoutStrategy(), … instead; the two are interchangeable.
The type parameters track which errors the pipeline can raise, for pipeline.settle() + Outcome.match().
ResiliencePipelineBuilder adds Polly-style addRetry() / addTimeout() / … shortcuts on top, at the cost of
bundling every strategy. Strategies run in the order they are added: the first one added is the outermost.
Options are validated and strategy state (e.g. circuit breaker) is created on build().
ResiliencePipelineBuilder adds Polly-style addRetry() / addTimeout() / … shortcuts on top, at the cost of
bundling every strategy. Strategies run in the order they are added: the first one added is the outermost.
Options are validated and strategy state (e.g. circuit breaker) is created on build().
Shorthands: addConcurrencyLimiter(10) (10 running, no queue) and addConcurrencyLimiter(10, 50) (10 running, 50 queued). The same works for concurrencyLimiterStrategy(10, 50).
A free permit (active < permitLimit): the execution runs right away.
No free permit, room in the queue (queued < queueLimit): it waits. The queue is ordered by priority (lower runs first), FIFO within one priority.
Queue full: the overflow policy decides who is rejected: the newcomer, or someone already waiting.
When an execution finishes, its permit goes straight to the head of the queue. A waiter is never overtaken by a newcomer.
A waiter leaves the queue when its queueTimeout expires (rejected, reason 'queue-timeout') or when its signal aborts (fails with the abort reason, not a rejection).
The default queueLimit is 0. Waiting rarely helps an overloaded service: callers usually prefer a fast 503 to a slow one. Add a queue to absorb short bursts, and give it a queueTimeout so nobody waits longer than the caller would.
The longest-waiting execution is rejected (reason: 'dropped') and the newcomer takes its place. Good when stale requests are worthless (the client has likely given up).
'drop-lowest-priority'
The newest waiter of the lowest priority is dropped, only if the newcomer outranks it (a strictly lower priority number). Otherwise the newcomer is rejected.
Polly-style builder with a shortcut for every strategy: addRetry(), addTimeout(), addCircuitBreaker(), …
Convenient, but it bundles every strategy. For the smallest browser bundle use PipelineBuilder with
retryStrategy(), timeoutStrategy(), … instead; the two are interchangeable.
The type parameters track which errors the pipeline can raise, for pipeline.settle() + Outcome.match().
Polly-style builder with a shortcut for every strategy: addRetry(), addTimeout(), addCircuitBreaker(), …
Convenient, but it bundles every strategy. For the smallest browser bundle use PipelineBuilder with
retryStrategy(), timeoutStrategy(), … instead; the two are interchangeable.
The type parameters track which errors the pipeline can raise, for pipeline.settle() + Outcome.match().
Shared bag for passing data between strategies and the callback.
properties.
Map<string, unknown>.get(key: string): unknown
Returns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
@returns ― Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.
When the queue is full: 'reject-new' (default) rejects the newcomer; 'drop-oldest' rejects the longest-waiting
execution instead; 'drop-lowest-priority' rejects the newest of the lowest priority, if the newcomer outranks it.
Dropped executions reject with BulkheadRejectedError reason 'dropped'.
Longest a queued execution waits before it is rejected with reason: 'queue-timeout'. Must be > 0.
priority
(context) => number
0 for all
Queue order: lower runs sooner (like a Unix nice value), FIFO within a priority. Only called when the execution has to queue. If it throws, the execution fails with that error.
'full' (no permit, no queue room), 'queue-timeout' (waited queueTimeout), 'dropped' (pushed out by overflow)
active, queued
Running and waiting executions at the moment of rejection
retryAfter
undefined
It extends RateLimiterRejectedError, so isRateLimitError() and isRejection() match it. The default retry predicate does not retry rejections; the default fallback predicate does handle them. The /http helpers map it to 503, not 429: a full bulkhead is a capacity problem on your side, not the client sending too fast. See error codes.
Aborted when the caller cancels, or when a strategy (timeout, hedging) gives up on this execution.
signal));
} catch (
var error:unknown
error) {
if (
var error:unknown
errorinstanceof
classBulkheadRejectedError
A concurrency limiter (bulkhead) is full: a capacity problem on our side, so HTTP maps it to 503, not 429.
BulkheadRejectedError) {
var console:Console
The console module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
A global console instance configured to write to process.stdout and
process.stderr. The global console can be used without importing the node:console module.
Warning: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the note on process I/O for
more information.
Example using the global console:
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(newError('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
constname='Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
Example using the Console class:
constout=getStreamSomehow();
consterr=getStreamSomehow();
constmyConsole=new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(newError('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
'full': no slot and no queue room; 'queue-timeout': waited queueTimeout without getting a slot;
'dropped': removed from the queue to make room (overflow: 'drop-oldest' | 'drop-lowest-priority').
active and queued are readable on the strategy instance, e.g. for a health endpoint or a dashboard. ResiliencePipelineRegistry.limiters() lists every limiter of every registered pipeline.
Polly-style builder with a shortcut for every strategy: addRetry(), addTimeout(), addCircuitBreaker(), …
Convenient, but it bundles every strategy. For the smallest browser bundle use PipelineBuilder with
retryStrategy(), timeoutStrategy(), … instead; the two are interchangeable.
The type parameters track which errors the pipeline can raise, for pipeline.settle() + Outcome.match().
ResiliencePipelineBuilder,
classConcurrencyLimiterStrategy<T>
Bulkhead: limits concurrent executions, queues a few, rejects the rest.
Polly-style builder with a shortcut for every strategy: addRetry(), addTimeout(), addCircuitBreaker(), …
Convenient, but it bundles every strategy. For the smallest browser bundle use PipelineBuilder with
retryStrategy(), timeoutStrategy(), … instead; the two are interchangeable.
The type parameters track which errors the pipeline can raise, for pipeline.settle() + Outcome.match().
The console module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
A global console instance configured to write to process.stdout and
process.stderr. The global console can be used without importing the node:console module.
Warning: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the note on process I/O for
more information.
Example using the global console:
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(newError('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
constname='Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
Example using the Console class:
constout=getStreamSomehow();
consterr=getStreamSomehow();
constmyConsole=new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(newError('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
Prints to stdout with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to printf(3)
(the arguments are all passed to util.format()).
One limiter per dependency. A shared pipeline means a shared limit. Build one pipeline per downstream (or use a registry key per downstream) so a slow payments API can’t starve the inventory API.
Pair it with a timeout. Permits are released only when the call ends. A call that hangs forever holds its permit forever. Add a timeout inside the limiter.
Cancellation is free. A queued caller whose signal aborts leaves the queue at once and never takes a permit.
HTTP servers. The /http, Fastify and Koa middlewares have a concurrency option that does this for incoming requests: see load shedding.