Laravel cookbook · Beginner

Rate limit routes per user and per IP

Login and public APIs are abused by scripts, and one heavy user slows everyone down.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Define named limiters that key by user ID when authenticated and by IP otherwise, with stricter limits for login (keyed by email and IP), and apply them with the throttle middleware.

Solution

<?php
// app/Providers/AppServiceProvider.php (boot)
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;

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

RateLimiter::for('login', function (Request $request) {
    return [
        Limit::perMinute(5)->by(strtolower((string) $request->input('email')).'|'.$request->ip()),
        Limit::perMinute(30)->by('ip:'.$request->ip()),
    ];
});
<?php
// routes/web.php
use App\Http\Controllers\Auth\LoginController;
use Illuminate\Support\Facades\Route;

Route::post('/login', [LoginController::class, 'store'])->middleware('throttle:login');

Pitfalls

  • Running behind a load balancer without trusted proxies configured, so every request has the same IP.
  • Limits stored in the array or file cache with several servers.
  • Returning different errors for "unknown email" and "wrong password", which helps attackers.

Variations

  • Customise the 429 response with ->response(fn () => ...) on the limit.
  • Apply coarse limits at the CDN or gateway as well.

Further reading: Rate limiting

Reference: https://laravel.com/docs/13.x/routing#rate-limiting

More Laravel recipes

Was this page helpful?