Back to skills
extension
Category: Development & EngineeringNo API key required

acc-create-rate-limiter

Generates Rate Limiter pattern for PHP 8.5. Creates request throttling with token bucket, sliding window, and fixed window algorithms. Includes unit tests.

personAuthor: jakexiaohubgithub

Rate Limiter Generator

Creates Rate Limiter pattern infrastructure for request throttling and API protection.

When to Use

| Scenario | Example | |----------|---------| | API protection | Prevent abuse | | Resource throttling | Database connection limits | | Fair usage | Per-user request limits | | Burst protection | Spike handling |

Component Characteristics

RateLimiterInterface

  • Common interface for all algorithms
  • Check and consume methods
  • Remaining capacity queries

Algorithms

  • Token Bucket: Smooth rate limiting with burst capacity
  • Sliding Window: Time-based with sliding window log
  • Fixed Window: Simple time-based counter

RateLimitResult

  • Contains allowed/denied status
  • Provides retry-after information
  • Generates HTTP headers

Generation Process

Step 1: Generate Core Components

Path: src/Infrastructure/Resilience/RateLimiter/

  1. RateLimiterInterface.php — Common interface
  2. RateLimitResult.php — Result value object with headers
  3. RateLimitExceededException.php — Exception with retry info
  4. StorageInterface.php — Storage abstraction

Step 2: Choose and Generate Algorithm

Choose based on use case:

  1. TokenBucketRateLimiter.php — For APIs with burst allowance
  2. SlidingWindowRateLimiter.php — For strict per-time limits
  3. FixedWindowRateLimiter.php — For simple rate limiting

Step 3: Generate Storage

  1. RedisStorage.php — Production storage with TTL

Step 4: Generate Tests

  1. {Algorithm}RateLimiterTest.php — Algorithm tests
  2. RateLimitResultTest.php — Result value object tests

File Placement

| Component | Path | |-----------|------| | All Classes | src/Infrastructure/Resilience/RateLimiter/ | | Unit Tests | tests/Unit/Infrastructure/Resilience/RateLimiter/ |


Naming Conventions

| Component | Pattern | Example | |-----------|---------|---------| | Interface | RateLimiterInterface | RateLimiterInterface | | Token Bucket | TokenBucketRateLimiter | TokenBucketRateLimiter | | Sliding Window | SlidingWindowRateLimiter | SlidingWindowRateLimiter | | Fixed Window | FixedWindowRateLimiter | FixedWindowRateLimiter | | Result | RateLimitResult | RateLimitResult | | Exception | RateLimitExceededException | RateLimitExceededException | | Test | {ClassName}Test | TokenBucketRateLimiterTest |


Quick Template Reference

RateLimiterInterface

interface RateLimiterInterface
{
    public function attempt(string $key, int $tokens = 1): RateLimitResult;
    public function getRemainingTokens(string $key): int;
    public function getRetryAfter(string $key): ?int;
    public function reset(string $key): void;
}

RateLimitResult

final readonly class RateLimitResult
{
    public static function allowed(int $remaining, int $limit, \DateTimeImmutable $resetsAt): self;
    public static function denied(int $limit, int $retryAfter, \DateTimeImmutable $resetsAt): self;
    public function isAllowed(): bool;
    public function isDenied(): bool;
    public function toHeaders(): array; // X-RateLimit-* headers
}

Usage Example

// Create limiter
$limiter = new TokenBucketRateLimiter(
    capacity: 100,
    refillRate: 10.0, // 10 tokens per second
    clock: $clock,
    storage: new RedisStorage($redis)
);

// Check limit
$result = $limiter->attempt('user:123');

if ($result->isDenied()) {
    throw new RateLimitExceededException(
        key: 'user:123',
        limit: $result->limit,
        retryAfterSeconds: $result->retryAfterSeconds
    );
}

// Add headers to response
foreach ($result->toHeaders() as $name => $value) {
    $response = $response->withHeader($name, (string) $value);
}

Algorithm Comparison

| Algorithm | Burst Handling | Memory | Precision | Use Case | |-----------|----------------|--------|-----------|----------| | Token Bucket | Good (configurable) | Low | Medium | APIs with burst allowance | | Sliding Window | Limited | High | High | Strict per-time limits | | Fixed Window | Poor (boundary issues) | Low | Low | Simple rate limiting |


Anti-patterns to Avoid

| Anti-pattern | Problem | Solution | |--------------|---------|----------| | No Redis/Shared Storage | Per-instance limits | Use shared storage | | Missing Headers | Client can't adapt | Return X-RateLimit-* headers | | Single Algorithm | Doesn't fit all cases | Choose per use case | | No Retry-After | Client spams | Always return retry timing | | Synchronous Blocking | Thread blocking | Use non-blocking check |


References

For complete PHP templates and examples, see:

  • references/templates.md — All algorithm implementations
  • references/examples.md — Middleware example and tests