-
Notifications
You must be signed in to change notification settings - Fork 0
Performance
All numbers are reproducible on your own hardware via npm run bench (and npm run bench:compare for the head-to-head). They are measured on the dev machine (below), not vendor claims, and vary run-to-run (~±10%). The Redis/Postgres latencies here are Docker-on-Windows (WSL2, NAT-bound) and are dominated by that network path — read the cross-library relative numbers and the round-trip counts as the signal, not the absolute microseconds. The full table — algorithms labelled, methodology, machine spec, and every place ThrottleKit loses — lives in SCOREBOARD.md.
Measured 2026-05-28 on an AMD Ryzen AI 9 HX 370 (24c), Node v24.13.1; reproducible via npm run bench:
checkSync(GCRA): ~5.4M ops/s, ~186 ns/op, ~1 B/op (≈allocation-free).-
check(async, GCRA): ~3.5M ops/s (~285 ns/op). - Token bucket
checkSync: ~5.5M ops/s; fixed windowcheckSync: ~5.2M ops/s. - Redis: exactly one
EVALSHAround trip per check.
npm run bench:compare — same machine, process, warmup, and iteration count; all on the allow path. The algorithm each library actually implements is labelled (a fixed-window counter and a GCRA cell are not the same guarantee even at equal ops/s).
- Sync: ThrottleKit is one of the few JS limiters with a synchronous API at all, and it's allocation-free.
-
Redis (loopback): roughly tied with
rate-limiter-flexibleon throughput and p50 (both one atomic Lua round trip), with a tighter tail (p999 ~1.3× lower — cachedEVALSHA+ a leaner script). -
Async in-memory: ThrottleKit now edges past
rate-limiter-flexible(~3.4M vs ~2.8M ops/s);express-rate-limit's bareMapcounter stays ~1.4× faster (~4.7M) — the cost of returning a fullDecisionover a bounded-memory GCRA / timing-wheel store. All contenders are far past real-world per-process need. -
Postgres: a single bare check trails
rate-limiter-flexible's one-statement upsert (~2.9×, by design —PostgresStoreruns one generic transaction per strategy so the same proven transform drives every backend). Under load,twoTier(leased)over Postgres amortizes one transaction perbatchrequests into a ~37× throughput win (13.8k vs 372 ops/s).
A rate limiter's value is its correctness guarantee, not its microbenchmark. ThrottleKit publishes the cases where a leaner counter beats it precisely because the trade is deliberate: a bounded-memory GCRA cell with a smooth pacing guarantee and a proven distributed bound is worth a few hundred nanoseconds against a plain counter that offers neither. The benchmark harness is in the repo so you can confirm all of this on your own hardware.
ThrottleKit · MIT · 1.0 — API frozen under SemVer (Stability)
- Getting Started
- Choosing a strategy
- Frameworks & the edge
- Distributed & provable
- Federation
- Scaling & the Fleet
- Unified admission
- Pillar 4 — Weighted Fair Escrow
- Middleware integration
- Distributed adaptive concurrency
- Advanced limiting
- Overload, fairness & DDoS
- Operations
- Monitoring — ThrottleKit Lens
- Policy Plans
- Replay
- Performance
- Migrating
- Polyglot & Python
- GALE & TALE