php
58 lines · 8 steps
A fixed-window rate limiter on APCu
A small PHP class counts requests per key in shared memory and resets the count after a fixed time window.
Explained by
highlit
1<?php
2
3namespace App\Security;
4
5use RuntimeException;
6
7final class ApcuRateLimiter
8{
9 public function __construct(
10 private readonly int $limit = 60,
11 private readonly int $window = 60,
12 private readonly string $prefix = 'ratelimit:'
13 ) {
14 if (!\function_exists('apcu_inc')) {
15 throw new RuntimeException('APCu extension is not available.');
16 }
17 }
18
19 public function attempt(string $key): bool
20 {
21 return $this->hits($key) <= $this->limit;
22 }
23
24 public function hits(string $key): int
25 {
26 $bucket = $this->prefix . $key;
27 $success = false;
28 $count = apcu_inc($bucket, 1, $success);
29
30 if (!$success || $count === 1) {
31 apcu_store($bucket, 1, $this->window);
32 return 1;
33 }
34
35 return $count;
36 }
37
38 public function remaining(string $key): int
39 {
40 $current = (int) apcu_fetch($this->prefix . $key);
41 return max(0, $this->limit - $current);
42 }
43
44 public function retryAfter(string $key): int
45 {
46 $info = apcu_key_info($this->prefix . $key);
47 if ($info === null) {
48 return 0;
49 }
50 $expiresAt = $info['creation_time'] + $info['ttl'];
51 return max(0, $expiresAt - time());
52 }
53
54 public function clear(string $key): void
55 {
56 apcu_delete($this->prefix . $key);
57 }
58}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1An atomic increment is the heart of a rate limiter — it lets concurrent requests share one counter without races.
- 2The fixed-window scheme is implemented by attaching a TTL only when the counter first appears, so it expires and resets automatically.
- 3Separating attempt, remaining, and retryAfter gives callers everything they need to enforce limits and build informative responses.
Related explainers
php
<?php namespace App\Support;
Locale-aware formatting with PHP's intl extension
internationalization
encapsulation
constructor-injection
Intermediate
7 steps
php
<?php namespace App\Support;
Merging query params onto a URL in PHP
url-parsing
query-strings
immutability
Intermediate
8 steps
php
<?php class ImageUploadService {
Validating file uploads safely in PHP
file-upload
input-validation
security
Intermediate
8 steps
python
import time from collections import defaultdict from threading import Lock
Sliding-window login rate limiting in Flask
rate-limiting
sliding-window
thread-safety
Intermediate
7 steps
javascript
const RATE_LIMIT = 100; const WINDOW_MS = 60 * 1000; const BLOCK_MS = 5 * 60 * 1000;
Building a rate-limiting middleware in Express
rate-limiting
middleware
closures
Intermediate
9 steps
php
<?php namespace App\View;
Building a safe HTML escaper in PHP
security
xss
escaping
Intermediate
6 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/a-fixed-window-rate-limiter-on-apcu-explained-php-7cab/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.