Context
Three core reliability subsystems store their state exclusively in instance fields:
| Subsystem |
State fields |
File |
CircuitBreaker |
consecutiveFailures, lastFailureAt, lastSuccessAt, primaryTrafficPct |
src/utils/circuit-breaker.ts |
ExhaustionRegistry |
per-provider exhaustion map |
src/utils/exhaustion.ts |
CreditLedger |
per-provider spend accumulators |
src/utils/credit-ledger.ts |
In Cloudflare Workers, each invocation runs in an isolated context. The global singleton instances (defaultCircuitBreakerManager, defaultExhaustionRegistry) are re-created on every request. This means:
- A provider that was
OPEN after 5 consecutive failures appears CLOSED on the next request
QuotaExceededError marks a provider exhausted for 5 minutes, but that mark is lost instantly
- Monthly budget spend in
CreditLedger resets to zero each invocation
The package is described as "Cloudflare Workers native" — this is a fundamental gap for that use case.
What's already there
CreditLedger has snapshot() and restore() methods (src/utils/credit-ledger.ts:523–580) for persistence — but no equivalent exists on CircuitBreaker or ExhaustionRegistry, and none of the three are wired up automatically.
Proposed direction
- Add
serialize() / deserialize() to CircuitBreaker and ExhaustionRegistry — lightweight JSON snapshots that callers can persist to KV or cache
- Document the CF Workers limitation in the README under Circuit Breaker and Cost Tracking sections — currently the package presents as fully Workers-native without noting this constraint
- Optional: provide a Durable Objects integration as a separate export or companion package — a DO that owns the circuit breaker state and is shared across invocations
Acceptance criteria for a minimal fix
Found by
Codebase audit (automated) — independently flagged by circuit-breaker and cost-tracking audit slices
Context
Three core reliability subsystems store their state exclusively in instance fields:
CircuitBreakerconsecutiveFailures,lastFailureAt,lastSuccessAt,primaryTrafficPctsrc/utils/circuit-breaker.tsExhaustionRegistrysrc/utils/exhaustion.tsCreditLedgersrc/utils/credit-ledger.tsIn Cloudflare Workers, each invocation runs in an isolated context. The global singleton instances (
defaultCircuitBreakerManager,defaultExhaustionRegistry) are re-created on every request. This means:OPENafter 5 consecutive failures appearsCLOSEDon the next requestQuotaExceededErrormarks a provider exhausted for 5 minutes, but that mark is lost instantlyCreditLedgerresets to zero each invocationThe package is described as "Cloudflare Workers native" — this is a fundamental gap for that use case.
What's already there
CreditLedgerhassnapshot()andrestore()methods (src/utils/credit-ledger.ts:523–580) for persistence — but no equivalent exists onCircuitBreakerorExhaustionRegistry, and none of the three are wired up automatically.Proposed direction
serialize()/deserialize()toCircuitBreakerandExhaustionRegistry— lightweight JSON snapshots that callers can persist to KV or cacheAcceptance criteria for a minimal fix
CircuitBreakerexposesserialize(): stringandstatic deserialize(json: string): CircuitBreakerExhaustionRegistryexposes equivalent snapshot/restore APIFound by
Codebase audit (automated) — independently flagged by circuit-breaker and cost-tracking audit slices