Rate Limiting and Throttling
Myxa includes a small request-throttling layer with:
- a shared
RateLimiter - route middleware
- named presets in
config/rate_limit.php - automatic rate-limit headers on
429 Too Many Requestsresponses
In this app, the main entry point is App\Http\Middleware\ThrottleMiddleware.
Quick Example
Use a named preset on a route or route group:
use App\Http\Middleware\ThrottleMiddleware;
use Myxa\Support\Facades\Route;
Route::middleware([ThrottleMiddleware::using('api')], static function (): void {
Route::get('/api/reports', [ReportController::class, 'index']);
});
The skeleton currently ships with these presets:
apiloginuploads
Default Presets
The defaults live in:
config/rate_limit.php
Out of the box they map to:
api:60requests per60secondslogin:5attempts per60secondsuploads:20requests per60seconds
Those values can also be overridden from .env.
Adding A Preset
Add another named preset in config/rate_limit.php:
'presets' => [
'api' => [
'max_attempts' => 60,
'decay_seconds' => 60,
'prefix' => 'api',
],
'admin-reports' => [
'max_attempts' => 15,
'decay_seconds' => 60,
'prefix' => 'admin-reports',
],
],
Then use it on a route:
Route::get('/admin/reports', [AdminReportController::class, 'index'])
->middleware(ThrottleMiddleware::using('admin-reports'));
One-Off Limits
If you need a route-specific limit without creating a preset first, use the framework middleware directly:
use Myxa\Middleware\RateLimitMiddleware;
Route::post('/imports', [ImportController::class, 'store'])
->middleware(RateLimitMiddleware::using(10, 60, 'imports'));
That means:
10attempts- per
60seconds - stored under the
importslimiter prefix
When A Limit Is Hit
When a request exceeds the configured limit:
- the middleware throws
TooManyRequestsException - the app exception handler returns a
429response - the response includes
Retry-After - the response includes
X-RateLimit-Limit - the response includes
X-RateLimit-Remaining - the response includes
X-RateLimit-Reset
That makes the throttling story work for both browsers and APIs.
Store Backends
The rate-limit store is configured in:
config/rate_limit.php
Supported stores in this project:
fileredis
Recommendation:
- use
filefor local development and small single-node apps - use
rediswhen limits must be shared across multiple app nodes
Example production-style env:
RATE_LIMIT_STORE=redis
RATE_LIMIT_REDIS_CONNECTION=default
RATE_LIMIT_REDIS_PREFIX=rate-limit:
Good Defaults In Practice
Some reasonable starting points:
- API reads:
60per minute - login attempts:
5per minute - uploads or expensive writes:
10-20per minute - admin-only heavy exports: much lower, often
5-15per minute
The right values depend on cost, abuse risk, and user experience.