alt-three/throttle
Alt Three Throttle provides configurable request rate limiting for Laravel applications. It offers middleware and helpers to protect routes from abuse, control traffic spikes, and return appropriate throttling responses using your chosen cache store.
Architecture fit
alt-three/throttle is a Laravel 5–era middleware package: a service provider binds a limiter into the container, a throttle-style middleware guards routes, and counters are persisted through Laravel's cache repository. That is architecturally aligned with the framework's HTTP kernel and requires no separate infrastructure — it fits inside an existing Laravel request lifecycle rather than beside it. However, the framework has since absorbed this exact capability: Illuminate\Routing\Middleware\ThrottleRequests (Laravel 5.2+), the RateLimiter facade (5.6+), and named limiters via RateLimiter::for() (8.x+). The package's architecture is therefore fit-for-purpose but redundant; the only defensible reason to adopt it is to preserve a specific limiter semantic (custom key derivation, per-route config arrays, response headers) that native middleware does not express as cleanly.
Integration feasibility
Low-to-moderate. Composer constraints will almost certainly pin illuminate/* to ^5.x and PHP to ^7.0, which blocks installation on any Laravel 6+ application and on PHP 8 runtimes. For a Laravel 5.x estate still in service, composer require alt-three/throttle plus provider registration and middleware aliasing is a sub-day task. For anything newer, integration means a fork: re-namespacing, updating contracts, replacing removed helpers, and revalidating against the current cache and routing internals.
Technical risk High, and concentrated in unsupportedness rather than in code quality. The repository is archived, the last release is September 2018, and there are zero dependents — no downstream projects are exercising it, so regressions would surface only in our environment. There is no security response path, no CVE monitoring, and no PHP 8 / Laravel 6+ compatibility work. Secondary risks: fixed-window counting permits boundary bursts roughly 2× the nominal limit; non-atomic read-then-write counter updates can over-admit under concurrency unless the cache driver supports atomic increment; and IP-derived keys break silently behind load balancers unless trusted proxies are configured. The MIT license does permit a fork, which is the mitigation lever.
Key questions
RateLimiter::for() cannot express (custom keys, per-tenant quotas, cost-weighted requests, custom 429 bodies, Retry-After/X-RateLimit-* headers)?Stack fit Poor as a dependency, good as a pattern reference. Rate limiting is now a first-class framework concern; adopting a third-party limiter on a supported Laravel version adds a dependency where none is needed and duplicates middleware that ships in the box. The package is a fit only for a frozen Laravel 5.x application where native limiter ergonomics are inadequate.
Migration path
Recommended path is replacement, not integration: extract the existing limiter configuration and behavior into native RateLimiter::for() definitions (or ThrottleRequests middleware parameters on 5.x–7.x), preserving key derivation and response semantics. Where the package is already in production, run the native limiter in shadow mode — log what it would have limited — before removing the package, so that threshold and key-derivation differences are observable rather than assumed.
Compatibility
Verify concretely before committing: composer why-not alt-three/throttle against each target, PHP version floor, cache driver behavior for increment atomicity, and any reliance on framework helpers removed in Laravel 6 (str_*, array_*) or on the Illuminate\Foundation internals that shifted across majors. If a fork is required, budget for a compatibility matrix (PHP 7.4/8.1/8.2 × Laravel 8/9/10/11) even if only one cell is currently needed — a single-cell fork becomes a trap at the next upgrade.
Sequencing
Maintenance Ongoing cost is effectively zero if not adopted, and open-ended if forked. A fork inherits: PHP and Laravel upgrade churn, dependency bumps, and security triage for a package nobody else uses — meaning no upstream fixes and no community signal when something breaks. Archived-plus-zero-dependents is the worst combination for maintenance: we would be the only consumer and the only detector of breakage.
Support No upstream support, no issue triage, no maintainer. Internal support requires an owner with Laravel middleware fluency; the code surface is small enough that a competent engineer can read it fully in an hour, which caps the support risk but does not remove it. Document the limiter semantics explicitly — thresholds, key derivation, window type, failure mode — because that knowledge currently lives only in the code.
Scaling Limiter cost is one cache round-trip per request, so throughput scales with the cache tier, not the application tier. Redis/Memcached is required for correctness under concurrency; file or database cache stores will both bottleneck and over-admit. Multi-region or multi-cluster deployments need a shared counter store, otherwise each region enforces its own quota and effective limits multiply by region count. Fixed windows do not smooth bursts — if downstream services need smoothing, a sliding-window or token-bucket implementation is required regardless of which package we choose.
Failure modes
X-Forwarded-For parsed incorrectly, allowing trivial bypass.Ramp-up Low for engineers familiar with Laravel middleware — provider registration, alias, config. The real ramp-up cost is archaeology: reconstructing why specific thresholds and keys were chosen, since the package offers no guidance and its maintainer is gone. Budget a half-day of reverse-engineering per consuming service, and treat the package as documentation of intent to be re-expressed natively rather than as a component to be carried forward.
How can I help you explore Laravel packages today?