Rate Limiting & Token-Bucket Algorithm
Understand Shortyy continuous token-bucket rate limiting, burst capacities, refill intervals, and HTTP 429 response handling.
Rate Limiting & Token-Bucket Algorithm
Shortyy implements a continuous Token-Bucket Rate Limiter powered by atomic Redis Lua scripts. Unlike traditional fixed-window limiters that cause artificial request spikes and lockouts at the boundary of an hour, the token-bucket allows natural burst traffic while continuously replenishing quota every second.
Token-Bucket Algorithm
Every API key has a virtual "bucket" with a maximum capacity $C$ and a continuous refill rate $R$ tokens per second:
POST /v1/links) consumes 1 token.HTTP 429 Too Many Requests accompanied by exact retryAfterSeconds.Plan Capacities & Refill Rates
| Channel / Tier | Burst Capacity ($C$) | Refill Rate ($R$) | Refill Interval | Max Link Expiration | Equivalent Sustained Rate | |
|---|---|---|---|---|---|---|
| Guest (Homepage) | 4 tokens | 1 token / 15 sec | 15 seconds | 1 hour | 240 links / hour (4/min) | |
| Free Developer (SDK & API) | 4 tokens | 1 token / 75 sec | 75 seconds | 3 hours (SDK) | 24 hours (Web) | 48 links / hour |
| Basic | 20 tokens | 1 token / 5 sec | 5 seconds | 100 years | 720 links / hour | |
| Pro | 100 tokens | 5 tokens / 1 sec | 0.2 seconds | 100 years | 18,000 links / hour | |
| Enterprise | Custom | Custom | Sub-second | 100 years | Dedicated throughput |
>
Standard Response Headers
Every API response returns standard, authoritative rate limit headers:
| Header | Description | Example |
|---|---|---|
X-RateLimit-Limit | The maximum token capacity for the authenticated tier | 4 |
X-RateLimit-Remaining | Current remaining tokens available right now | 3 |
X-RateLimit-Reset | UTC timestamp (in seconds) when the bucket will be completely full | 1763040120 |
Retry-After | Present on 429 responses: seconds to wait before trying again | 15 |
Handling HTTP 429 Responses
When your bucket is exhausted, the API returns HTTP 429 Too Many Requests with both the standard Retry-After header and the typed retryAfterSeconds JSON field:
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "That's four links already. Give us 15 seconds and try again.",
"status": 429,
"retryAfterSeconds": 15
}
}Always pause your worker or display a live countdown for retryAfterSeconds before sending another creation request. Avoid automatic blind retries without delay.