Changelog
Every release, in one place.
Curated highlights across the three published packages, newest first. Each links out to
its full CHANGELOG.md on GitHub, and you can see the at-a-glance shipped
state on the status board.
throttlekit
The core library — algorithms, stores, adapters, the two engines.
1.7.0 hardening
- A decision-finiteness invariant now applies across every strategy: a construction parameter that would make a Decision field (
limit/remaining/resetAt/retryAfterMs) non-finite throws aRangeErrorat construction instead of emitting a malformed value, closed ingcra,tokenBucket, andfixedWindow/slidingWindow/quota. The worst case wasleakyBucket, where a non-finitedelayMsmadeschedule()callsleep(Infinity)and hang forever: a silent hang, not just a bad number. - New hard limits close DoS/overflow vectors: the zero-dependency YAML/JSON config parser caps block-nesting depth at 64 (a deeply nested untrusted config could previously stack-overflow), a per-request cost above
Number.MAX_SAFE_INTEGERis now rejected (it previously overflowed internal arithmetic to a non-finite value),slidingWindow.bucketsis capped at 100,000, and a decoded sketch snapshot with a poisoned/non-finite total is rejected on decode and ignored on merge. - Internal: a new fuzzing, mutation-testing, and model-based-testing layer found these (Stryker mutation score on the core decision math went 65.4% → 77.5%, and a live-store CI gate now runs on every push). Minor bump, not patch: a handful of previously-garbage-returning absurd option values now throw, no valid input's behavior changed.
1.6.1 performance
multiRateLimit.checkSyncis about 40% faster on composite dimensions (2-dim 4968→2968 ns/op, 3-dim 7507→4599 ns/op) by skippingstructuredClonefor dimensions whose state is an immutable primitive (the GCRA default); only object/array states still clone.weightedFairEscrowgrant is about 15% faster (182→155 ns/op) via an O(1) running Σweight/Σused aggregate, gated on integer weights/costs, falling back to the exact rescan the instant a fractional value appears.RedisStorenow pipelines thettlFloorMsfloor into the strategy eval in one round trip for pipeline-capable clients;PostgresCoordinatordrops a redundantSELECT...FOR UPDATEviaRETURNING.- All decisions are byte-identical before/after: this is an internal perf pass, not a behavior change.
1.6.0 audit sweep
- A multi-agent correctness/security audit — every fix reproduced on real code and pinned by a regression that failed on the prior commit.
- Fixes: concurrency-coordinator over-eviction (now anchors to the Redis server clock), two window-roll over-admits (federation lease +
twoTierlow-water refill), and amultiRateLimitRedis-prefix mismatch that madereset()a no-op. - New opt-in options:
RedisStore.ttlFloorMs,RedisConcurrencyCoordinator.useServerTime, and a per-instance sketchseed.
1.5.0
- Tier-2 fleet leasing —
LeaseSpenderspends a leased slice of a global budget locally, refreshing once per batch (proven byte-identical to the core leased path, golden-vector pinned). - Store-authoritative lease window (
leaseWindowed) eliminates node↔store clock skew.
1.4.0
- Policy Plans (
throttlekit/policy) — a terraform plan for limits: replay recorded traffic vs a candidate → the allow↔deny diff, gate-able in CI. - Store-backed cross-region fair escrow (
RedisRegionFairPool) — weighted-max-min across separate region processes.
1.3.0
- What-If Replay testkit — record a leaf limiter's decisions, replay a candidate, read the flip ledger. Fail-loud throughout.
1.2.0
- New stable OTel metric
denies_by_axis{lane}— break unified-admission denials down by axis in Grafana.
1.1.0
- In-process telemetry (
admissionTap/withAdmissionAnalytics) — the binding-axis signal that powers ThrottleKit Lens.
1.0.0 API frozen
- The API is frozen under SemVer — mechanically enforced (type-surface tests + publint / attw on every push).
- STABILITY.md (the v1 promise) and BENCH.md (measured, reproducible numbers) ship with the package.
throttlekit-server
The gRPC service door + ThrottleKit Lens — reach the same limiter from any language.
0.4.4 performance
- The
RateLimiter.CheckgRPC handler is about 25% faster (898→675 ns/op, 1.11M→1.48M ops/s in-process) by building the server enforcer withemit:false, so theRateLimit-*header set the gRPC path discards is never computed. - Capture: the in-process collision witness now uses an unkeyed SHA-256 (it never persists), and the encrypted segment store is swept once per flush batch instead of once per write (O(K×N) → O(N)).
- Cost Room validates and sorts the weighted-fair-escrow tenant roster once per snapshot frame instead of twice.
0.4.3
- Audit fixes: Monitor
safeStringifyDAG false-positive, a startup banner that mislabeled a downgraded channel as mTLS, captureSegmentStore.readO(N)→O(1), and clarifiedAdmitcost semantics.
0.4.2 security
- Lease ids are now 128-bit random capability tokens (was a guessable global counter — a slot-hijacking vector).
- Monitor
GetSnapshotno longer crashes on a non-serializable custom stat; an authorized captureexportthat fails mid-flight is now audited.
0.4.1
- Replay what-if no longer misclassifies distributed policies (
federated/fleetBudget/distributedConcurrency/federatedFairEscrow) as plain leaf-rate.
0.4.0
- Tier-2 Fleet lease door (
Fleet.Reserve) — a high-throughput client leases a slice of afederated:budget and spends it locally; loopback-only until--fleet-secret. - Store-authoritative lease window; clean startup-drain and
--monitor offfixes.
0.3.0
- Four fleet features over existing RPCs —
federated/federatedFairEscrow(Check),fleetBudget(Debit),distributedConcurrency(Admit) — no client change, no wire change. - Read-only Monitor door + Prometheus
/metrics+ standard gRPC health. - Policy Plans: the
policy planCLI and a--tuiPlan tab.
0.2.0
- Deterministic What-If Replay tab — how many requests a config change would flip, against live traffic.
0.1.0 wire frozen
- Graduated from experimental: the gRPC wire is frozen and conformance-tested against the golden vectors.
- Opt-in, AES-256-GCM-encrypted, redacted decision capture with a fail-closed audited CLI.
0.1.0-experimental.6
- Monitoring moved to a built-in, zero-dependency terminal dashboard (
--tui) — ThrottleKit Lens.
throttlekit-py
The reference Python client — every axis, bit-for-bit against the Node oracle.
0.5.1
slots=Trueon the per-call frozen dataclasses (Decision,Forecast,Lease,LeaseGrant) roughly halves the transported decision's footprint (160 → 72 bytes).- The Redis backend precomputes its ARGV template once per backend instance instead of rebuilding it per call, for both sync and async.
- The lease-spend cost guard is inlined, and the adapter checker's sync/async nature is classified once at construction instead of per request.
0.5.0
- Tier-2 fleet leasing (
FleetBackend/LeasedLimiter) + aMonitorBackendsnapshot client; lease vectors byte-verified. - A full runnable
examples/set — one script per axis (rate, leased, cost, concurrency, unified, FastAPI).
0.4.0
- Async backends (
AsyncServiceBackend/AsyncRedisBackend). @rate_limitdecorator,decision_headers, and FastAPI / Starlette / Django / Flask adapters.
0.3.0
admit()reaches the concurrency / unified axis over the service door (Door C).
0.2.0
debit()for the cost axis — windowed token budgets over the service door (Door B).
0.1.0
- Initial release:
ServiceBackend(gRPC) +RedisBackend, the rate strategies, the frozen types, and the cross-language conformance suite.