Hey everyone,
One of the... "joys" of a fresh reformat is rediscovering all the background noise. After getting my dev machine back up, I noticed a significant and immediate increase in web traffic aimed at my Hive Engine node.
Unfortunately, a quick look at the logs showed it was 99% garbage traffic: bots, web scrapers, and spiders endlessly hitting the API. I've shared my Fail2ban setup with you before, which is great for blocking malicious actors, but this new traffic was technically "valid." The bots were making legitimate API calls, just a lot of them. This meant they weren't getting banned, but they were causing a noticeable drop in my home network's bandwidth.
I needed a way to slow down this torrent of calls without unfairly penalizing legitimate users. The perfect solution is rate limiting, so I rebuilt Caddy, my reverse proxy, with the caddy-ratelimit plugin.

Building Caddy with Rate Limiting
Building Caddy with new plugins is straightforward using xcaddy:
xcaddy build --with github.com/mholt/caddy-ratelimit --output caddy
cp caddy /usr/local/bin/caddy
The New Caddyfile Configuration
After replacing my Caddy binary, I updated the configuration. I realized the first limit I tried was far too strict for an API, so I immediately adjusted it to be a bit more generous for legitimate, high-speed use.
Here is the final Caddyfile I put into production:
(rotating-log) {
log {
output file {args[0]} {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
}
}
engine.thecrazygm.com {
encode zstd gzip
import rotating-log /var/log/caddy/engine.log
rate_limit {
zone per_client_ip {
key {remote_host}
events 60 # 60 requests allowed in each window
window 5s
burst 20 # extra burst length
# Transparent header so the app knows it’s rate‑limited
header X-Rate-Limit-Remaining
header X-Rate-Limit-Limit
header X-Rate-Limit-Reset
}
}
reverse_proxy localhost:5000
}
The rate_limit block in the engine.thecrazygm.com section is where the magic happens:
key {remote_host}: This uses the remote IP address as the check to filter forevents 60andwindow 5s: This sets a limit of 60 requests per client IP within a 5-second window. This is a very permissive setting, ensuring any human or properly coded application has plenty of room to operate.burst 20: This adds a 20-request buffer, allowing for sudden spikes in traffic (like an initial data load) without immediately hitting the limit.header X-Rate-Limit-Remaining: I added these directives to pass rate limit information back to the client. This allows any developer using the node to see their current limits and write their applications responsibly.
This setup is working beautifully. It has tamed the constant barrage of garbage bot traffic while ensuring the node remains fully usable for anyone making a legitimate, reasonable number of calls.
As always,
Michael Garcia a.k.a. TheCrazyGM