RPC reliability for Web3 apps that cannot go down

May 26, 20264 min readBy Harman Kamboj
Web3Engineering

Almost every Web3 outage I have been paged for traced back to the same thing, and it was never the smart contract. It was the RPC layer. The node provider had a bad afternoon, rate limits kicked in during a traffic spike, or a single endpoint silently started returning stale data. Web3 RPC reliability is the unglamorous foundation everything else sits on, and it is the part teams think about last. That order is backwards.

Your RPC is a dependency, treat it like one

A contract on chain is about as reliable as software gets. But your app does not talk to the chain directly. It talks to an RPC node, usually one you rent from a provider, and that node is a normal piece of internet infrastructure with all the normal failure modes. It goes down, it gets slow, it rate limits you, it occasionally lies about the latest block. If you wire your whole app to one endpoint, you have built a single point of failure in front of the most reliable thing in your stack.

The first shift in thinking is to stop treating the RPC URL as a constant and start treating it as a fallible service you depend on. The moment you see it that way, the engineering follows naturally, because you already know how to build around flaky dependencies.

Multiple providers, always

I never ship production with a single RPC provider. I configure at least two from different companies, because the failure that takes down one provider often does not touch another. The app tries the primary, and on failure or timeout it falls through to the secondary. This is not exotic, it is the same failover pattern you would use for any external service, applied to the one external service Web3 apps cannot live without.

The detail that trips people up is what counts as failure. A connection error is obvious. Harder cases are a node that responds quickly but returns a block number several blocks behind, or one that returns an empty result for a query that should have data. Those need health checks that go beyond is it up, into is it telling me the truth and is it current.

Retries that help instead of hurt

Naive retries make outages worse. The moment a provider gets slow, a retry storm from your app piles on more load and pushes it fully over. The retry logic I use has a few non-negotiable properties.

  • Exponential backoff with jitter, so a thousand clients do not all retry on the same tick and hammer the recovering node
  • A hard cap on attempts, infinite retries just convert a brief blip into a permanent hang
  • Only retry idempotent reads freely, a transaction send needs careful handling so you do not broadcast twice
  • Fail over to the next provider after a couple of failed attempts rather than retrying the same dead endpoint forever

That last point is the one that actually saves you during a real incident. Retrying the same broken endpoint is just waiting politely for something that is not coming back. Moving to a healthy provider is what keeps the app responsive.

Reads and writes are different problems

Reads are easy to make reliable because they are idempotent. Ask any healthy node, get the answer, done. Writes are where reliability gets genuinely hard. If you send a transaction and the connection drops before you get a hash, did it go through. Resending blindly risks a double submission, and on chain that can mean spending money twice.

The pattern that works is to track the transaction by nonce and check chain state before resending, rather than trusting the network round trip. If a transaction with that nonce already landed, you are done and you must not send again. This is fiddly, it is worth getting right once and wrapping in a helper, because the alternative is users who occasionally get charged twice and rightly never trust you again.

Watch the layer everyone ignores

You cannot fix what you cannot see. I put metrics on the RPC layer specifically: latency per provider, error rate per provider, how far behind the latest block each one is, and how often failover triggers. When a provider starts degrading, those numbers move well before users notice, which gives you room to switch primaries or open a support ticket before it becomes an outage.

None of this is glamorous and none of it ships a feature. But a Web3 app that cannot stay up is not really a product, and the thing that most often takes it down is the RPC layer nobody planned for. Plan for it. Two providers, sane retries, careful writes, and real metrics will keep you online through the bad afternoons that are coming whether you prepared or not.

Building something where this matters?

I am open to senior full-stack, Web3, or AI engineering roles, fully remote and any timezone. If the hard part of your product is fighting you, that is the work I like.

Get in touch →