Skip to content

Getting started ​

IMPORTANT

Public beta. Everything planned for 0.1.0 is in, but names and options may still change, and the changelog will say how to upgrade. Try it in staging first, and tell us what breaks or confuses you.

Requirements ​

  • PHP 8.3+, and Laravel 12.69+ or 13.30+.
  • A counter store: Redis 6.2+ or Valkey 7.2+ is best, and the live feed and offenders need one. Memcached and the database store work too, but not file or apc in production.
  • On PHP-FPM, the APCu extension, so a server's workers share the rules.

Installation ​

1. Install the beta:

bash
composer require hanzala-afzal/laravel-dynamic-throttle:^0.1@beta

2. Create the tables, and compile the rules once. After this, saving a rule compiles them, and so does the scheduler.

bash
php artisan vendor:publish --tag=dynamic-throttle-migrations
php artisan migrate
php artisan dynamic-throttle:compile

3. Attach the middleware to the routes rules may limit, in bootstrap/app.php. Routes without it are never limited.

php
->withMiddleware(function (Middleware $middleware) {
    $middleware->appendToGroup('api', 'dynamic.throttle');
})

4. Say who may use the dashboard, in a service provider's boot(). Until you do, only the local environment gets in, and php artisan dynamic-throttle:health warns everywhere else.

php
use App\Models\User;
use Illuminate\Support\Facades\Gate;

Gate::define('viewDynamicThrottle', fn (User $user) => $user->is_admin);
Gate::define('manageDynamicThrottle', fn (User $user) => $user->is_admin);

5. Run Laravel's scheduler. It recompiles the rules every five minutes and stores the traffic numbers every minute.

Then check your setup with php artisan dynamic-throttle:health.

Usage ​

Add a rule in the dashboard under Rules → New rule, from a template such as "Login" or "API per user". New rules start in dry-run: they count requests and show who they would block, but block no one until you promote them.

Or from code:

php
use Afzal\DynamicThrottle\Models\Rule;

Rule::create([
    'name' => 'API per user',
    'pattern' => 'api/*',
    'scope' => 'user',        // ip, user, api_token, header, global or custom
    'max_attempts' => 60,
    'window_seconds' => 60,
]);

Each user now gets 60 requests a minute under /api. The 61st gets Laravel's own 429, with Retry-After and X-RateLimit-* headers.

CommandWhat it does
dynamic-throttle:healthLooks for setup mistakes. --strict fails on a warning too
dynamic-throttle:explain GET /api/orders --user=42Shows why a request would be allowed or limited, without counting it
dynamic-throttle:statusShows what the servers apply now, and until when
dynamic-throttle:bypass on --for=30mLifts every limit until the end time
dynamic-throttle:scale 2 --for=2hMultiplies every limit: 2 doubles them, 0.5 halves them
dynamic-throttle:disable-rule 12, enable-rule 12Switches one rule off or back on
dynamic-throttle:listLists every rule with its id
dynamic-throttle:compileRecompiles the rules now

Beta feedback ​

What helps most:

  • Did it install cleanly on your Laravel and PHP versions, cache store and runtime (PHP-FPM, Octane, Vapor)?
  • Did a rule do something you did not expect? Paste the output of php artisan dynamic-throttle:explain.
  • Was anything in the dashboard or the docs unclear?

Report bugs in issues, and bring questions and ideas to discussions. Report security issues privately, as SECURITY.md explains, never in a public issue.

Released under the MIT License. An independent package, not affiliated with or endorsed by Laravel.