Use Redis atomic operations to count requests per key and time window.
The examples focus on the operation itself, including the important distinction: A process-local PHP counter does not coordinate workers.
What It Does
Use the examples below to observe the behavior on a small dataset before extending it to application code.
Before You Start
Read the input requirements before applying this pattern to production data.
Example 1: Basic Use
The Lua script combines increment and first-time TTL atomically. This is a fixed-window limiter, not a sliding window.
<?php
$redis = new Redis();
$redis->connect(getenv("REDIS_HOST") ?: "127.0.0.1", 6379);
$key = "limit:user:3";
$script = "local n = redis.call('INCR', KEYS[1]); if n == 1 then redis.call('EXPIRE', KEYS[1], ARGV[1]) end; return n";
$attempts = $redis->eval($script, [$key, 60], 1);
echo $attempts <= 20 ? "allowed" : "rate limited";
This example is meant for a configured application environment; output depends on the installed extension, external service, or database contents.
Example 2: Checking Behavior
The Lua script combines increment and first-time TTL atomically. This is a fixed-window limiter, not a sliding window.
<?php
$redis = new Redis();
$redis->connect(getenv("REDIS_HOST") ?: "127.0.0.1", 6379);
$key = "limit:user:8";
$script = "local n = redis.call('INCR', KEYS[1]); if n == 1 then redis.call('EXPIRE', KEYS[1], ARGV[1]) end; return n";
$attempts = $redis->eval($script, [$key, 60], 1);
echo $attempts <= 20 ? "allowed" : "rate limited";
This example is meant for a configured application environment; output depends on the installed extension, external service, or database contents.
Example 3: Practical Example
The Lua script combines increment and first-time TTL atomically. This is a fixed-window limiter, not a sliding window.
<?php
$redis = new Redis();
$redis->connect(getenv("REDIS_HOST") ?: "127.0.0.1", 6379);
$key = "limit:user:21";
$script = "local n = redis.call('INCR', KEYS[1]); if n == 1 then redis.call('EXPIRE', KEYS[1], ARGV[1]) end; return n";
$attempts = $redis->eval($script, [$key, 60], 1);
echo $attempts <= 20 ? "allowed" : "rate limited";
This example is meant for a configured application environment; output depends on the installed extension, external service, or database contents.
Important Behavior and Edge Cases
Set expiry atomically or in a transaction/script so counters cannot be left without TTL; handle Redis failures sensibly.
Comparison with Related Approaches
| Approach | Difference |
|---|---|
| Creating a Rate Limiter with Redis and PHP | Use Redis atomic operations to count requests per key and time window. |
| Related API or alternative | A process-local PHP counter does not coordinate workers. |
Common Beginner Mistakes
| Mistake | Correct approach |
|---|---|
| Ignoring the operation-specific limits | Set expiry atomically or in a transaction/script so counters cannot be left without TTL; handle Redis failures sensibly. |
| Confusing it with a related API | A process-local PHP counter does not coordinate workers. |
Key Takeaways
- Use Redis atomic operations to count requests per key and time window.
- Set expiry atomically or in a transaction/script so counters cannot be left without TTL; handle Redis failures sensibly.
- A process-local PHP counter does not coordinate workers.
Use Creating a Rate Limiter with Redis and PHP when its documented behavior matches the problem. Test the relevant edge cases in your own runtime before deploying it.