Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message
Laravel Fixed Window Limiter

Laravel Fixed Window Limiter Laravel Package

beyondcode/laravel-fixed-window-limiter

A Laravel rate limiter using fixed time windows instead of the default sliding windows, so limits reset predictably. Useful for API throttling where you need strict, evenly spaced counters per window.

View on GitHub
Deep Wiki
Context7

Fixed window rate limiting for Laravel and Redis

Frequently asked questions about Laravel Fixed Window Limiter
How do I install beyondcode/laravel-fixed-window-limiter?
Install it with composer require beyondcode/laravel-fixed-window-limiter and point your cache store at Redis, since the counter and its expiry live there. The catch is vintage: the released illuminate/* and PHP constraints target the Laravel 6/7 era, so on Laravel 10, 11 or 12 you will need --ignore-platform-reqs, a Composer alias, or a fork with widened constraints. Once you do that you are effectively maintaining a fork, so budget for that before the roadmap commits.
What is the difference between fixed window and Laravel's default sliding window rate limiter?
Laravel's built-in RateLimiter uses a sliding window that decays gradually, so the allowance refills smoothly as old hits age out. This package uses one counter key per identity per clock-aligned bucket that expires exactly at the boundary, so a 100/min limit always resets at :00. That is exactly what you want when mirroring an external provider's advertised quota, because your remaining count and reset time match theirs. The trade-off is boundary bursts: a client can send a full window right before the reset and another full window right after.
Which Laravel and PHP versions does beyondcode/laravel-fixed-window-limiter support?
The last release is from January 2020 and its composer.json targets illuminate/* components and PHP versions from the Laravel 6/7 era. There are no compatibility patches for Laravel 8 through 12. You can force an install with ignored platform requirements or a Composer alias, but that is unsupported and untested on modern PHP, so treat it as a fork rather than a drop-in dependency.
Is beyondcode/laravel-fixed-window-limiter still maintained?
No. The repository is archived, the last release is January 2020, it has around 67 stars and zero dependents, and there is no changelog, no security response channel and no compatibility work. An archived package in your graph triggers security review, license-scanning exceptions and dependency-policy exceptions at every audit. Use it as a reference implementation for the fixed-window pattern, not as something you expect to receive fixes from.
Is the Redis counter update atomic, or can the INCR and EXPIRE race?
That is the key thing to verify by reading the source before any production exposure. The canonical fixed-window defect is an INCR followed by a separate EXPIRE: if the process crashes between the two, the key survives with no TTL and that identity is throttled permanently, which surfaces as a support ticket rather than an alert. Confirm the implementation wraps both operations in a Lua script or a MULTI/EXEC transaction. The package docs do not make that guarantee for you.
What happens if Redis is unavailable - does the limiter fail open or fail closed?
That behaviour is undocumented, and it matters: failing open protects availability while failing closed protects downstream systems from overload. Because the dependency is unowned and archived, an implicit policy would get baked into your stack without anyone signing off on it. Test the connection-failure path explicitly, decide the behaviour your product needs, and document who approved it. If the package does not do what you need, that is a strong argument for the in-house version.
How do I configure the window length, max attempts and middleware?
The package follows the familiar Laravel shape: a cache-store abstraction, a RateLimiter-style facade and an HTTP middleware, so you define a limiter with a max attempt count and a window length in seconds and attach the middleware to your route group. The window is clock-aligned rather than relative, so a 60-second window resets on the minute rather than 60 seconds after the first request. Check the README for the exact facade and middleware names, since the repository is archived and there is no versioned docs site. Also set a named Redis connection rather than relying on the default cache store if you share a cache with other features.
Does it work with Redis Cluster, predis and phpredis?
There is no evidence either way: zero dependents means nobody has publicly exercised Redis Cluster key-slot behaviour, predis versus phpredis differences, or connection-failure handling. A single counter key per identity per window is generally cluster-safe, but if the implementer used a Lua script or transaction spanning multiple keys, it can break across hash slots. Test against your actual topology and client before relying on it.
Should I use this package or write my own fixed window limiter?
The behaviour is roughly 30 to 50 lines: an INCR plus a conditional PEXPIRE, ideally inside a Lua script, with your own tests and a documented fail-open or fail-closed policy. That gives you atomicity you can prove, modern Laravel and PHP constraints, and no archived dependency in the audit conversation. Reach for the package only if you have written down a concrete semantic gap that Laravel's native RateLimiter::for() plus the throttle middleware cannot close. If sliding window semantics are acceptable to your product, the case for this package collapses entirely.
How do I test fixed window rate limiting in Laravel?
Freeze or travel time with Carbon (travel() or setTestNow) so you can step across the window boundary deterministically, then assert that requests inside one bucket count against the same key and that the counter resets at the boundary. Flush the Redis keys you use between tests so a leftover key with no TTL does not leak into the next case. Cover the 429 response shape, any Retry-After or remaining headers, and the connection-failure path. Because the window is clock-aligned, tests that assume a rolling 60 seconds will be flaky.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo
bernskioldmedia/laravel-harvest
bernskiold/laravel-data-scrubber
bernskiold/laravel-currency-converter
bernskiold/laravel-campaign-monitor
bernskioldmedia/laravel-autotranslate
siberfx/telegram-bot
roy-sandip/laravel-view-extended
gregsphotography/site-builder-core
roy-sandip/laravel-view
anodyne/blade-fluentui-icons
webx-ui/module-catalog-collections