How to secure REST APIs against brute force with Redis
Protect your REST API against brute force attacks by implementing token bucket rate limiting in Redis and dynamic blocking of malicious IPs.
Summary
- The token bucket algorithm allows controlled traffic spikes without penalizing legitimate requests
- Redis ensures millisecond-level atomic counts to prevent race conditions in distributed environments
- Lua scripts executed inside the Redis server reduce network hops and guarantee safe operations
- Dynamic blocking based on consecutive failures isolates suspicious IP addresses automatically
- The combination of fast caching and TTL expiration protects infrastructure without memory leaks
Why REST APIs are easy targets for brute force attacks
Brute force attacks happen when bots test thousands of password combinations or keys within seconds to breach systems. In an open REST API, this consumes precious CPU and database resources, potentially crashing the entire server. In practice, this means that without an intelligent barrier, any web application remains vulnerable to downtime and data theft. To mitigate this issue, we need automated mechanisms that recognize and block abusive behavior before damage occurs.
What is the Token Bucket algorithm and how it works
The token bucket is an elegant mathematical model to control traffic velocity. Imagine a bucket that receives water drops at a constant rate until full; each request spends one drop to pass. If the bucket is empty, the request is rejected or queued until new drops fall. In practice, this allows a legitimate user to make a few quick requests in sequence — such as loading multiple page images — while preventing bots from sending thousands of calls per second. It is a flexible system that differentiates normal traffic spikes from deliberate attacks.
Why use Redis for request rate limiting
Redis is an extremely fast in-memory database, operating with keys and values directly in computer RAM. When we use multiple cloud servers to run an application, storing request tracking in each machine's local memory fails because the data is isolated. In practice, this means Redis acts as a centralized and shared dashboard where all API instances instantly check the token balance. Furthermore, atomic operations prevent concurrent accesses from corrupting allowed counts. For those looking to optimize performance, it is also worth checking how slow NestJS APIs use distributed caching with Redis to understand other uses for this tool.
Implementing Token Bucket with Lua scripts in Redis
To ensure token balance verification and updating occur in a single step without interference, we use Lua scripts executed directly inside Redis. In practice, this prevents parallel requests from reading outdated values while the bucket is being recalculated. Below is a functional example of a Lua script that calculates elapsed time, refills tokens, and safely deducts the current request:
local key = KEYS[1]local capacity = tonumber(ARGV[1])local refill_rate = tonumber(ARGV[2])local now = tonumber(ARGV[3])local requested = tonumber(ARGV[4])local state = redis.call('HMGET', key, 'tokens', 'last_updated')local tokens = tonumber(state[1])local last_updated = tonumber(state[2])if not tokens then tokens = capacity last_updated = nowelse local delta = math.max(0, now - last_updated) tokens = math.min(capacity, tokens + (delta * refill_rate))endlocal allowed = 0if tokens >= requested then tokens = tokens - requested allowed = 1endredis.call('HMSET', key, 'tokens', tokens, 'last_updated', now)redis.call('EXPIRE', key, math.ceil(capacity / refill_rate))return {allowed, tokens}This script runs directly inside the database engine, ensuring maximum speed and total data integrity under high concurrency.
Dynamic blocking strategy for malicious IPs
Simply limiting request volume may not be enough to stop persistent bots that rotate access patterns. The best complementary approach is dynamic blocking, which monitors consecutive failures or repeated token bucket overflows. In practice, if an IP address exceeds the limit three times in under five minutes, our system places that IP into a temporary blocklist for one hour. This saves valuable processing power, as requests coming from there are rejected instantly at the application edge without ever reaching API controllers. To complement this implementation in production environments, see our related technical analyses on How to find short circuits on boards with a thermal camera and How to configure Cron scheduler on Linux without errors.
Final considerations on API resilience and security
Securing a REST API requires combining efficient in-memory architectures, like Redis, with intelligent flow control algorithms and suspicious traffic isolation. Implementing the token bucket perfectly balances legitimate user experience with the necessary rigidity against automated brute force attacks. By adopting these practices, your infrastructure gains operational stability, prevents fraud, and protects sensitive data against constant malicious attempts on the internet.