beyondcode/laravel-sliding-window-limiter
A drop-in extension for Laravel's RateLimiter that adds sliding window rate limiting. Instead of fixed intervals that reset abruptly, throttling rolls continuously, giving smoother, more accurate limits for APIs, queued jobs, and other rate-limited actions.
Retry-After and X-RateLimit-* values, honest 429 bodies, and documented reset semantics. A limiter with fuzzy reset behavior manufactures retry storms — and customers will build SDKs against whatever we publish.Consider the approach when:
Do not adopt this as a dependency. It is archived, last released September 2019, has 42 stars and zero known dependents, and predates Laravel 8/9/10/11 and PHP 8.x. There is no maintainer to ship compatibility fixes or respond to a limiter-bypass report. A rate limiter sits on the hot path of every request and functions as a security and cost control — that is not a component to source from an unmaintained repository. The MIT license permits copying the logic with attribution; that is the sane path.
Look elsewhere — or build — when:
Redis::throttle() already clears the bar. It is sorted-set based and effectively sliding. Evaluate it first; the delta may not justify any new code.Adoption criteria to resolve before writing code: target Laravel/PHP/Redis versions; the purpose (abuse prevention vs. cost control vs. SLA enforcement vs. tenant fairness); Redis topology (single, Sentinel, Cluster, managed) and whether the Lua operations stay within one hash slot; header requirements; and whether the team can own a fork. If any of these is unresolved, the correct answer is a spike, not a dependency.
For executives. Rate limiting is simultaneously a pricing surface, a fairness mechanism, and a trust signal — it determines whether customers experience their purchased quota as predictable or arbitrary. Sliding-window limiting is the more defensible model, and this package is a useful reference implementation of it. We should not take it as a dependency: archived since 2019, 42 stars, zero dependents, no maintainer, no security response path, and almost certainly incompatible with our current Laravel and PHP versions. Recommendation: borrow the algorithm, not the code. Estimated effort is small — a time-boxed spike plus a modest middleware with concurrency and Redis-outage tests — and it keeps an unmaintained component off the critical path of every request. Two decisions are needed from product: (1) confirm rolling-window semantics for all published quotas and update the API contract and docs accordingly; (2) choose fail-open or fail-closed behavior when Redis is unavailable, and accept the consequences of that choice explicitly.
For engineering. Treat the repository as a design document, not a dependency; MIT permits reimplementation with attribution. Price in three things: memory — a per-request sorted-set log is O(limit) per key, so define key granularity, TTLs, and ZREMRANGEBYSCORE eviction deliberately and watch for hot shards on high-cardinality keys; atomicity — check-and-record must be a single Lua script, and under Redis Cluster the keys must be hash-tagged into one slot; availability and latency — the limiter is now on every request path, so add a documented Redis failure policy, p50/p99 limiter latency metrics, and a 429-rate-by-tenant dashboard before broad rollout. Recommended sequence: a time-boxed spike comparing this algorithm against Laravel's built-in Redis::throttle() and a token-bucket alternative; then a small internal middleware behind a feature flag, wrapped behind an internal SlidingWindowLimiter interface so the implementation is swappable; shadow-mode it on a low-traffic route and diff decisions against current behavior before enforcing. Document the external contract — window type, key granularity, limit values, headers, reset behavior, failure mode — in the public API docs, because that contract is what customers and their SDKs will integrate against.
For a legacy carve-out. The only scenario where installing the artifact is defensible is a Laravel 5.8/6.x application on PHP 7.x with a bounded remaining lifespan and an existing Redis dependency, where a fork is cheaper than a rewrite. Even then, name an internal maintainer and a release process; ownership is what actually gates this decision.
How can I help you explore Laravel packages today?