How to Set Up Rate Limiting on Your Own RPC Node
Rate limiting your own RPC node means configuring it to reject or throttle requests that exceed a threshold you define. You do this to protect the node from overload, abusive traffic, or simply to enforce fair use if you share the endpoint with others. The setup is not a single switch; it depends on which client you run and what sits in front of it.
The core idea is straightforward: your node has finite CPU, memory, and network capacity. Without limits, one heavy user or a misbehaving script can starve everyone else. Rate limiting lets you trade a small amount of complexity for predictable behaviour under load.
Why your node needs limits
Public RPC endpoints are frequently scraped, hammered by bots, or used in ways that resemble denial-of-service attacks - even when unintentional. A typical Ethereum execution client like Geth or Erigon will happily process any request you send it. That is the problem. A single eth_getLogs call with a wide block range can tie up resources for seconds, blocking simpler calls like eth_blockNumber for everyone.
You also want to protect yourself from yourself. If you run a public-facing node and you haven't limited it, you are effectively offering free compute to anyone who finds the port. That is how people end up with a node that is perpetually behind, or worse, a server that is constantly out of memory.
The two levels of rate limiting
There are two places you can apply limits: at the application level (inside the client) and at the network level (in a reverse proxy or firewall). Most production setups use both.
Application-Level limits in geth
Geth has built-in flags for this. The relevant ones are:
--rpc.rate-limit- sets the number of requests per second allowed from a single IP (default is unlimited).--rpc.rate-limit-burst- allows a short burst above the sustained rate (default is 1.5 times the rate limit).--rpc.max-batch-requests- caps how many individual calls can be bundled into a single JSON-RPC batch request.
You start Geth with these flags, for example:
geth --rpc --rpc.rate-limit 100 --rpc.rate-limit-burst 150
This allows 100 requests per second per IP, with a burst of 150. Requests beyond that get an HTTP 429 response. That is the same error you likely researched when your own calls failed against a public endpoint.
Erigon has similar flags but with different names. Check your client’s --help output for terms like rpc.rate-limit or http.rpc.rate-limit. The exact syntax changes between versions, so verify what your installed binary supports.
Network-Level Limits with a Reverse Proxy
Application-level limits only apply to the client itself. They do not stop a flood of connections from exhausting your server’s socket table, nor do they give you fine-grained control over which endpoints are expensive. For that, you put a reverse proxy in front of the node.
Common choices are Nginx, Caddy, or HAProxy. The general pattern is the same:
- Run your node on localhost (e.g., port 8545) with no external exposure.
- Configure the proxy to listen on port 443 (HTTPS) or 8545 externally.
- Apply per-IP limits at the proxy level.
A minimal Nginx configuration for this looks like:
http {
limit_req_zone $binary_remote_addr zone=rpc_limit:10m rate=10r/s;
server {
listen 443 ssl;
server_name rpc.yourdomain.com;
location / {
limit_req zone=rpc_limit burst=20 nodelay;
proxy_pass http://127.0.0.1:8545;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
This limits each IP to 10 requests per second, with a burst of 20. The nodelay flag means excess requests are rejected immediately rather than queued. You can tune the numbers based on your node’s capacity and your expected user base.
What to limit beyond raw request count
Not all requests are equal. A eth_call that simulates a complex contract interaction is far more expensive than a simple eth_blockNumber. If you only limit by request count, a user can still harm you by sending fewer, heavier calls.
Consider limiting by:
- Block range size for
eth_getLogsand similar. Many clients have a--rpc.max-log-rangeflag or equivalent. Set it to something sane like 1000 or 5000 blocks. - Response size. Some proxies can inspect response headers and reject or truncate large responses.
- Concurrency. A user can open many parallel connections. Proxy-level
limit_conndirectives in Nginx, or equivalent in HAProxy, stop that.
The right mix depends on what your node serves. If it is a personal node, a simple rate limit is probably enough. If you are publishing an endpoint for others, spend time on the heavier limits.
Testing Your Configuration
After you have set limits, test them. Use a tool like ab (Apache Bench) or a simple script that fires many requests in a loop. You want to see HTTP 429 responses when you exceed the threshold, and normal responses when you stay under it.
A quick test with curl in a loop:
for i in $(seq 1 200); do
curl -s -o /dev/null -w "%{http_code}\n" \
-X POST http://localhost:8545 \
-H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
done | sort | uniq -c
This fires 200 requests and counts the HTTP status codes. You should see a mix of 200s and 429s once you pass the limit. If you see only 200s, your limit is too high or not applied.
When not to bother
If your node is for personal use on a private network, skip this entirely. A rate limit adds complexity and can occasionally reject your own legitimate requests if you misconfigure it. The point is to protect shared or public infrastructure.
If you are running a node solely to sync and serve your own wallet through a local connection, the risk of abuse is low. You can always add limits later if you expose the node to the internet.
A practical starting point
For a modest public node, begin with these numbers:
- 100 requests per second per IP at the application level.
- 10 requests per second per IP at the proxy level, with a burst of 20.
- A block range cap of 5000 for
eth_getLogs.
Run the node for a week, watch the logs for 429s, and adjust. If you see many rejected requests from a single IP, that IP is either a heavy user or a bot - decide which and act accordingly. If you see no 429s at all, your limits are probably too generous.
Rate limiting is not a one-time setup. It is a tuning exercise that follows your usage patterns. Start strict, loosen up if needed, and keep an eye on the metrics.
Not financial advice. starname.me publishes market data and general information about digital assets. Crypto assets are volatile and you can lose everything you put in. Nothing here is a recommendation to buy, sell or hold, and we make no price predictions.
Prices are sourced from third parties and may be delayed or wrong. Verify anything you intend to act on against a primary source.