Proxy Rate Limiting
Per-IP rate limiting using a sliding window. Counts requests in 1-second windows; returns HTTP 429 when exceeded. For distributed rate limiting across multiple proxy instances, use nyx-kv INCR + EXPIRE.
Code
// nyx-proxy rate limiting — per-IP sliding window
// Rate limiting nyx-proxy — ventana deslizante por IP
var ip_counts: Map = Map.new()
var window_start: Map = Map.new()
fn now_seconds() -> int {
return time()
}
// Check if an IP has exceeded the rate limit
// Returns true if allowed, false if rate-limited
fn rate_check(ip: String, max_per_sec: int) -> bool {
let now: int = now_seconds()
// Initialize window if new IP
if not ip_counts.contains(ip) {
ip_counts.insert(ip, "1")
window_start.insert(ip, int_to_string(now))
return true
}
// Reset window if more than 1 second elapsed
let start_s: String = window_start.get(ip)
let start: int = string_to_int(start_s)
if now - start >= 1 {
ip_counts.insert(ip, "1")
window_start.insert(ip, int_to_string(now))
return true
}
// Increment count
let count_s: String = ip_counts.get(ip)
let count: int = string_to_int(count_s) + 1
ip_counts.insert(ip, int_to_string(count))
return count <= max_per_sec
}
fn main() -> int {
let max_rps: int = 5 // allow 5 requests per second per IP
let ip: String = "192.168.1.100"
// Simulate 8 rapid requests from the same IP
var i: int = 0
while i < 8 {
let ok: bool = rate_check(ip, max_rps)
if ok {
print("request " + int_to_string(i + 1) + ": ALLOWED")
} else {
print("request " + int_to_string(i + 1) + ": 429 Too Many Requests")
}
i = i + 1
}
return 0
}
Output
request 1: ALLOWED request 2: ALLOWED request 3: ALLOWED request 4: ALLOWED request 5: ALLOWED request 6: 429 Too Many Requests request 7: 429 Too Many Requests request 8: 429 Too Many Requests
Explanation
Rate limiting is the first line of defense against both abuse and runaway clients. The fixed-window counter here is the simplest implementation: for each IP, remember when its window started and how many requests have arrived; reset the counter on every new second. It's not perfect — a client hitting the boundary can burst 2x the limit — but it's cheap and good enough for most proxies. In a multi-instance deployment the counters drift because each instance sees only its own traffic; the fix is to keep counts in nyx-kv with INCR + EXPIRE so all instances share one view. For stricter fairness, the token bucket or true sliding window are next steps up.