RateLimit Adapters
RateLimit stores counters through one adapter per configured backend.
Use the file adapter when you want a local default with no extra service. Use the Redis adapter when rate limits must be shared across multiple PHP processes or servers.
Configure the default adapter
RateLimiterFactory reads config/rate_limit.php and uses rate_limit.default when you do not request an adapter explicitly.
A typical config looks like this:
return [
'default' => env('RATE_LIMIT_ADAPTER', 'file'),
'file' => [
'path' => base_dir() . DS . 'cache' . DS . 'data',
'ttl' => 60,
'prefix' => 'api-rate-limit:',
],
'redis' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'port' => env('REDIS_PORT', 6379),
'ttl' => 60,
'prefix' => 'api-rate-limit:',
],
];
File adapter
FileRateLimitAdapter stores one JSON state file per rate-limit key and uses a lock file to serialize updates.
Use it when the app runs on one machine or when each node can keep its own independent limits.
Required config
path- directory used for.rateand.lockfilesttl- lifetime used only when you manually reset to a non-zero countprefix- optional namespace added before hashing the key
What it guarantees
- The storage directory is created if it does not exist.
- Each hit stores
countandreset_at. - When the window expires, the next hit starts a fresh counter.
retryAfter()returns0when the state file is missing or unreadable.
Caveats
- File limits are local to the filesystem backing
path. - If the adapter cannot open or lock its state file,
hit()returnsfalse. - Stored filenames are hashed, so inspecting the directory is useful for operations, not for human-readable debugging.
Redis adapter
RedisRateLimitAdapter stores each counter as one Redis key.
Use it when multiple workers or servers must share the same limits.
Required config
hostportttl- lifetime used only when you manually reset to a non-zero countprefix- optional string prepended directly to the runtime key
What it guarantees
- The first hit creates the key and sets its expiry to the route interval.
- Later hits increment the same key until the key expires.
retryAfter()returns the Redis TTL in seconds, or0when Redis reports no usable expiry.
Caveats
- The adapter only configures host and port. Authentication, database selection, and other Redis options are not part of this package contract.
prefixis stored directly in Redis key names, unlike the file adapter where it only affects the hashed filename.- Redis client errors are surfaced by the Redis client, so handle them in your app-level exception flow.
Shared adapter behavior
Both built-in adapters support the same runtime contract:
hit($key, $limit, $interval)increments and reports whether the request is still allowedreset($key)clears the counterreset($key, $count)seeds the counter and uses the adapter configttl, not the route intervalretryAfter($key)returns seconds until reset, or0
Unsupported adapters
The factory only ships file and redis.
Passing any other adapter name to RateLimiterFactory::get(...) throws RateLimitException::adapterNotSupported(...).