150 requests hammer the endpoint. Exactly 100 sail through. The rest? 429s, stone-cold rejected. No leaks. No mercy.
That’s the live demo of Praise Macaulay’s API Gateway with Abuse Detection — a FastAPI beast that laughs at your garden-variety rate limiter. Tired of tutorials spitting out CRUD apps? This guy’s project screams ‘interview gold’: a full-stack defense system, built from scratch, every line justified. And yeah, it nearly broke him with bugs that’d make pros weep.
But here’s the thing — rate limiting? It’s a joke without this. Fixed windows let attackers burst twice the limit across boundaries. Sliding windows fix it, but only if you’re atomic. Enter Lua scripts in Redis. No races. No exploits.
local key = KEYS[1] local now = tonumber(ARGV[1]) local window = tonumber(ARGV[2]) local limit = tonumber(ARGV[3]) redis.call(‘ZREMRANGEBYSCORE’, key, 0, now - window) local count = redis.call(‘ZCARD’, key) if count < limit then redis.call(‘ZADD’, key, now, now) return 1 – allowed end return 0 – blocked
That’s the script. Executed server-side. Prometheus metrics back it: 200 rejections tallied perfectly, keyed by client_id — not IP, smart move for NAT hellscapes.
Why Your Rate Limiter’s a Sitting Duck
Short answer: timing games. Attackers time bursts perfectly. But this middleware chain — RequestID, Auth, BloomFilter, RateLimit, AbuseDetector, ShadowMode — fails fast. Bloom flags bad IPs or user-agents in O(1), no Redis hop. Skips the rest. Cheap.
Bloom filters? Two of ‘em, in-memory, synced from Redis. One for known-bad IPs, one for scraper agents. 1.1MB RAM for a million entries, 0.1% false positives. Shadow mode logs false alarms first — no accidental bans on grandma’s VPN.
Bugs, though. The killer: per-request Bloom instantiation. Fresh filter every call. Zero detections. Invisible failure. Fixed by app.state sharing. Classic gotcha — should’ve been obvious, but concurrency bites.
Credential stuffing? Dual axes: IP failing many logins, or username hit from many IPs. Independent Redis counters, TTL’d. Thresholds tunable: 10 fails per IP, 20 per user, 300s window. Blocks the source, not the victim.
Does Bot Entropy Actually Catch Scrapers?
Humans jitter. Bots? Clockwork. Track last N timestamps per client in Redis sorted set. Std dev of gaps below 0.5? Bot flag. Doesn’t care about volume — slow, stealthy scrapers still pop. Pairs with UA fingerprinting. Multi-signal win.
Genius for low-volume attacks. But scale? Redis thrashes under millions. That’s my hot take: this indie hero nails the prototype, but prod needs sharding or Kafka streams. Echoes early Cloudflare days — rules before ML hype. Corps’ll rebrand it ‘AI-powered’ by Q2, watch.
Graduated responses rule: throttle first, then block. Shadow mode tests waters. JWT auth extracts client_id, roles. Trace IDs everywhere. Six steps, interdependent. Miss one? Chain breaks.
Live on Render: api-gateway-with-abuse-detection.onrender.com/docs. GitHub: macaulaypraise/api-gateway-with-abuse-detection. Poke it. Abuse it. See 429s fly.
The Sanity-Shredding Bugs That Almost Killed It
Bloom bug first. Then credential races — non-atomic counters let stuffing slip. Lua fixed rates, but auth failures needed pipelining. User-agent sync lagged 60s — background worker desynced under load.
And ShadowMode? Logged blocks but didn’t enforce till flipped. Perfect for tuning without downtime. But flip too soon? Legit users rage-quit.
This ain’t hype. It’s battle-tested grit. Most ‘security’ projects? Vaporware. This? Runs. Explains why. Macaulay’s transition flex — from tutorial drone to backend ninja.
Unique twist: behavioral entropy’s underrated gem. Reminds me of 90s IDS like Snort — signature + anomaly, before everyone chased signatures-only. Prediction? Open-source forks explode for SaaS side-projects. But without Lua atoms, they’ll leak like sieves.
PR spin? None here. Just code. Refreshing. No ‘revolutionary’ fluff.
Why Developers Obsess Over This Now?
APIs bleed cash from bots. Scrapers steal data. Stuffers crack accounts. Basic nginx limits? Child’s play. This scales teachable defense — Redis, FastAPI, Prometheus. Interview bait.
Shared NATs? Client_id saves it. Corporate proxies? Unaffected. Bots mimic humans? Entropy nails ‘em.
Downsides? Memory blooms balloon. Redis hotspots under DDoS. Mitigate with proxies. Still, for solos? Gold.
Production verified: 150 parallels, metrics pure. Envy that.
**
🧬 Related Insights
- Read more: Server Components? Skip ‘Em — Stream React SSR Like It’s 2024
- Read more: Terraform Your First AWS VPC: Escape Networking Hell in Under an Hour
Frequently Asked Questions**
What does an API gateway with abuse detection do?
Sits in front, validates JWTs, rate-limits via sliding windows, flags bad IPs/agents with Blooms, detects stuffing and bot entropy — blocks creeps before they hit your backend.
How does sliding window rate limiting prevent bursts?
Timestamps in Redis sorted sets, atomic Lua cleans old entries, counts live ones — no boundary exploits, concurrent-safe.
Is this API gateway production-ready?
For small-med scale, yes — live demo proves it. Add sharding for big iron.