This is a continuation of `Laravel: creating config file for rate limits`.
Turning Rate limiter into middleware is the most “Laravel way” — so you can attach limits directly to routes, without bloating controllers.
1. Create Middleware
bash
php artisan make:middleware RateLimitMiddleware
Then edit app/Http/Middleware/RateLimitMiddleware.php:
php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use App\Services\RateLimiter;
class RateLimitMiddleware
{
/**
* Handle an incoming request.
*
* @param string $endpoint
*/
public function handle(Request $request, Closure $next, string $endpoint)
{
$userId = $request->user()->id ?? $request->ip();
if (!RateLimiter::attempt($userId, $endpoint)) {
return response()->json([
'error' => 'Too Many Requests',
'endpoint' => $endpoint,
], 429);
}
return $next($request);
}
}
2. Register Middleware
Open app/Http/Kernel.php and add it to $routeMiddleware:
php
protected $routeMiddleware = [
// ...
'rate.limit' => \App\Http\Middleware\RateLimitMiddleware::class,
];
3. Use It in Routes
Now you can declare rate limits per route in routes/api.php:
php
use App\Http\Controllers\ApiController;
Route::post('/login', [ApiController::class, 'login'])
->middleware('rate.limit:login');
Route::get('/profile', [ApiController::class, 'profile'])
->middleware('rate.limit:profile');
// fallback → default rule in config/rate_limits.php
Route::get('/posts', [ApiController::class, 'posts'])
->middleware('rate.limit:default');
4. Config Remains Centralized
php
return [
'login' => ['limit' => 3, 'window' => 60],
'profile' => ['limit' => 20, 'window' => 60],
'default' => ['limit' => 100, 'window' => 60],
];
Benefits:
- Now your controllers don’t care about rate limits.
- You manage limits in one config file + middleware assignment.
- Works cleanly with Laravel route groups, API versions, etc.

