PHP code example of colinmollenhour / rate-limiter
1. Go to this page and download the library: Download colinmollenhour/rate-limiter library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
colinmollenhour / rate-limiter example snippets
use Cm\RateLimiter\RateLimiterFactory;
use Credis_Client;
$redis = new Credis_Client('127.0.0.1', 6379);
$factory = new RateLimiterFactory($redis);
// Choose your algorithm
$rateLimiter = $factory->createSlidingWindow(); // or createFixedWindow(), createLeakyBucket(), createGCRA(), createTokenBucket()
// Rate limit: 10 burst capacity, 1 request/second sustained, 60 second window
$result = $rateLimiter->attempt('user:123', 10, 1.0, 60);
if ($result->successful()) {
echo "Request allowed. {$result->retriesLeft} requests remaining";
} else {
echo "Rate limited. Try again in {$result->retryAfter} seconds";
}
// GCRA + concurrency control
$limiter = $factory->createConcurrencyAware('gcra');
// Token bucket + concurrency control
$limiter = $factory->createConcurrencyAware('token');
// Pure concurrency limiting (no rate limiting)
$limiter = $factory->createConcurrencyAware(null);
// Pure rate limiting (no concurrency control)
$limiter = $factory->createGCRA(); // or any other algorithm
// Web API Protection (GCRA for performance + concurrency for slow queries)
$limiter = $factory->createConcurrencyAware('gcra');
$result = $limiter->attemptWithConcurrency('api:search', $requestId, 5, 20, 1.0, 60, 30);
// File Upload Service (Token bucket for bursts + concurrency for upload congestion)
$limiter = $factory->createConcurrencyAware('token');
$result = $limiter->attemptWithConcurrency('upload:user:'.$userId, $requestId, 2, 5, 0.5, 3600, 300);
// Background Job Processing (Pure concurrency for resource control)
$limiter = $factory->createConcurrencyAware(null);
$result = $limiter->attemptWithConcurrency('jobs:heavy', $jobId, 3, 0, 0, 0, 1800);
$factory->createSlidingWindow(); // Smooth rate limiting
$factory->createFixedWindow(); // Window-based with burst
$factory->createLeakyBucket(); // Bucket capacity with leak
$factory->createGCRA(); // Memory-efficient smooth limiting
$factory->createTokenBucket(); // Perfect burst + sustained rate
$factory->createConcurrencyAware('gcra'); // GCRA + concurrency control
$factory->createConcurrencyAware(null); // Pure concurrency limiting
$slidingWindow = new \Cm\RateLimiter\SlidingWindow\RateLimiter($redis);
$fixedWindow = new \Cm\RateLimiter\FixedWindow\RateLimiter($redis);
$leakyBucket = new \Cm\RateLimiter\LeakyBucket\RateLimiter($redis);
$gcra = new \Cm\RateLimiter\GCRA\RateLimiter($redis);
$tokenBucket = new \Cm\RateLimiter\TokenBucket\RateLimiter($redis);
$concurrencyAware = new \Cm\RateLimiter\ConcurrencyAware\RateLimiter($redis, $tokenBucket);
class RateLimiterResult {
public function successful(): bool; // Was the request allowed?
public int $retryAfter; // Seconds until next request allowed
public int $retriesLeft; // Requests remaining in current window
public int $limit; // Total limit (burst capacity)
}
class ConcurrencyAwareResult extends RateLimiterResult {
public bool $concurrencyAcquired; // Was concurrency slot acquired?
public ?string $concurrencyRejectionReason; // Why was concurrency rejected?
public int $currentConcurrency; // Current concurrent requests
public int $maxConcurrency; // Maximum allowed concurrent requests
public function rejectedByConcurrency(): bool; // Was blocked by concurrency limit?
public function rejectedByRateLimit(): bool; // Was blocked by rate limit?
}
// Perfect for APIs with bursty traffic AND slow backend operations
$limiter = $factory->createConcurrencyAware('token');
$requestId = uniqid('req_', true);
$result = $limiter->attemptWithConcurrency(
key: "api:upload:{$userId}",
requestId: $requestId,
maxConcurrent: 3, // Max 3 concurrent uploads per user
burstCapacity: 10, // Allow 10 uploads immediately
sustainedRate: 2.0, // Then 2 uploads/second sustained
window: 60, // 60-second rate limit window
timeoutSeconds: 300 // 5-minute timeout for slow uploads
);
if ($result->successful()) {
try {
// Process file upload - guaranteed max 3 concurrent + 2/s rate
processFileUpload($file);
} finally {
// Always release concurrency slot when done
$limiter->releaseConcurrency("api:upload:{$userId}", $requestId);
}
} elseif ($result->rejectedByConcurrency()) {
// Too many concurrent uploads - don't count against rate limit
http_response_code(503);
echo "Too many concurrent uploads. Try again shortly.";
} else {
// Rate limit exceeded
http_response_code(429);
header("Retry-After: " . $result->retryAfter);
echo "Upload rate limit exceeded. Try again in {$result->retryAfter} seconds.";
}
// Perfect for resource-intensive operations like database migrations or heavy processing
$limiter = $factory->createConcurrencyAware(null); // null = no rate limiting
$jobId = uniqid('job_', true);
$result = $limiter->attemptWithConcurrency(
key: 'jobs:heavy-processing',
requestId: $jobId,
maxConcurrent: 2, // Only 2 heavy jobs at once
burstCapacity: 0, // No rate limiting
sustainedRate: 0, // No rate limiting
window: 0, // No rate limiting
timeoutSeconds: 1800 // 30-minute timeout for long jobs
);
if ($result->successful()) {
try {
// Process heavy job - guaranteed max 2 concurrent, no rate limits
processHeavyJob($jobData);
} finally {
$limiter->releaseConcurrency('jobs:heavy-processing', $jobId);
}
} else {
// Only concurrency rejection possible (no rate limiting)
echo "Too many concurrent jobs. Current: {$result->currentConcurrency}/{$result->maxConcurrency}";
}
$slidingWindow = $factory->createSlidingWindow();
// Smooth 100 requests per hour (no bursts)
$result = $slidingWindow->attempt("user:{$id}", 100, 100.0/3600, 3600);