Skip to content

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.

createRetryStore(store: ObjectStore, options?: RetryOptions): ObjectStore
ParameterTypeDescription
storeObjectStoreThe store to wrap.
options?RetryOptionsSee below.
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.

createRetryStore(store, {
breaker: { threshold: 5, resetMs: 30_000 }, // defaults shown
});

After threshold consecutive retryable 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 (concurrent calls keep failing fast until that probe settles). Any success resets the count, and errors your isRetryable rejects (a 403, a malformed request) never count — they say nothing about the backend’s health.

Set breaker: false to disable it entirely.

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.