Scaling Infura: Not All API Calls are Equal

The Infura team continues to grow and scale along with Ethereum itself. As a core infrastructure provider to the public Ethereum networks, the demands on our infrastructure over the last several months have been sizable. Fueled in large part by ERC20 token sale activity and ENS registrations, the main Ethereum network is handling about 400,000 transactions per day. These transactions all arrive into the Ethereum network through a node that relays it eventually to a miner who packages it in a block. Infura is one such gateway that these transactions relay through and find their way into the chain.

Beyond these 400,000 “write” transactions per day, the Ethereum network supporting decentralized application handles many more “read” requests in the form of JSON RPC API calls. Just as with traditional web development, the number of read requests are often orders of magnitude larger than the write requests. Infura is routinely servicing over 600 million of these “read” requests per day. We continue to work on back-end infrastructure to ensure these requests are served lightning fast and reliably.

Not all API Calls are Equal

One of the challenges and learnings we found quickly with our public-facing endpoints was that not all API method calls are equal. For example, eth_blockNumber is pretty lightweight and due to its nature, provides an opportunity to cache given it only changes about every 15.. I mean, 21 seconds (see Ethereum Ice Age).

Now let’s consider eth_getLogs and it’s impact on an Ethereum client. The “getLogs” method has become a very common tool for the Dapp developer to query previous blocks and transactions for data needed to determine current actions. While it has shown to be extremely useful to Dapp developers, the getLogs method is extremely heavy on an Ethereum client and its underlying chaindata database structure.

Imagine a call to search for any arbitrary array of data from block zero to the current block (currently ~4.1 million blocks). In this case, a call to eth_getLogs would initiate a sequential scan of the entire database, bringing that particular node to a crawl for several minutes. It isn’t that difficult to initiate a Denial-of-service attack against an Ethereum node using this technique.

Using Ferryman, the Infura service layer, we are able to automagically route specific method calls to fit-for-purpose client backends. The eth_getLogs method is a perfect use case for bespoke method routing with Ferryman.

When an inbound request comes in making a getLogs request, Ferryman isolates these to a pool of dedicated backend clients running in full archive mode and with specific resource capabilities needed to service the requests. This approach has the primary benefit of preventing our entire service from being negatively impacted due to heavy getLogs requests. A side benefit being that it helps us to optimize costs as we can size our resources more for-purpose.

The Infura team is hard at work identifying use cases such as this to optimize and scale in order to deliver the best possible experience to Dapp developers and users. We remain committed to our strategy to meet the infrastructure demands needed to support the ongoing growth of the Ethereum world computer.

Updated statistics 8/18/17.