
On this page
01 Why crawlers need their own limits
A crawler differs from a user in the way that matters to capacity: it walks the long tail. People concentrate on a few popular pages that stay in cache. A crawler requests every archive page, tag listing and paginated view, most of them cold, so each request lands on the origin. Ten requests a second from one crawler can cost more origin CPU than a thousand users. This procedure belongs to the load balancing hub and assumes you already know which crawlers you accept, from measuring and verifying crawler traffic.
02 Token bucket and leaky bucket
A token bucket holds up to B tokens and refills at R tokens per second. Each request spends one; with the bucket empty, the request is refused. It allows a burst of B, then a sustained rate of R, which suits crawlers that fetch a sitemap and then pause. A leaky bucket queues requests and releases them at a fixed rate R; the queue depth is the burst allowance. It smooths traffic into the origin but adds latency to queued requests. Many proxy implementations use leaky bucket semantics with an optional burst that is served immediately rather than delayed, which behaves much like a token bucket.
| Client key | Catches | Collateral risk |
|---|---|---|
| Verified crawler identity | One named crawler across all its addresses | None if verification is correct |
| Single address (/32 or /128) | A single noisy host | Corporate and carrier NAT users |
| IPv4 /24 or IPv6 /48 | A crawler spread over one allocation | Neighbours in shared hosting |
| Origin AS | A fleet across many prefixes | Every customer of a large provider |
| Fingerprint plus address | Unverified bots rotating user-agents | Proxies that share a fingerprint |
03 Procedure
Cache before you limit
Set cache lifetimes on the balancer or proxy for pages that tolerate them, and serve stale content while revalidating. A cache hit costs the origin nothing, and most crawler load vanishes once deep pages are cacheable for even a few minutes.
Classify the client
Tag each request as verified crawler, claimed but unverified crawler, suspected bot or other. Use DNS or published-range verification for the first, and fingerprint and behaviour scoring for the third. The class selects the bucket.
Choose the key and bucket
Key verified crawlers on their identity, other clients on address or prefix. Size rate R from what the origin can serve uncached, and burst B from what a well-behaved crawler does after reading a sitemap.
Refuse correctly
Return
429 Too Many Requestswith aRetry-Aftervalue in seconds. Compliant crawlers back off. Keep503for genuine origin overload, because some crawlers read repeated 503s as the site being down and change how they schedule it.Protect health checks and the origin
Exempt the balancer's own health checks and your monitoring addresses from every limit, and apply limits in front of the real server pool, never on the path the balancer uses to test it. A limiter that fails health checks takes servers out of rotation and turns a crawler problem into an outage.
Log and review
Log key, class, rule, bucket level and decision for every refused request and a sample of passed ones. Review weekly: rising 429s to a verified crawler mean the limit is too tight or the cache too cold.
04 Illustrative config shape
The shape below uses generic open-source reverse proxy syntax with leaky bucket semantics. A map chooses the key: verified crawlers share a key per identity, everyone else is keyed on address. It is a sketch, not a drop-in configuration.
map $crawler_class $limit_key {
verified $crawler_name;
default $binary_remote_addr;
}
limit_req_zone $limit_key zone=crawl:10m rate=5r/s;
limit_req_status 429;
server {
listen 443 ssl;
server_name www.example.com;
location = /healthz { limit_req off; }
location / {
limit_req zone=crawl burst=20 nodelay;
error_page 429 = @throttled;
# hand off to the real server pool here
}
location @throttled {
add_header Retry-After 30 always;
return 429;
}
}05 Where the limiter sits
Put it at the first device that terminates HTTP, usually a Layer 7 balancer or reverse proxy, because it needs the user-agent and path. A Layer 4 device can only limit connections per address, which is blunt. Keep limiter state local to each balancer unless the pair shares it; two units each allowing 5 requests a second allow 10 in total. That matters under persistence rules that pin a crawler to one unit, and it matters in reverse when they do not. Watch the effect on volume by prefix with sampled flow data after each change.
Do not rate limit robots.txt and sitemaps harder than pages. A crawler that cannot read your rules cannot obey them.
Rate limits are the last line. Before them, caching rules that absorb crawler requests remove most repeat load, and a written AI crawler policy decides who is limited at all.
06 Questions
Should crawlers get 429 or 503 when they exceed a limit?
429 Too Many Requests with Retry-After. It says the client is the problem and when to return. 503 says the server is the problem; use it only for real overload, since crawlers may treat repeated 503s as downtime.
What is the difference between a token bucket and a leaky bucket?
A token bucket allows a burst up to its size, then a steady rate. A leaky bucket queues requests and releases them at a steady rate, adding delay instead of refusing. Proxies that serve the burst immediately behave much like a token bucket.
Is limiting by /24 safe?
Safe enough for unverified bots on hosting ranges, risky on residential or corporate networks where one /24 holds many unrelated users. Prefer verified identity for known crawlers and single addresses elsewhere.
Why is caching called the cheapest rate limiter?
A cache hit is served without touching the origin, so crawler requests for cacheable pages cost almost nothing. Tuning cache lifetimes often removes more origin load than any limit and never refuses a legitimate client.
How do I stop rate limits from breaking health checks?
Exempt the health check path and the balancer and monitoring source addresses from every limit rule, and test by watching pool member state while you load the limiter.