If you know Polly, you know this API: ResiliencePipelineBuilder, addRetry,
addCircuitBreaker, shouldHandle, PredicateBuilder, ResiliencePropertyKey, OnRetry and OnCircuitOpened
events, Simmy-style chaos. The differences are JavaScript ones: durations are milliseconds or strings like '30s',
and CancellationToken is an AbortSignal. See Migrating from Polly.
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().
ms to wait before starting another attempt. Default 2000.
> 0 latency mode, 0 parallel mode (all at once), < 0 fallback mode (next attempt only after a failure).
delay: '150ms',
HedgingOptions<any>.maxHedgedAttempts?: number |undefined
Hedged attempts in addition to the primary. Default 1.
maxHedgedAttempts: 1 }) // second request after 150 ms; the loser is aborted
Adaptive concurrency. A bulkhead whose limit tunes itself from observed latency, with the gradient2, vegas
and AIMD algorithms known from Netflix’s concurrency-limits. You stop guessing “how many parallel calls can this database take”.
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().
Concurrency limit that tunes itself from observed latency and failures (gradient2 / vegas / aimd),
so you don't have to guess the right number: it grows while the dependency keeps up and backs off when it queues.
A pipeline executed inside another one inherits its signal through AsyncLocalStorage. A 3-second budget on an
incoming request cancels every downstream call made under it, even ones that never received the signal. See
Context and signals.
pipeline.settle() returns an outcome whose error type is computed from the strategies you added.
Outcome.match() then requires a handler per error code. Add a circuit breaker, forget to handle CIRCUIT_OPEN,
and the build fails. See Typed errors.
Retries and circuit breakers ignore 4xx client errors, caller aborts and rejections from other strategies. Retrying
a 404 can’t help, and a breaker that counts its own “circuit open” rejections never closes. An open circuit is never
retried. Calls marked idempotent: false are never repeated once they may have reached the dependency. See
What counts as a failure.
You need one retry loop and nothing else.p-retry is smaller.
The retry() one-liner is close, but a dedicated library is still lighter.
You use every strategy through ResiliencePipelineBuilder in a browser bundle. The full builder is 15.1 KB
min+gzip. Switch to PipelineBuilder to pay only for what you use.
You want durable workflows (retries that survive a process restart, sagas). That is a job for a workflow
engine or a queue, not an in-process pipeline.