How we benchmark RPC performance
Author: Alchemy

Benchmark numbers are easy to quote and easy to misread. That is especially true for RPC performance. One latency chart can hide several different questions: where the request started, which method ran, what payload was sent, what counted as success, how failures were handled, and whether the test measured one RPC call or a full application workflow.
We built our public EVM read benchmark to make those details visible. The goal is to show how providers compare under a controlled, repeatable test setup.
Our benchmark answers how providers compare on common EVM JSON-RPC read methods across selected chains, regions, and time windows.
These are method-level infrastructure benchmarks: one controlled methodology run separately for each method, chain, provider, and region. They measure individual RPC requests, not full application workflows like loading a wallet portfolio, preparing a swap, or polling transaction status across several calls. That distinction matters: method-level results help developers compare provider behavior, but they are not a complete model of any production app.
What is Alchemy's public EVM read benchmark?
Alchemy's public EVM read benchmark is a controlled test that measures how RPC providers respond to configured EVM JSON-RPC read requests. It captures successful-response latency (average, p50, and p95), success rate, and failed-request counts, grouped across providers, chains, methods, regions, and time windows.
We calculate latency only from successful responses. Failed attempts and timeouts are tracked separately, through success rate and failed-request counts. This keeps the benchmark focused on both speed and reliability rather than treating either metric in isolation.
Definitions and measurement rules
The definitions, setup, and rules the rest of this post builds on. Each row is expanded in the sections below.
Concept or rule | What it means |
|---|---|
What the benchmark measures | Successful-response latency (average, p50, p95), success rate, and failed-request counts for configured EVM JSON-RPC read requests. Results are grouped by provider, chain, method, region, and time window. |
JSON-RPC | The standard message format apps use to ask blockchain nodes for data. In plain English, the app sends a structured request like "get this wallet balance" or "return this transaction receipt," and the node sends back a structured answer. |
Method-level benchmark | A test of one configured RPC request with one payload, such as eth_getBalance, eth_getBlockByNumber, eth_getLogs, or eth_getTransactionReceipt. |
What is not measured | Full app workflows, write transactions, customer-specific traffic mixes, first-request connection setup, block freshness, every chain, every provider, and every possible payload shape. |
Request origin | The benchmark runs from controlled AWS ECS regions: US East, US West, EU Central, and AP Southeast. This describes benchmark traffic only, not all Alchemy production traffic. |
Test frequency | Common public EVM read methods run approximately every 10 seconds. |
Success criteria | A request succeeds only if it returns before the 8-second timeout, returns HTTP 2xx, parses as JSON, and does not contain a JSON-RPC error object. |
Latency calculation | Latency is measured only for successful responses. It is runner-side wall-clock time for the measured JSON-RPC POST request and response over a warmed, reused HTTP connection. |
Timeout handling | Timeouts count as failures. They are not inserted into latency calculations as 8,000 ms responses. |
Retries | None. The benchmark makes one attempt. If that attempt fails, the failure is counted. |
Latency with success rate | Latency shows how quickly valid responses return. Success rate shows how often they return successfully at all. |
What does the benchmark cover?
The benchmark covers Ethereum, Optimism, Arbitrum, Base, and World Chain mainnets, and the public provider set includes Alchemy, dRPC, Infura, and QuickNode. We selected these to cover widely used EVM mainnets and the RPC providers developers most often evaluate, with room to expand the set over time. For a given method, every provider receives the same configured JSON-RPC request.
We run each test from controlled AWS ECS regions: US East, US West, EU Central, and AP Southeast. Within a region, every provider is tested from the same runner location, because network distance can change latency. If we tested one provider from Virginia and another from Singapore, the result would tell you as much about geography as about provider performance.
Each result is grouped by:
- Provider
- Chain
- Method
- Region
- Trailing time window
What does the benchmark send to each provider?
A method is the operation being called, like eth_getBalance or eth_getLogs. A payload is the full request we send to exercise that method, including its parameters. The distinction matters because performance depends on both: a cheap lookup and a large range scan place very different load on a provider, and even one method can shift with its inputs.
For a given method, every provider receives the same configured JSON-RPC payload, on a standard paid account. That is the fairness rule: same method, same parameters, same chain, same region, same timeout, same success criteria, and no special treatment for any provider.
Today that means seven configured tests on most chains, and eight on Ethereum:
eth_getBalance: an account balance lookupeth_getBlockByNumberat theearliestblock: a header read at the start of the chaineth_getBlockByNumberat thelatestblock: a header read at the chain headeth_getLogsover a 1-block rangeeth_getLogsover a 10-block rangeeth_getLogsover a 100-block rangeeth_getLogsover a 1,000-block range (Ethereum only)eth_getTransactionReceipt: a single transaction receipt lookup
Some payloads move with the chain. Calls that use the latest block tag, for example, change as the chain advances. Others use fixed historical inputs: the Ethereum eth_getLogs tests use configured historical block ranges for the LINK token contract.
The mix is intentional:
- Fixed inputs make parts of the test repeatable.
- Moving inputs make parts of the test reflect live chain state.
- Fixed historical inputs may be easier for providers to cache.
RPC performance can vary widely depending on method, parameters, block range, response size, cache behavior, and chain state. When reading the benchmark, focus on the method and parameters closest to your own workload.
How is performance measured?
We measure performance through two signals, each answering a different question: latency, how fast successful responses come back (reported as average, p50, and p95), and success rate, how often requests succeed at all (with the failed-request counts behind it).
The two are related but distinct: a fast successful response is not the same as a reliable one. We report them side by side so neither hides the other.
How is latency measured?
Latency is the runner's measured request-and-response time for a successful JSON-RPC HTTP POST. The timer starts when the runner sends the request and stops when it receives the response. If a provider returns a valid response in 120 milliseconds, that request has 120 ms of latency.
We use warmed, reused HTTP connections. In plain English, we are not timing the first setup steps needed to open a new connection, such as DNS lookup, TCP connection setup, or the TLS handshake. The runner primes the connection first, then measures the POST itself over a pooled keep-alive connection.
That brings the latency number closer to repeat application traffic, where clients commonly reuse connections. It also means you should not read these numbers as cold first-request latency.
Only successful responses enter the latency distribution. If a request times out, returns an HTTP error, returns a JSON-RPC error object, fails to parse, or hits a network error, we count it as a failed attempt instead.
Timeouts are not treated as slow 8,000 ms responses. We exclude them from latency and count them in success rate, which keeps latency focused on response speed and success rate focused on reliability.
What is success rate?
Success rate is the share of attempted requests that returned successfully under the benchmark rules: successful requests divided by total attempted requests.
A request counts as successful only if all of the following happen:
- It completes before the benchmark timeout.
- It returns an HTTP 2xx status.
- The response body parses as JSON.
- The JSON-RPC response does not contain a non-null
errorobject.
We do not use retries to hide failed attempts. One attempted request gets one chance. If it fails, that failure is counted.
How does the benchmark handle timeouts?
The benchmark runner waits up to 8 seconds for each provider to return a valid response. If no valid response comes back in time, we record the attempt as a timeout failure.
The 8-second cutoff is part of our test setup. It is not set by the chain, and it is not whatever timeout a provider may use internally.
The 8-second cutoff applies to all the public EVM read methods today. A specific method could be configured with a different timeout, but none currently is.
What counts as a failed request?
We track failed attempts separately from latency. A request is counted as a failure if it:
- returns a non-2xx HTTP status, such as 403, 429, 500, 502, 503, or 504
- returns a JSON-RPC error object
- times out after 8 seconds
- fails at the network level, or
- fails to parse as valid JSON
Rate-limit responses count as failures, and we never use retries to convert failed attempts into successful ones. Each failure lowers the provider's success rate and adds to its failed-request count for that method, chain, region, and window.
How are the metrics defined?
Metric | Technical definition | Plain-English meaning | Important caveat |
|---|---|---|---|
Average latency | Sum of successful response times divided by count of successful responses. | On successful calls, how long did the provider take on average? | Excludes failures, so it must be read with success rate. |
p50 latency | Median latency across successful responses in the same provider, chain, method, region, and window group. | The typical successful response time. | Can hide slower tail behavior. |
p95 latency | The latency point where 95% of successful responses were faster and 5% were slower. | How slow successful requests get outside the normal case. | Timeouts are not included as 8-second samples; they count as failures. |
Success rate | Successful requests divided by total attempted requests. | How often the provider returned successfully under the test rules. | The reliability companion to latency. |
Failed requests | Count of attempts that did not meet the success criteria. | How many requests failed. | Shown as counts per method; the flip side of success rate. |
Why report latency and success rate together?
Fast responses only matter when responses actually come back. A provider can show low latency on the requests that succeed while timing out or failing more often, so we report latency alongside success rate: latency shows how quickly valid responses return, success rate shows how often they return at all.
For example, if we send 1,000 attempts and 990 return successfully before the 8-second timeout, the success rate is 99%. The 10 failed attempts do not enter p50, p95, or average latency; they show up as reliability failures.
That prevents two misreads: a provider with low latency but more failures should not be judged on speed alone, and a provider with a high success rate but slower tail latency should not be judged on reliability alone.
Why does the benchmark use a trailing window?
The benchmark runs continuously. Common public EVM read methods run roughly every 10 seconds, and we refresh the public benchmark page every 5 minutes from a trailing 24-hour window.
At full uptime, a method that runs every 10 seconds produces about 8,640 attempts per provider, method, network, and region each day. A trailing 24-hour window gives each public number enough samples to smooth over one-off blips while keeping the page fresh.
So read the public page as a rolling daily summary, not a single request, a one-time test, or one momentary snapshot.
What does the benchmark not measure?
Today, the benchmark measures warm, single-method read performance under controlled conditions. It does not measure:
- Multi-call user flows
- Write transactions or transaction submission
- WebSocket or subscription behavior
- Customer-specific request mixes
- Cold first-request connection setup
- Every provider, chain, region, method, or payload shape
- The exact behavior of your own architecture, traffic level, or deployment geography
That boundary is what makes the benchmark useful: it tells you where the numbers apply and where you should run your own workload-specific tests.
Speed and reliability are related but separate questions:
- Speed asks how quickly successful requests return.
- Reliability asks how often requests return successfully.
We designed the benchmark to show that distinction rather than flatten it into one "fastest provider" claim.
How should developers use the results?
Use the public benchmark as a starting point for provider evaluation. A practical reading pattern:
- Pick the chain and method closest to your workload.
- Compare the region that best matches where your users or infrastructure sit.
- Look at p95, not just average or p50.
- Check success rate beside latency.
- If your workload uses different payloads, higher concurrency, writes, WebSockets, or multi-call flows, run a workload-specific benchmark before deciding.
Transparent benchmarks help you ask better questions. They make it easier to see what was tested, what was counted, what was excluded, and which parts of the result matter most for a real application.
Frequently asked questions
What is Alchemy's public EVM read benchmark?
It is a controlled test that measures how RPC providers handle common EVM JSON-RPC read requests. It records successful-response latency (average, p50, p95), success rate, and failed-request counts across selected providers, chains, methods, and regions, letting developers compare providers under identical, repeatable conditions rather than marketing claims.
How is RPC latency measured?
Latency is the runner's wall-clock time for one JSON-RPC POST and its response over a warmed, reused connection. The timer starts when the request is sent and stops when a valid response arrives. Only successful responses count, so latency reflects response speed, not connection setup or failures.
What counts as a successful request?
A request succeeds only if it returns within the 8-second timeout, returns an HTTP 2xx status, parses as JSON, and contains no JSON-RPC error object. Anything else, including timeouts, HTTP errors, and rate-limit responses, is counted as a failed attempt and excluded from latency.
How does the benchmark handle timeouts?
The runner waits up to 8 seconds for a valid response. If none arrives, the attempt is recorded as a timeout failure, not as a slow 8,000 ms response. Timeouts lower success rate but never inflate latency, which keeps speed and reliability as separate measurements.
Does the benchmark use retries?
No. Each measurement is a single attempt. If that attempt fails, the failure is counted rather than retried away. This keeps success rate honest, since retries would hide the intermittent failures that real applications actually experience.
Which chains and providers does the benchmark include?
The public benchmark covers Ethereum, Optimism, Arbitrum, Base, and World Chain mainnets. The provider set includes Alchemy, dRPC, Infura, and QuickNode. Each provider receives the same configured request for a given method, from the same region, under the same timeout and success rules.
Which RPC methods does the benchmark test?
The benchmark runs seven configured read tests, built from four EVM methods: eth_getBalance; eth_getBlockByNumber at the earliest and latest blocks; eth_getLogs over 1-, 10-, and 100-block ranges; and eth_getTransactionReceipt. Ethereum adds a 1,000-block eth_getLogs test, for eight. Each uses a fixed payload, so results stay comparable across providers.
What does the benchmark not measure?
It does not measure full application workflows, write transactions, WebSocket subscriptions, customer-specific traffic mixes, or cold connection setup. It also does not cover every chain, provider, region, method, or payload. For those cases, run a workload-specific benchmark that matches your own traffic.
How should I read a p95 latency number?
Read p95 as: for this method, chain, region, and time window, 95% of successful responses were at least this fast. It exposes tail behavior the average hides. Always read it beside success rate, since fast responses only matter when responses actually return.
Alchemy Newsletter
Be the first to know about releases
Sign up for our newsletter
Get the latest product updates and resources from Alchemy
By entering your email address, you agree to receive our marketing communications and product updates. You acknowledge that Alchemy processes the information we receive in accordance with our Privacy Notice. You can unsubscribe anytime.
Related articles

12 things you can do faster with the Alchemy CLI
The Alchemy CLI turns every onchain workflow into one command: auth, agent wallets, multi-chain reads, sends, swaps, bridges, and AI agent integrations.

What are agent payments? How AI agents pay for APIs, data, and compute
Agent payments let AI agents pay for what they need — APIs, data, compute — autonomously and within limits. Learn how they work and why they matter for real agentic workflows.

AI agent crypto glossary: x402, ACP, and MCP and 20 more terms
A plain-language glossary of the terms you need to follow agentic crypto — from x402 and MCP to spend limits, account abstraction, and more.