Retry & circuit breaker
createRetryStore wraps any ObjectStore with exponential-backoff retries
and a circuit breaker. Place it directly above the network store, under the
cache — see the production stack guide
for why that order matters.
createRetryStorecreateRetryStore(store: ObjectStore, options?: RetryOptions): ObjectStore| Parameter | Type | Description |
|---|---|---|
store | ObjectStore | The store to wrap. |
options? | RetryOptions | See below. |
Backoff options
Section titled “Backoff options”| Option | Default | What it does |
|---|---|---|
retries |
3 | Attempts after the first (total attempts = retries + 1). |
initialDelayMs |
100 | Base delay, doubled every attempt. |
maxDelayMs |
5000 | Upper bound on the backoff delay. |
jitter |
0.3 | Random jitter added to each delay, as a fraction of it. |
isRetryable |
see below | Decide whether an error is worth retrying. |
The store contract already maps “not found” to null rather than throwing
(see the ObjectStore guide) — so any
thrown error here is a genuine failure. The default isRetryable retries
network faults, throttling, and HTTP 5xx/429 responses; anything else
(a 4xx that isn’t throttling, a programming error) fails immediately.
The circuit breaker
Section titled “The circuit breaker”createRetryStore(store, { breaker: { threshold: 5, resetMs: 30_000 }, // defaults shown});After threshold consecutive failures, the store stops even trying — every
call fails fast with CircuitOpenError (code: "EUNAVAILABLE") for
resetMs, then lets exactly one request through to probe whether the
backend has recovered.
Set breaker: false to disable it entirely.
Observability
Section titled “Observability”createRetryStore(store, { onRetry: (info) => console.warn('retrying', info),});onRetry fires on every retry attempt — wire it into your existing logging/
metrics pipeline rather than debugging retries blind.