throttlekit
Comparison

What only ThrottleKit does.

The incumbents are good at what they do — this isn't a teardown. It's the line between "counts requests" and "governs rate, concurrency, and cost behind a bound you can prove." Every ThrottleKit row is a shipped, tested feature; every benchmark — including the rows an incumbent wins — is reproducible on your hardware.

Fair framing — who's who
Each of these is the right tool for something.
express-rate-limit

The simplest drop-in.

If you want a few lines of Express middleware to stop casual abuse, it's perfect — minimal, battle-tested, ubiquitous. It counts requests; that's the job.

rate-limiter-flexible

The versatile workhorse.

Many backends, many algorithms, mature and widely deployed. On a single Redis or Postgres counter it's fast and solid — a strong general-purpose choice.

@upstash/ratelimit

Serverless-native.

Built for edge/serverless on Upstash's REST Redis. If that's your stack, it fits the deployment model cleanly out of the box.

ThrottleKit is for the next tier of requirement: when "approximately right across the fleet" isn't good enough, when you need to govern LLM spend, or when you want one verified core behind every backend and language. The matrix below is what it adds on top.

Capability matrix
Distributed-correctness guarantees & breadth.
Capability express-rate-limit rate-limiter-flexible @upstash/ratelimit ThrottleKit
Provable, fleet-size-independent overshoot bound (TLA⁺-checked) ✓ GALE
LLM token-budget escrow — the post-hoc cost axis ✓ TALE
Unified rate × concurrency × cost in one decision
Synchronous, allocation-free check ✓ 169 ns
One algorithm, proven bit-identical across backends ✓ 6 stores
Two-tier leasing — amortized round trips, bounded overshoot
Weighted-fair share · overload shedding · fixed-memory DDoS sketch
Polyglot from one verified core (Python today)
Framework / transport adapters 1 (Express) a few 13
Zero runtime dependencies

This table is about distributed-correctness guarantees and breadth, and reflects each library's documented capabilities. All three incumbents do basic rate limiting well; the rows show what ThrottleKit layers on top, not a quality judgement of their core job.

The honest head-to-head
Where an incumbent ties — or wins.
  • Redis: a dead heat. ThrottleKit and rate-limiter-flexible both do one atomic Lua round trip per request and land within noise (778 vs 752 ops/sec) — ThrottleKit has a slightly tighter tail, but there's no throughput story here.
  • A single Postgres counter: rate-limiter-flexible wins. Its specialized one-statement UPSERT (348 ops/sec) beats ThrottleKit's generic read-modify-write transaction (121 ops/sec) that reuses one proven transform across every strategy. Add twoTier(leased) and that flips to a ~35× win — but on the raw shared counter, the upsert is faster.
  • Drop-in simplicity: express-rate-limit wins. If all you need is a few lines guarding an Express route, ThrottleKit is more than you need.
  • Where ThrottleKit pulls ahead — the sync GCRA path computes a full decision in 169 ns (faster than express's bare counter bump at 199 ns), and the two-tier lever reaches 66.4k ops/sec where the incumbents have no equivalent. Full methodology →
Pick which, when
Choose ThrottleKit when…
  • You run a fleet and "approximately the limit" isn't good enough — you need admitted ≤ Limit you can point a model checker at.
  • You operate an LLM gateway and need to bound token spend, not just request count.
  • You want rate, concurrency, and cost governed in one decision, not three bolted-together libraries.
  • You need the same proven core behind Node and Python, across Redis / Postgres / DynamoDB / edge KV, byte-identically.

If none of those apply, the incumbent you already use is probably the right call — and ThrottleKit's benchmarks will tell you the truth either way.