This page documents the complete set of types that form ThrottleKit’s stable API surface. All types are exported from the top-levelDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/AmeyaBorkar/throttlekit/llms.txt
Use this file to discover all available pages before exploring further.
throttlekit package. They are designed for extensibility:
producer types (values the library returns) grow only by appending optional readonly fields;
consumer interfaces (contracts you implement) grow only by adding optional members.
Decision
The immutable result of one rate-limit check. Every check method returns aDecision.
All numeric fields are integers so the JavaScript and Redis-Lua execution paths produce bit-identical
values.
Whether the request is permitted.
The effective ceiling: burst capacity (GCRA/token bucket) or window quota.
Whole units remaining before the next rejection. Never negative.
Epoch-ms at which the limiter is fully replenished.
Milliseconds to wait before retrying.
0 when allowed is true.Forecast
A non-consuming projection of a key’s near-future capacity. Returned byLimiter.forecast().
Whole units of the given
cost admissible right now before the next denial.Epoch-ms when capacity next increases by at least one unit.
Epoch-ms when the limiter is fully replenished to its ceiling from the current state.
Strategy<S>
A pure rate-limiting algorithm over serializable stateS. The check function is a pure function
of (state, now, cost) — no I/O, no clock reads — which makes it deterministic, trivially testable,
and portable to an atomic Redis Lua form.
Stable identifier surfaced in
RateLimit-Policy and metrics (e.g. "gcra").Effective ceiling reported to clients (burst capacity or window quota).
Effective window length in ms, surfaced as the
w of RateLimit-Policy. Optional.Upper bound on how long state stays relevant; used as the store TTL hint.
The pure transition. Given the current state, epoch-ms
now, and request cost, returns the next
state and the resulting Decision.Optional atomic Redis form. When present, a Lua-capable store runs it in one round trip.
Pure, non-mutating introspection: the
Decision for the current state without consuming. Optional.
The basis of Limiter.peek.Pure capacity forecast for the current state. Optional. The basis of
Limiter.forecast.Read-only access to stored state for a Lua-capable store. Required for
peek/forecast to work
over a Lua store.Store
Storage exposes exactly one mutating primitive:apply. Adding a backend means implementing one
method; adding an algorithm never touches a store.
Run
transform atomically with respect to other applies on the same key.Synchronous, allocation-light variant. Absent on async-only stores (e.g.
RedisStore). When
present, enables checkSync, checkManySync, peekSync, and forecastSync on the limiter.Forget a key’s stored state.
Synchronous reset. Optional; only on stores that can guarantee synchronous deletion.
Release resources (timers, connections). Optional.
Limiter
A constructed limiter: a strategy + store + key namespace + clock. Returned byrateLimit(),
twoTier(), and every higher-level factory.
The active strategy. Use
limiter.strategy.name for headers/policy labelling.Check
key consuming cost units (default 1).Zero-
await synchronous check. Throws ThrottleKitError on an async-only store.Check many independent keys in one call at a single consistent timestamp.
Synchronous batch check. Throws on an async-only store.
Non-consuming introspection without spending capacity. Optional.
Synchronous
peek. Requires a synchronous store and a strategy that implements peek. Optional.Non-consuming capacity forecast. Optional.
Synchronous
forecast. Optional.Forget a key’s state.
Release resources owned by this limiter. Optional.
Transform<S, R>
A pure read-modify-write run atomically by a store. Closes overnow and cost.
lua property carries an atomic acceleration for Lua-capable stores. Stores that
ignore it remain correct via the function body.
ApplyOutcome<S, R>
The outcome of a storeapply: new state + caller’s result + persistence info.
Next state. Written when
persist is true.Value returned to the caller (a
Decision for rate-limit checks).TTL for the persisted state, in ms.
Whether state must be written to the store.
StrategyOutcome<S>
What aStrategy returns from a single transition. An alias for ApplyOutcome<S, Decision>.
FailMode
Behavior when the backing store is unreachable."open"— admit the request when the store is unavailable (fail permissively)."closed"— deny the request when the store is unavailable (fail safely).
Clock
Injected time source. Epoch-ms. Nothing in the core ever reads the clock directly.ManualClock
A controllableClock for deterministic testing. Advance its time with advance(ms).
Error Classes
All errors extendThrottleKitError and carry a code field. Prefer code over instanceof for
robustness across realms and duplicate bundle copies.
ThrottleKitError
Base class for all errors thrown by ThrottleKit.Machine-readable discriminant. Robust to cross-realm
instanceof checks. One of:
"throttlekit_error" | "store_unavailable" | "not_implemented" |
"rate_limit_exceeded" | "queue_full" | "config_invalid".StoreUnavailableError
Thrown when the backing store cannot be reached. Code:"store_unavailable".
RateLimitExceededError
Convenience error for callers who prefer throwing over inspecting aDecision. Carries the denying
decision and its retryAfterMs. Code: "rate_limit_exceeded".
NotImplementedError
Thrown by placeholder code paths that are declared but not yet implemented. Code:"not_implemented".
QueueFullError
Thrown byleakyBucket when the shaper’s internal queue is at capacity and cannot accept another
reservation. Code: "queue_full". Carries retryAfterMs.
combineDecisions
Combine twoDecision objects into one — the pure algebra at the heart of unifiedAdmission.
| Field | Rule | Why |
|---|---|---|
allowed | a.allowed && b.allowed | AND — both must allow |
limit | min(a.limit, b.limit) | binding (smaller) ceiling |
remaining | min(a.remaining, b.remaining) | binding remainder |
resetAt | max(a.resetAt, b.resetAt) | latest-resolution wait |
retryAfterMs | max(a.retryAfterMs, b.retryAfterMs) | dominant wait |
ALLOW_FULL),
associativity, commutativity, and idempotency.
ALLOW_FULL
The neutral element (identity) forcombineDecisions. An always-allowing Decision with
limit = remaining = Number.MAX_SAFE_INTEGER.
buildRateLimitHeaders
Build standards-compliant rate-limit response headers for aDecision.
The decision to build headers from.
Current epoch-ms for delta-seconds math. Defaults to the system clock. Pass
clock.now() for
deterministic output in tests.Policy name surfaced in structured fields. Defaults to
"default".Window length in seconds, surfaced as
;w= in RateLimit-Policy.Which header families to emit. Defaults to
{ draft: true }.createEnforcer
Build a transport-agnosticEnforcer from a limiter plus the shared header/fail policy.
Build a fresh in-memory limiter from this strategy. Mutually exclusive with
limiter.A pre-built limiter to use directly. Mutually exclusive with
strategy.Store-outage policy. Default
"open".Which header families to emit on each decision.
Policy name surfaced in structured headers.
Callback fired on every denial (
outcome: "limited").Callback fired when the store throws, before the fail policy is applied.
The resolved limiter, for direct
check use or header/policy introspection.The store-outage policy applied inside
enforce.Run the limit for
key. Never throws on a store outage — the fail policy converts it to an
EnforceResult with outcome: "error".clientIp
Derive the proxy-correct, IPv6-aggregated client IP key from a request’s socket peer andX-Forwarded-For header.
The socket peer address (e.g.
req.socket.remoteAddress).The
X-Forwarded-For header value.Trust policy for
X-Forwarded-For. Default false (ignore XFF, use socket peer only). A number
trusts that many hops; a string array is an IP/CIDR allowlist of trusted proxies.IPv6 aggregation prefix length in bits. Default
64. IPv4-mapped IPv6 is collapsed to its
embedded IPv4 address.