How to Fix API Rate Limiting in Laravel

Checks if API endpoints implement proper rate limiting.

authentication authorization Easy fix 15 minutes

What This Check Detects

Checks if API endpoints implement proper rate limiting.

Full Documentation

What is API Rate Limiting?

Rate limiting restricts the number of requests a user can make to your API within a time period. This prevents abuse, protects resources, and ensures fair usage.

Security Impact

Severity: Medium

  • API abuse and resource exhaustion
  • DDoS attacks
  • Brute force attacks
  • Data scraping
  • Service degradation

How to Fix

1. Apply Built-in Throttle Middleware

// routes/api.php
Route::middleware('throttle:60,1')->group(function () {
    Route::get('/user', function () {
        return auth()->user();
    });
});

2. Configure Rate Limiters

// app/Providers/RouteServiceProvider.php
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;

protected function configureRateLimiting()
{
    // Default API limiter
    RateLimiter::for('api', function (Request $request) {
        return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
    });
    
    // Authenticated users - higher limit
    RateLimiter::for('authenticated', function (Request $request) {
        return $request->user()
            ? Limit::perMinute(100)->by($request->user()->id)
            : Limit::perMinute(10)->by($request->ip());
    });
    
    // Premium users - even higher limit
    RateLimiter::for('premium', function (Request $request) {
        if ($request->user()?->isPremium()) {
            return Limit::none();
        }
        return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
    });
}

3. Apply to Routes

Route::middleware(['auth:sanctum', 'throttle:authenticated'])->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index']);
});

Route::middleware(['auth:sanctum', 'throttle:premium'])->group(function () {
    Route::get('/premium/data', [PremiumController::class, 'data']);
});

4. Custom Response

// app/Http/Middleware/CustomThrottleMiddleware.php
use Illuminate\Routing\Middleware\ThrottleRequests;

class CustomThrottleMiddleware extends ThrottleRequests
{
    protected function buildException($key, $maxAttempts)
    {
        $retryAfter = $this->limiter->availableIn($key);
        
        return response()->json([
            'message' => 'Too many requests',
            'retry_after' => $retryAfter,
        ], 429);
    }
}

5. Different Limits for Different Endpoints

// Strict limits for sensitive operations
Route::post('/login', [AuthController::class, 'login'])
    ->middleware('throttle:5,1'); // 5 per minute

// Generous limits for reading
Route::get('/posts', [PostController::class, 'index'])
    ->middleware('throttle:100,1'); // 100 per minute

Verification Steps

  1. Make requests up to the limit - should succeed
  2. Exceed the limit - should get 429 error
  3. Check response headers for rate limit info
  4. Wait for reset period - should work again
  5. Verify different limits for different user types

Response Headers

Laravel includes helpful headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
Retry-After: 60

Advanced Configuration

Multiple Limits

RateLimiter::for('api', function (Request $request) {
    return [
        Limit::perMinute(60),
        Limit::perDay(1000),
    ];
});

Dynamic Limits

RateLimiter::for('api', function (Request $request) {
    $limit = $request->user()->rate_limit ?? 60;
    return Limit::perMinute($limit)->by($request->user()->id);
});

Related Issues

  • Brute Force Protection
  • JWT Token Security
  • CORS Misconfiguration

Related Security Checks

Free security check

Is your Laravel app exposed right now?

34% of Laravel apps we scan have at least one critical issue. Most teams don't find out until something breaks. Our free scan checks your live application in under 60 seconds.

18% have debug mode on
72% missing security headers
12% have exposed .env
Scan My App Free No signup required. Results in 60 seconds.