php
46 lines · 7 steps
How a token bucket rate limiter works
A token bucket smooths request bursts by refilling credits over time and blocking callers until enough tokens are available.
Explained by
highlit
1final class TokenBucketLimiter
2{
3 private float $tokens;
4 private float $lastRefill;
5
6 public function __construct(
7 private readonly float $capacity,
8 private readonly float $refillPerSecond
9 ) {
10 $this->tokens = $capacity;
11 $this->lastRefill = microtime(true);
12 }
13
14 public function acquire(float $cost = 1.0): void
15 {
16 if ($cost > $this->capacity) {
17 throw new InvalidArgumentException('Cost exceeds bucket capacity');
18 }
19
20 while (true) {
21 $this->refill();
22
23 if ($this->tokens >= $cost) {
24 $this->tokens -= $cost;
25 return;
26 }
27
28 $deficit = $cost - $this->tokens;
29 $waitSeconds = $deficit / $this->refillPerSecond;
30 usleep((int) ceil($waitSeconds * 1_000_000));
31 }
32 }
33
34 private function refill(): void
35 {
36 $now = microtime(true);
37 $elapsed = $now - $this->lastRefill;
38
39 if ($elapsed <= 0) {
40 return;
41 }
42
43 $this->tokens = min($this->capacity, $this->tokens + $elapsed * $this->refillPerSecond);
44 $this->lastRefill = $now;
45 }
46}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1A token bucket allows short bursts up to capacity while enforcing a steady average rate over time.
- 2Refilling lazily from elapsed time avoids running a background timer to add tokens.
- 3Computing the wait from the exact token deficit lets a blocked caller sleep just long enough instead of busy-polling.
Related explainers
php
<?php declare(strict_types=1);
Normalizing human names in PHP
unicode
text-normalization
transliteration
Intermediate
8 steps
php
<?php namespace App\Http\Controllers;
Handling Stripe webhooks in Laravel
webhooks
signature-verification
dependency-injection
Intermediate
7 steps
go
package handler type flightResult struct { status int
Deduping in-flight requests in Gin
middleware
concurrency
deduplication
Advanced
9 steps
php
<?php namespace App\FeatureFlags;
How a feature flag evaluator decides
feature-flags
rollout
hashing
Intermediate
8 steps
go
package middleware import ( "net/http"
Per-IP write rate limiting in Gin
rate-limiting
middleware
concurrency
Intermediate
8 steps
python
import asyncio from dataclasses import dataclass import aiohttp
Bounded-concurrency HTTP fetching with asyncio
async
concurrency
semaphore
Intermediate
8 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/how-a-token-bucket-rate-limiter-works-explained-php-2aad/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.