spb/ultra-sharp-agent-skills Public
Ultra-Sharp Agent Skills — a research-first skill-authoring system + 72 production-ready skills for AI agents.
Python 100%
1<!--2Author: Simon-Pierre Boucher3Contact: contact@spboucher.ai4-->56# Patterns — Rate Limiting78## Contents9- Token bucket in Redis (atomic)10- Response headers11- Cost-weighted limits12- Local fallback13- Penalty escalation14- Load shedding15- Gotchas1617## Token bucket in Redis (atomic)1819```lua20-- KEYS[1]=bucket key ARGV: rate_per_s, burst, now_ms, cost21-- Returns {allowed(0/1), remaining, retry_after_s}22local rate, burst = tonumber(ARGV[1]), tonumber(ARGV[2])23local now, cost = tonumber(ARGV[3]), tonumber(ARGV[4])24local b = redis.call('HMGET', KEYS[1], 'tokens', 'ts')25local tokens = tonumber(b[1]) or burst26local ts = tonumber(b[2]) or now27tokens = math.min(burst, tokens + (now - ts) / 1000 * rate)28local allowed = tokens >= cost and 1 or 029if allowed == 1 then tokens = tokens - cost end30redis.call('HMSET', KEYS[1], 'tokens', tokens, 'ts', now)31redis.call('PEXPIRE', KEYS[1], math.ceil(burst / rate * 2000)) -- self-clean idle keys32local retry = allowed == 1 and 0 or math.ceil((cost - tokens) / rate)33return {allowed, math.floor(tokens), retry}34```3536```python37allowed, remaining, retry = redis.evalsha(38 SHA, 1, f"rl:{api_key}:{cls}", RATE, BURST, now_ms(), cost)39```4041One Lua call = read-modify-write with no race; never split GET/SET42across the network.4344## Response headers4546```python47def limit_headers(limit, remaining, reset_epoch):48 return {49 "X-RateLimit-Limit": str(limit),50 "X-RateLimit-Remaining": str(max(0, remaining)),51 "X-RateLimit-Reset": str(reset_epoch),52 }5354# On rejection add:55# Retry-After: <seconds> and body: {"error": "rate_limited", "retry_after": n}56```5758Send the X-RateLimit-* trio on 200s too — clients pace themselves only if59they can see the meter.6061## Cost-weighted limits6263```python64COSTS = { # units per call; base=1. Weigh by measured backend cost.65 "search": 10, # fans out to the search cluster66 "export": 25, # long-running, memory heavy67 "read": 1,68 "health": 0, # never throttle probes69}70cost = COSTS.get(endpoint_class, 1)71```7273## Local fallback7475```python76NODE_SHARE = RATE // max(node_count(), 1) # conservative split when Redis is down7778def check(key, cost):79 try:80 return redis_bucket(key, cost)81 except RedisError:82 if key_route_is_sensitive(key): # login/signup/reset/payment83 return REJECT # fail-closed84 return local_bucket(key, cost, rate=NODE_SHARE) # fail-open, degraded85```8687## Penalty escalation8889```python90# Repeat offenders get exponentially longer cool-downs.91strikes = redis.incr(f"rl:strikes:{api_key}")92redis.expire(f"rl:strikes:{api_key}", 3600)93if strikes > 3:94 penalty = min(2 ** (strikes - 3) * 60, 3600) # 1min → 1h cap95 redis.setex(f"rl:block:{api_key}", penalty, "1")96```9798## Load shedding99100```python101QUEUE_DEPTH_MAX = 100 # ≈ p99 concurrency × safety factor 2102def middleware(request):103 if executor.queue_depth() > QUEUE_DEPTH_MAX:104 return Response(503, headers={"Retry-After": "5"})105 ...106```107108Shed at the cheapest point in the stack (edge/middleware), before auth and109DB work — the point of shedding is to spend nothing on rejected requests.110111## Gotchas112113- **Fixed windows double-dose at boundaries**: 100/min allows 200 requests114 in the 2 s straddling the minute mark; token bucket doesn't.115- **Limiting after authentication** spends a DB call on every rejected116 request — put coarse anti-abuse limits before auth, fine per-user limits117 after.118- **`Retry-After: 0`** (rounding down) makes clients hammer instantly;119 always `ceil`.120- **One bucket for reads and writes** lets a read storm starve writes;121 split classes.122- **Missing `PEXPIRE` on buckets** leaks a key per client forever.123- **Health checks and load-balancer probes** must bypass limits or the LB124 will mark healthy nodes dead during an attack — exactly when you need them.125