Rate Limits
The public OXN RPC endpoint applies rate limits to prevent abuse and ensure availability for all users. This page documents what those limits are and how to handle them.
Limits
Rate limits apply per source IP address. Concrete numbers may change; contact the team via Support for the current guidance.
Rough current limits (subject to change):
- Standard JSON-RPC requests: several requests per second per IP.
- Batch requests: limited batch size (25 requests per batch as a rule of thumb).
- WebSocket subscriptions: limited number of concurrent connections per IP; limited subscriptions per connection.
- Heavy calls (
eth_getLogswith wide ranges): consume multiple quota units. debug_*methods: may be disabled entirely under load.
Behavior on limit exceeded
When you exceed the rate limit, the server returns:
HTTP/1.1 429 Too Many Requests
Retry-After: N
Where N is the number of seconds to wait before retrying. Well-behaved clients should:
- Respect the
Retry-Afterheader. - Implement exponential backoff for repeated failures.
- Not immediately retry — that just wastes both sides' resources.
Example handling in ethers.js:
import { ethers } from "ethers";
async function withRetry(fn, maxAttempts = 5) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await fn();
} catch (err) {
if (err.code !== 429) throw err;
const wait = Math.min(1000 * 2 ** attempt, 30_000);
console.log(`Rate limited. Waiting ${wait}ms`);
await new Promise((r) => setTimeout(r, wait));
}
}
throw new Error("Rate limited too many times");
}
// Usage
const balance = await withRetry(() => provider.getBalance(addr));
Requesting increased limits
If your integration genuinely needs more headroom than the default allows, contact the team through the Support channels. Include:
- What you're building.
- Your expected request rate (per second, per hour).
- Which methods you use most heavily.
- Whether you can run your own node instead.
Elevated limits are granted on a case-by-case basis for legitimate applications.
Alternatives to hitting the public endpoint hard
Before pushing the limits, consider:
-
Cache read results locally. Chain state does not change more than once per block. If you're calling
eth_getBalancerepeatedly for the same address within a block, cache the result. -
Batch multiple queries into one request. See JSON-RPC Overview for batch format.
-
Subscribe to events instead of polling. Use WebSocket
newHeadsandlogssubscriptions instead of pollingeth_blockNumberin a tight loop. -
Run your own node. For sustained high traffic, hosting your own RPC node is more reliable and predictable than the public endpoint. See Running a Read-Only RPC Node.
Monitoring your usage
The public endpoint does not currently expose per-user usage counters. You can measure your own request rate client-side:
let requestCount = 0;
provider._perform_orig = provider._perform;
provider._perform = function(...args) {
requestCount++;
return this._perform_orig(...args);
};
setInterval(() => {
console.log("Requests in last minute:", requestCount);
requestCount = 0;
}, 60_000);
Next steps
- JSON-RPC Overview — for batch and other optimization patterns
- Public RPC Endpoints — availability and general policy
- Running a Read-Only RPC Node — if you need more capacity