- Updated: March 18, 2026
- 4 min read
Building a Distributed Token‑Bucket Rate Limiter for the OpenClaw Rating API with Redis Cluster on UBOS
Introduction
In this guide we expand on the single‑instance token‑bucket tutorial and the cross‑region consistency guide to show you how to build a distributed rate limiter for the OpenClaw Rating API using a Redis Cluster deployed across edge regions. The solution runs on UBOS, leverages Redis Cluster for high‑availability, and ensures consistent rate limiting across all edge nodes.
Why a Distributed Token‑Bucket?
- Scalable across multiple edge locations.
- Consistent limits even when traffic is routed to different regions.
- Fault‑tolerant – Redis Cluster handles node failures.
Prerequisites
- UBOS installed on your edge servers.
- Access to a Redis Cluster (3+ master nodes) deployed in the edge regions.
- OpenClaw Rating API source code.
- Basic knowledge of Docker and Kubernetes (optional but recommended).
Architecture Overview
The diagram below illustrates the components:
+-------------------+ +-------------------+ +-------------------+
| Edge Node A | | Edge Node B | | Edge Node C |
| (UBOS + App) | | (UBOS + App) | | (UBOS + App) |
+--------+----------+ +--------+----------+ +--------+----------+
| | |
+-----------+-------------+-------------+-----------+
| |
+-----v-----+ +-----v-----+
| Redis | | Redis |
| Cluster || Cluster |
+-----------+ +-----------+
Step‑by‑Step Implementation
1. Set Up Redis Cluster
- Create three UBOS nodes in different edge regions.
- On each node, install Redis using UBOS package manager:
ubos install redis
- Configure each Redis instance as a cluster node (update
redis.conf):cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes
- Start Redis on all nodes and create the cluster:
redis-cli --cluster create :6379 :6379 :6379 --cluster-replicas 1
2. Add Token‑Bucket Logic
We will use a Lua script executed atomically in Redis to implement the token‑bucket.
-- token_bucket.lua
local key = KEYS[1]
local now = tonumber(ARGV[1])
local capacity = tonumber(ARGV[2])
local refill_rate = tonumber(ARGV[3]) -- tokens per second
local bucket = redis.call('HMGET', key, 'tokens', 'timestamp')
local tokens = tonumber(bucket[1])
local timestamp = tonumber(bucket[2])
if tokens == nil then
tokens = capacity
timestamp = now
else
local elapsed = now - timestamp
tokens = math.min(capacity, tokens + (elapsed * refill_rate))
timestamp = now
end
if tokens < 1 then
redis.call('HMSET', key, 'tokens', tokens, 'timestamp', timestamp)
return 0 -- reject request
else
tokens = tokens - 1
redis.call('HMSET', key, 'tokens', tokens, 'timestamp', timestamp)
return 1 -- allow request
end
3. Integrate with OpenClaw Rating API
Modify the request‑handling middleware to call the Lua script before processing a rating.
const redis = require('ioredis');
const cluster = new redis.Cluster([
{ host: 'redis-node-a', port: 6379 },
{ host: 'redis-node-b', port: 6379 },
{ host: 'redis-node-c', port: 6379 }
]);
const bucketScript = fs.readFileSync('token_bucket.lua', 'utf8');
async function rateLimit(userId) {
const key = `rate:${userId}`;
const now = Math.floor(Date.now() / 1000);
const capacity = 100; // max 100 requests per minute
const refillRate = capacity / 60; // tokens per second
const allowed = await cluster.eval(bucketScript, 1, key, now, capacity, refillRate);
return allowed === 1;
}
app.post('/rating', async (req, res) => {
const userId = req.body.userId;
if (!await rateLimit(userId)) {
return res.status(429).json({ error: 'Rate limit exceeded' });
}
// ... existing rating logic ...
});
4. Deploy on UBOS
- Create a Dockerfile for the API (including the Lua script).
FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . CMD ["node", "server.js"]
- Build and push the image to your registry.
docker build -t registry.example.com/openclaw-rate-limiter:latest . docker push registry.example.com/openclaw-rate-limiter:latest
- Create a UBOS service definition (YAML) that pulls the image and links to the Redis Cluster.
services: openclaw-rate-limiter: image: registry.example.com/openclaw-rate-limiter:latest ports: - "8080:8080" environment: REDIS_NODES: "redis-node-a:6379,redis-node-b:6379,redis-node-c:6379" restart: always - Deploy with UBOS CLI:
ubos deploy -f openclaw-rate-limiter.yml
Testing the Distributed Limiter
Use curl or a load‑testing tool (e.g., k6) to send rapid requests from different edge locations. All nodes should respect the shared limit.
curl -X POST https://api.ubos.tech/rating -d '{"userId":"123","rating":5}' -H "Content-Type: application/json"
Conclusion
By combining a Redis Cluster with a Lua‑based token‑bucket, you obtain a highly available, low‑latency rate limiter that works across edge regions. This approach scales with your traffic and integrates seamlessly with UBOS deployments.
For a full end‑to‑end example of hosting OpenClaw on UBOS, see the OpenClaw hosting guide.