Skip to content
0%

The Cortex router: how we pick the fastest healthy node for every request

Author: Uttam Singh

Last updated: August 6, 20268 min read
The Cortex router: how we pick the fastest healthy node for every request

Every RPC call your app makes has to reach a node and come back before your user sees anything. Getting that call to a nearby region is something every serious provider does automatically, us included, and we keep opening regions to shorten that first hop further. The more interesting question is what happens after it lands: which specific node in that region answers, and whether anything checked that the node was healthy and caught up to the chain before the request went there.

That second decision is the one we make fresh on every request, and it is a large part of why our average response time across EVM chains is under 15ms. That figure is warm request-and-response time, measured over a connection that is already open, which is what repeat traffic from a running app looks like. It leaves out DNS, connection setup, and the TLS handshake, so the edge work below sits outside that number rather than inside it.

What does the Cortex router actually decide?

Cortex is the engine powering the whole Alchemy platform, from the node fleet up through the routing layer to the RPC and Data APIs on top. The earlier setup put a third-party CDN in front of the traffic, which made that CDN a single point of failure for every network and every customer at once. Replacing it with bare metal we run ourselves removed that dependency and put the whole path under our own operation. Every request you send passes through Cortex now, and the router is the part that decides where a given request goes.

For each request, the router picks the path: which region accepts it, which node serves it, and what happens if that node degrades mid-flight. "Best route to your chain" really means the lowest-latency healthy node that can answer this particular call correctly, right now. That answer changes by the second as load and health shift, which is why we recompute it per request rather than resolving it once and reusing the result.

The regional half of that is now standard across the industry. A request from Singapore and one from Frankfurt will enter at different places on any major provider, and none of them make you configure it. What we add is the second decision, made per request rather than per connection: of the nodes available in the region a request landed in, which one is healthy, current, and suited to this particular call.

Cortex router architecture: a request enters at the nearest edge region, the control plane selects a healthy serving stack, and the gateway in front of the fleet picks the node

How does a request reach the right region?

Geo-based DNS resolves the endpoint to the nearest edge region, so a request enters the system close to where it originates instead of all traffic landing in one place. This happens before the router looks at a single node, because distance to the front door is pure round-trip time you can never win back. Connection setup and TLS negotiation happen there too, at the closest point rather than deep in the stack.

That front door is our own Alchemy Edge Proxy, a bare-metal ingress layer we run instead of a third-party CDN. Rolling it out was one of the largest latency wins of the rebuild. P99 in Asia-Pacific went from 150ms to 20ms, and P95 across all networks roughly halved, from about 200ms to about 100ms. Those are the before-and-after of that migration rather than where the numbers sit today, and P95 and P99 are the slowest 5% and 1% of requests, which is the part users actually feel. The edge is one layer of a broader push on latency that runs from predictive scaling through to fleet automation.

How do we pick the node inside a region?

Two layers do different jobs here. At the edge, the control plane looks at which serving stacks support the network you asked for and which of those are healthy, then sends the request to the closest one. But choosing a node happens a layer deeper, in the gateway in front of the fleet. That gateway is the first thing in the path that knows anything about individual machines.

Picking a node well takes more than picking a close one, so several things narrow the candidate list before anything is forwarded.

  • Health, from live tracking. A node-tracking system runs continuous health checks, and a node that fails them is not a candidate. This is what keeps a degraded backend from being chosen in the first place, rather than being discovered by your users.
  • Agreement on current state. Nodes do not all sit at the same block, so handing a read to whichever one is quickest can return state the chain has already moved past. A consistency layer keeps requests on the same canonical view of the chain regardless of which node serves them, and versioned updates mean you do not hit a stale read even while a failover is in progress.
  • Observed latency, not just geography. Candidates are scored on an exponentially weighted moving average of their recent measured latency, the same approach load balancers have used for years. Because older samples decay out of the average, a node that started slowing down minutes ago falls down the ranking on its own, without anyone raising an alert.
  • Workload shape. Node clients differ in sync behavior and in which methods they serve well, and archival and full nodes hold different data, so the method and params on the request narrow the pool further. A heavy historical query and a simple balance read do not belong on the same node.

So "lowest latency" is never a setting we switch on somewhere. It gets recomputed for every call, out of where that call came in, what it is asking for, and which machines happen to be fast and healthy right then.

What happens when the chosen node is not healthy?

Failover is part of the routing decision rather than an alarm bolted on beside it. When a node goes down, Cortex reroutes traffic to healthy ones automatically. The more interesting case is the node that has not failed outright but is congested, lagging, or running a client version with a known bug, and the same context-aware routing steers around those too. Your application does not see an error, and there is no retry logic here for you to write.

The same holds a level up. If a whole region is degraded, requests route to a secondary one, and there is a further fallback behind that. Real-time global replication keeps every region consistent through those transitions, so ending up on a farther region does not mean reading older data.

Shuffle sharding and redundant node pools sit underneath all of this, keeping failures isolated and contained rather than letting one problem spread across the fleet. The routing layer treats a degraded node as a path to avoid, which is the same fault tolerance behind our zero-downtime Solana gRPC streaming and the fleet that stayed up through the biggest liquidation event in crypto.

Why does owning the edge make routing smarter?

RPC traffic is mostly dynamic. An eth_call or a transaction submission can't be cached the way a static image can, so a generic CDN's main trick, serving cached content near the user, mostly doesn't apply, and the request still has to reach a live node. Owning the edge instead of renting a CDN lets us tune it for this specific traffic shape, and lets routing use signals a third-party layer never sees, like which node is synced, healthy, and fastest for this method and chain right now.

It also means we are not sharing that layer with unrelated traffic. On a shared CDN, an incident that has nothing to do with your app can still surface as your latency spike, and the fix is on someone else's schedule.

Where providers actually diverge is everything below the region, because that is where a routing layer either knows what each machine is doing or it is guessing.

Approach
How a request gets routed
What the routing layer knows

Brokered across third-party operators

A balancer scores independent operators and forwards each request to one of them

Health and latency as the operators expose it, at endpoint level rather than node level

Own fleet, geo-routed and then selected per request (Cortex)

A single endpoint resolves to the nearest healthy serving stack for that network, and the gateway in front of the fleet picks the node

Every node's health, whether it agrees with the current state of the chain, recent measured latency, and which client it runs

We run it ourselves because it is the only way no segment of the route belongs to someone else. We pay real engineering cost for that, and in exchange we can tune the whole path rather than filing a ticket with whoever owns the slow part.

What does this mean for a chain like Base?

Base is a good stress test, because the chain itself is fast. It ships 200ms incremental block updates through Flashblocks, so an RPC path that takes longer than that to answer becomes the bottleneck rather than the chain. A Base call from any region enters at the nearest edge, gets matched to a healthy Base node that is current with the chain, and reroutes within the region if that node degrades. Removing a hundred milliseconds of network overhead matters more, not less, when the chain previews new state every 200ms.

Consistency is the harder guarantee, and it is the one worth judging us on. Polymarket is the stress case. Through the 2024 US elections they ran over 125,000 concurrent users and $3.3 billion in bets, with requests dynamically rerouted on p99 latency to hold performance up. Their critical ingestion workflows separately sped up 2.5x, from roughly 250ms to roughly 100ms. A median measured in one region on a quiet afternoon tells you almost nothing about what your users get during a mint or a liquidation cascade. If you'd rather check than take our word for it, our benchmark methodology measures latency alongside success rate and failed requests, and the provider benchmarks are public.

Build on the same routing path

Every app on Alchemy already routes through this engine, with nothing to configure. Spin up a free RPC endpoint and your reads and writes take the same per-request path described here. No contract, no waitlist, no endpoint change. Your Data API calls run on it too.

If you need a node pinned to one region, single-tenant isolation, or a custom binary on the path, Alchemy Dedicated Clusters run the same routing on single-tenant hardware, and you can opt in to automatic failover to the shared fleet if traffic outgrows the cluster's capacity. Either way, the request behind your app is the part you stop thinking about.

Frequently asked questions

Which RPC provider delivers the lowest latency across global regions?

Alchemy's average response time across EVM chains is under 15ms on our continuously updated benchmarks, measured as warm request-and-response time on an already-open connection. That page recomputes every few minutes, so read the current provider ranking off it. Uptime is 99.995%. Every serious provider routes you to a nearby region. Cortex goes further inside that region, matching each request to a node checked for health and for agreement on the current state of the chain.

Which RPC provider supports Base RPC with the lowest latency?

Base RPC on Alchemy enters at the nearest edge region, then gets matched to a healthy Base node that is current with the chain. That matters more on Base than on slower chains, because Flashblocks push block updates every 200ms, so a node even slightly behind can return state that has already changed.

How does Cortex choose which node serves an RPC request?

Two layers share the work. The edge control plane picks the closest healthy serving stack that supports the network requested, and the gateway in front of the fleet then picks the node, narrowing candidates by health, agreement on the current state of the chain, recently observed latency, and the method being called.

Does per-request routing add latency?

Routing is a small slice of the response budget rather than the headline figure. The sub-15ms figure is warm request-and-response time across EVM chains, not the cost of the routing decision itself, and not the same measurement as the platform-wide sub-50ms average across all chains and products. Region selection happens at the edge, close to the user, and node selection happens deeper in, at the gateway that fronts the fleet.

What happens when an RPC node fails?

Failover is part of the routing decision rather than a retry you build yourself. Cortex reroutes traffic to healthy nodes automatically when one goes down, and its context-aware routing also steers around nodes that are congested, lagging, or running a buggy client. If a whole region degrades, requests move to a secondary region, with real-time replication keeping the data consistent.

Alchemy Newsletter

Be the first to know about releases

Sign up for our newsletter

Get the latest product updates and resources from Alchemy

A
O
D
+
Over 80,000 subscribers

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.