This is a continuation of Laravel: rate limiter for different API endpoints
Centralizing your rate limits in a config file keeps your Laravel app clean and easy to maintain.
1. Create a Config File
Make a new file: config/rate_limits.php
php
<?php
return [
// Key = endpoint name
// Value = [limit, window_in_seconds]
'login' => [
'limit' => 3,
'window' => 60, // 3 requests per minute
],
'profile' => [
'limit' => 20,
'window' => 60, // 20 requests per minute
],
'default' => [
'limit' => 100,
'window' => 60, // 100 requests per minute
],
];
2. Update the Service
Modify app/Services/RateLimiter.php to load limits from the config:
php
<?php
namespace App\Services;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Config;
class RateLimiter
{
public static function attempt(string $userId, string $endpoint): bool
{
$script = file_get_contents(app_path('Services/Redis/rate_limit.lua'));
// Load limit & window from config
$settings = Config::get("rate_limits.$endpoint") ?? Config::get("rate_limits.default");
$limit = $settings['limit'];
$window = $settings['window'];
// Key = endpoint + user
$key = "rate_limit:{$endpoint}:{$userId}";
$result = Redis::eval($script, 1, $key, $limit, $window);
return $result === 1;
}
}
3. Simplify Controllers
Now controllers don’t need hardcoded values — just pass the endpoint name:
php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\RateLimiter;
class ApiController extends Controller
{
public function login(Request $request)
{
$userId = $request->ip(); // limit login by IP
if (!RateLimiter::attempt($userId, 'login')) {
return response()->json(['error' => 'Too Many Login Attempts'], 429);
}
return response()->json(['message' => 'Login successful']);
}
public function profile(Request $request)
{
$userId = $request->user()->id ?? $request->ip();
if (!RateLimiter::attempt($userId, 'profile')) {
return response()->json(['error' => 'Too Many Profile Requests'], 429);
}
return response()->json(['profile' => ['name' => 'ice', 'age' => 26]]);
}
}
Benefits:
- Single place for limits → change behavior without touching controllers.
- Default rule applies automatically if endpoint not configured.
- Easy to add new endpoints → just update
config/rate_limits.php. - Can be tuned per environment (production vs. local).
You want to make this middleware-based, so you can attach rate limits to routes directly (Route::middleware('throttle:login'))? That way, you won’t even touch controllers. See Laravel: a middleware-based Rate limiter.

