ThrottleKit is a pluggable, framework-agnostic rate-limiting toolkit for Node and the web. Where most limiters count requests and hope for the best, ThrottleKit governs the three axes a real request must clear — rate, concurrency, and cost — each behind a bound you can state and prove. It ships a 169 ns synchronous in-process fast path, zero runtime dependencies, and the same algorithm running bit-identically across six storage backends — in memory, on Redis, on Postgres, and on the edge.Documentation 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 is 1.0 — the public API is frozen under SemVer. The STABILITY.md promise covers algorithms, stores, adapters, and federation. Experimental features (adaptive lease sizing, joint-LP policy, learned escrow) are opt-in and tagged
@experimental.Why ThrottleKit exists
Counting requests is the easy 10% of production rate limiting. The hard part is being correct under concurrency, correct across a fleet of many processes, cheap enough to run on every request, resilient when the backing store is down, and honest about the trade-offs you are making. The popular alternatives each solve a slice of this and punt on the rest:express-rate-limitis ergonomic but Express-only, primarily fixed-window, and leans on storeincrementsemantics rather than a single atomic operation — so distributed accuracy depends entirely on the store adapter.rate-limiter-flexibleis powerful and backend-rich but is not edge-native, has no Web-standardfetchstory, no GCRA, and no adaptive concurrency.@upstash/ratelimitis excellent for serverless/edge over HTTP Redis, with multi-region and an ephemeral deny cache — but it is bound to Upstash’s HTTP Redis, offers no pure in-memory mode, and is rate-only (no concurrency or cost axis).
How it compares
Every row is a shipped, tested ThrottleKit feature. The comparison reflects each library’s documented capabilities.express-rate-limit | rate-limiter-flexible | @upstash/ratelimit | ThrottleKit | |
|---|---|---|---|---|
| Provable, fleet-size-independent overshoot bound (TLA⁺-checked) | – | – | – | ✓ |
| Synchronous, allocation-free check | – | – | – | ✓ 169 ns |
| One algorithm, proven bit-identical across backends | – | – | – | ✓ (6 stores) |
| Two-tier leasing — amortized round trips, bounded overshoot | – | – | – | ✓ |
| LLM token-budget escrow (post-hoc cost axis) | – | – | – | ✓ (TALE) |
| Unified rate × concurrency × cost in one decision | – | – | – | ✓ |
| Weighted-fair share · overload shedding · fixed-memory DDoS sketch | – | – | – | ✓ |
| Live binding-axis monitoring dashboard | – | – | – | ✓ (Lens) |
| Plan a limit change before deploy — replay traffic → allow↔deny diff | – | – | – | ✓ (Policy Plans) |
| Framework / transport adapters | 1 (Express) | a few | – | 13 |
| Zero runtime dependencies | – | – | – | ✓ |
Architecture: three cleanly separated concerns
ThrottleKit treats rate limiting as three concerns that never entangle each other:(state, now, cost) — no I/O, no clock reads. This makes them trivially testable and portable to an atomic Redis Lua form. Adding a new algorithm never touches a store.
Stores expose exactly one mutating primitive: an atomic apply. The contract is: run a read-modify-write transform atomically per key. That is the entire surface a backend author must satisfy. Adding a new backend never touches an algorithm.
Adapters are thin glue to your framework — Express, Fastify, Koa, Hono, Next.js, NestJS, the Web fetch API, and more. They extract a key from the request, call the limiter, and emit standard HTTP headers.
Key differentiators
Provable overshoot bound, independent of fleet size. Two-tier leasing is model-checked in TLA⁺/TLC. WithwindowCoupled: true, worst-case global admissions are exactly Limit, no matter how many nodes are in the fleet. Most limiters cannot state a bound at all.
Sub-microsecond synchronous checks. checkSync returns a complete Decision in 169 ns/op (5.9M ops/s), effectively allocation-free — a true sync API for hot paths that should not pay for an await.
One algorithm, six backends, proven bit-identical. All numeric Decision fields are integers so that the JavaScript path and the Redis-Lua path produce byte-equal values. A dual-path conformance suite — including a 200-way concurrent read-modify-write — proves this holds across every backend.
Batteries included, dependencies not. 24 subpath entry points — 8 strategies, 6 storage backends, 13 framework/transport adapters — and zero runtime dependencies.
Quickstart
Install, create your first limiter, and handle a Decision in under five minutes.
Installation
Package manager commands, peer deps, and all 24 entry points.
Strategies
GCRA, token bucket, sliding window, adaptive concurrency, and more.
Two-Tier Limiting
L1 + L2 architecture with strict, cached-deny, and leased modes.