Skip to content

What resilix is

Why this exists

JavaScript has fault handling. Its load limiting is locked inside two RPC clients — hedging and retry budgets only in @grpc/grpc-js, adaptive throttling only in the AWS SDK, ~90M downloads a week between them, and unavailable to anyone calling a plain HTTP API, a database or a queue.

Two failure modes motivated this library, both from production:

1. Your upstream degrades without erroring. A provider went from p50 0.35s / p95 0.9s to p50 10.4s / p95 15.3s — roughly 25–30× slower with a completely flat error rate. A failure-rate circuit breaker is blind to that until calls start timing out. resilix trips on slow-call rate, a dimension no other JavaScript breaker has.

2. Healthy traffic contains a lot of 4xx. On a good day, 13–18% of calls to a validating upstream returned 4xx. Any breaker whose failure predicate is "did the promise reject?" opens because customers submitted bad input. resilix classifies outcomes into verdicts, so a 4xx is answered — healthy — while a 429 is overload: not a failure, but still a load signal.

Design commitments

  • Zero runtime dependencies, no I/O in core. A policy decision costs microseconds and cannot itself fail.
  • Time is injected. Every temporal behaviour is deterministically testable; the test suite has no real timers and no sleep().
  • Nothing at module scope. No timers, no AbortController, no random values at import time — which is what makes some libraries crash wrangler dev on import.
  • O(1) per call. The window keeps running counters, so rates never iterate and eviction is a tail advance, not a scan. Typed arrays, preallocated, no steady-state allocation.
  • Bounded key registry. Per-host state has a TTL and a hard cap, so tenant- or attacker-influenced keys cannot leak memory.
  • No distributed state. Cross-instance ejection belongs to the service mesh. snapshot() / hydrate() cover the serverless case, which is what people actually need — and they are origin-safe: every serialised time is relative, and idle time between processes is accounted for, so a rehydrated window ages correctly instead of coming back looking fresh.

Where to go next

Getting startedinstall, your first pipeline, and the two mistakes that bite immediately
The verdict modelthe idea the rest of the library is built on
Design decisionswhy it is shaped this way, including what was rejected

MIT licensed. Zero runtime dependencies.