Laravel rate limiting for API protection

Carlos Mendez Jan 2026
2 tabs
<?php

namespace App\Providers;

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;

class RouteServiceProvider extends ServiceProvider
{
    protected function configureRateLimiting(): void
    {
        // Default API rate limit
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });

        // Custom rate limit for login
        RateLimiter::for('login', function (Request $request) {
            return Limit::perMinute(5)->by($request->ip());
        });

        // Different rates for authenticated vs guest
        RateLimiter::for('posts', function (Request $request) {
            return $request->user()
                ? Limit::perMinute(100)->by($request->user()->id)
                : Limit::perMinute(10)->by($request->ip());
        });

        // Multiple limits - whichever is hit first
        RateLimiter::for('strict', function (Request $request) {
            return [
                Limit::perMinute(10),
                Limit::perHour(100),
            ];
        });

        // Custom response
        RateLimiter::for('uploads', function (Request $request) {
            return Limit::perMinute(5)
                ->by($request->user()->id)
                ->response(function (Request $request, array $headers) {
                    return response('Too many uploads', 429, $headers);
                });
        });
    }
}
2 files · php Explain with highlit

Rate limiting prevents API abuse by restricting request frequency per user or IP. Laravel's RateLimiter facade defines limits in RouteServiceProvider. I apply limiters via middleware—throttle:api for the default API limiter. Custom limiters use closures returning Limit objects with max attempts and decay time. Named limiters enable different rates for different endpoints. The for() method creates per-user limits, while static limits apply globally. Headers like X-RateLimit-Remaining inform clients of remaining attempts. Exceeded limits return 429 responses. For advanced scenarios, I integrate Redis for distributed rate limiting across servers. This protection is essential for public APIs and prevents resource exhaustion attacks.